From 231d810c91c60723bfe1d83af83fced8560a9389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 17 Feb 2024 23:02:27 +0100 Subject: [PATCH 01/38] Compatibility with core#2492 Migrate Analysis Profiles to Dexterity https://github.com/senaite/senaite.core/pull/2492 --- src/senaite/ast/adapters/configure.zcml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/senaite/ast/adapters/configure.zcml b/src/senaite/ast/adapters/configure.zcml index e5870ca..df979c8 100644 --- a/src/senaite/ast/adapters/configure.zcml +++ b/src/senaite/ast/adapters/configure.zcml @@ -23,8 +23,8 @@ AST-like analyses are always added manually afterwards, based on the result oif the "Microorganism Identification" analysis --> From 2514ffe0895781c9a40ac6122a99b67b4a998b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 17 Feb 2024 23:49:54 +0100 Subject: [PATCH 02/38] Use getRawServices and setServices properly when removing ASTs --- src/senaite/ast/upgrade/v01_00_000.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/senaite/ast/upgrade/v01_00_000.py b/src/senaite/ast/upgrade/v01_00_000.py index 76ef321..94c1ce5 100644 --- a/src/senaite/ast/upgrade/v01_00_000.py +++ b/src/senaite/ast/upgrade/v01_00_000.py @@ -152,9 +152,9 @@ def remove_ast_from_profiles(portal): brains = api.search(query, SETUP_CATALOG) for brain in brains: obj = api.get_object(brain) - services = obj.getRawService() or [] - services = filter(lambda s: s not in ast_uids, services) - obj.setService(services) + services = obj.getRawServices() or [] + services = filter(lambda s: s.get("uid") not in ast_uids, services) + obj.setServices(services) logger.info("Removing AST-like analyses from profiles [DONE]") From 2f255182dd837eb47fa82d79cf7886cc7263a94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 17 Feb 2024 23:52:19 +0100 Subject: [PATCH 03/38] simplify --- src/senaite/ast/upgrade/v01_00_000.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/senaite/ast/upgrade/v01_00_000.py b/src/senaite/ast/upgrade/v01_00_000.py index 94c1ce5..175377c 100644 --- a/src/senaite/ast/upgrade/v01_00_000.py +++ b/src/senaite/ast/upgrade/v01_00_000.py @@ -146,12 +146,8 @@ def remove_ast_from_profiles(portal): """ logger.info("Removing AST-like analyses from profiles ...") ast_uids = get_ast_services_uids(portal) - query = { - "portal_type": "AnalysisProfile" - } - brains = api.search(query, SETUP_CATALOG) - for brain in brains: - obj = api.get_object(brain) + profiles = portal.setup.analysisprofiles.objectValues() + for obj in profiles: services = obj.getRawServices() or [] services = filter(lambda s: s.get("uid") not in ast_uids, services) obj.setServices(services) From d91c072e5d838cce8ebf8512d26119f4ad9cee63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 17 Feb 2024 23:55:49 +0100 Subject: [PATCH 04/38] Changelog --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 9626b19..672cde6 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,7 @@ Changelog 1.2.0 (unreleased) ------------------ +- #32 Compatibility with senaite.core#2492 (AnalysisProfile to DX) 1.1.0 (2024-01-04) ------------------ From 11aafc1ae047b29ba9004e9b85f1cb77295816a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Fri, 1 Mar 2024 16:31:22 +0100 Subject: [PATCH 05/38] Hide AST results table when no AST analyses --- src/senaite/ast/browser/results.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/senaite/ast/browser/results.py b/src/senaite/ast/browser/results.py index 29002f5..49beef2 100644 --- a/src/senaite/ast/browser/results.py +++ b/src/senaite/ast/browser/results.py @@ -31,6 +31,9 @@ from senaite.ast import messageFactory as _ from senaite.ast import utils from senaite.ast.config import AST_POINT_OF_CAPTURE +from senaite.ast.config import IDENTIFICATION_KEY +from senaite.ast.utils import get_ast_analyses +from senaite.ast.utils import get_identified_microorganisms from senaite.core.browser.viewlets.sampleanalyses import LabAnalysesViewlet @@ -42,9 +45,24 @@ class ASTAnalysesViewlet(LabAnalysesViewlet): capture = AST_POINT_OF_CAPTURE def available(self): - """Returns true if senaite.ast is installed + """Returns true if senaite.ast is installed and the sample contains + at least one sensitivity testing analysis or the microorganism + identification analysis is present """ - return is_installed() + if not is_installed(): + return False + + # does this sample has the identification analysis? + analyses = self.context.getAnalyses(getKeyword=IDENTIFICATION_KEY) + if analyses: + return True + + # does this have sensitivity testing analyses? + ast_analyses = get_ast_analyses(self.context) + if ast_analyses: + return True + + return False class ManageResultsView(AnalysesView): From 97780304108cc87f294115071c6871b2c81b59d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Fri, 1 Mar 2024 16:36:54 +0100 Subject: [PATCH 06/38] Changelog --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 672cde6..b7efe0f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,7 @@ Changelog 1.2.0 (unreleased) ------------------ +- #33 Display the Antibiotic Sensitivity section only when necessary - #32 Compatibility with senaite.core#2492 (AnalysisProfile to DX) 1.1.0 (2024-01-04) From 5ddda8207789a502914ae46ff1b30b6910da07a0 Mon Sep 17 00:00:00 2001 From: Ramon Bartl Date: Fri, 1 Mar 2024 16:43:32 +0100 Subject: [PATCH 07/38] Whitespace only --- docs/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index b7efe0f..fdc8a55 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -7,6 +7,7 @@ Changelog - #33 Display the Antibiotic Sensitivity section only when necessary - #32 Compatibility with senaite.core#2492 (AnalysisProfile to DX) + 1.1.0 (2024-01-04) ------------------ @@ -19,6 +20,7 @@ Changelog - #21 Fix AST entry is empty when analyses categorization for sample is checked - #20 Compatibility with senaite.app.listing#87 + 1.0.0 (2022-06-18) ------------------ From 45442afa331fa1fbecb8b2cf4cef9c8ff8639aae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sun, 10 Mar 2024 20:01:21 +0100 Subject: [PATCH 08/38] Add modal for antibiotics rejection --- src/senaite/ast/browser/configure.zcml | 1 + src/senaite/ast/browser/modals/__init__.py | 19 ++++ src/senaite/ast/browser/modals/configure.zcml | 13 +++ .../ast/browser/modals/rejectantibiotics.py | 97 +++++++++++++++++++ .../modals/templates/reject_antibiotics.pt | 54 +++++++++++ 5 files changed, 184 insertions(+) create mode 100644 src/senaite/ast/browser/modals/__init__.py create mode 100644 src/senaite/ast/browser/modals/configure.zcml create mode 100644 src/senaite/ast/browser/modals/rejectantibiotics.py create mode 100644 src/senaite/ast/browser/modals/templates/reject_antibiotics.pt diff --git a/src/senaite/ast/browser/configure.zcml b/src/senaite/ast/browser/configure.zcml index 7b2b524..7c010df 100644 --- a/src/senaite/ast/browser/configure.zcml +++ b/src/senaite/ast/browser/configure.zcml @@ -6,6 +6,7 @@ + diff --git a/src/senaite/ast/browser/modals/__init__.py b/src/senaite/ast/browser/modals/__init__.py new file mode 100644 index 0000000..6899a65 --- /dev/null +++ b/src/senaite/ast/browser/modals/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# +# This file is part of SENAITE.AST. +# +# SENAITE.AST is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright 2020-2024 by it's authors. +# Some rights reserved, see README and LICENSE. diff --git a/src/senaite/ast/browser/modals/configure.zcml b/src/senaite/ast/browser/modals/configure.zcml new file mode 100644 index 0000000..4420d95 --- /dev/null +++ b/src/senaite/ast/browser/modals/configure.zcml @@ -0,0 +1,13 @@ + + + + + + diff --git a/src/senaite/ast/browser/modals/rejectantibiotics.py b/src/senaite/ast/browser/modals/rejectantibiotics.py new file mode 100644 index 0000000..f99e50d --- /dev/null +++ b/src/senaite/ast/browser/modals/rejectantibiotics.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# +# This file is part of SENAITE.AST. +# +# SENAITE.AST is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright 2020-2024 by it's authors. +# Some rights reserved, see README and LICENSE. + +import itertools +from bika.lims import api +from bika.lims.interfaces import IAnalysis +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from senaite.ast import logger +from senaite.ast import utils +from senaite.core.browser.modals import Modal + + +class RejectAntibioticsModal(Modal): + """Modal that allows to reject antibiotics (flag them as Not Tested) + """ + + template = ViewPageTemplateFile("templates/reject_antibiotics.pt") + + def __call__(self): + if self.request.form.get("submitted", False): + self.handle_submit() + return self.template() + + @property + def analyses(self): + """Returns the analyses passed-in as UIDs through the request + """ + analyses = map(api.get_object_by_uid, self.uids) + # include the siblings (ast analyses from same microorganism) + siblings = map(utils.get_ast_siblings, analyses) + # flatten the list of siblings + siblings = list(itertools.chain.from_iterable(siblings)) + analyses.extend(siblings) + return filter(IAnalysis.providedBy, set(analyses)) + + @property + def antibiotics(self): + """Returns a list of antibiotics with the antibiotics assigned to + the analyses passed-in as UIDs through the request, sorted by name + ascending + """ + kwargs = dict(filter_criteria=self.is_valid_antibiotic) + antibiotics = utils.get_antibiotics(self.analyses, **kwargs) + return sorted(antibiotics, key=lambda ab: api.get_title(ab)) + + def is_valid_antibiotic(self, interim_field): + """Returns whether the interim field corresponds to an antibiotic that + has not been rejected (flagged as not tested) + """ + if interim_field.get("status_rejected", False): + return False + return True + + def handle_submit(self): + """Handles the form submit. Flag the antibiotics selected in the form + as Not Tested for all analyses passed-in as UIDs through the request + """ + # get the uids that have been selected for rejection + rejected_uids = self.request.get("antibiotics") + + # flag the antibiotic as Not Tested (NT) for each analysis + for analysis in self.analyses: + self.reject_antibiotics(analysis, rejected_uids) + + def reject_antibiotics(self, analysis, antibiotics): + """Flags the antibiotics passed-in for the given analysis as Not tested + """ + interims = [] + not_tested = map(api.get_uid, antibiotics) + for interim in analysis.getInterimFields(): + abx_uid = interim.get("uid") + if abx_uid in not_tested: + logger.info("{}:{} Flagged as rejected".format( + api.get_title(analysis), interim.get("keyword") + )) + interim["status_rejected"] = True + + interims.append(interim) + + analysis.setInterimFields(interims) diff --git a/src/senaite/ast/browser/modals/templates/reject_antibiotics.pt b/src/senaite/ast/browser/modals/templates/reject_antibiotics.pt new file mode 100644 index 0000000..061a2ce --- /dev/null +++ b/src/senaite/ast/browser/modals/templates/reject_antibiotics.pt @@ -0,0 +1,54 @@ + From 382cc6bc6bd59971735fc1be5cd289b106ce3c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sun, 10 Mar 2024 20:01:36 +0100 Subject: [PATCH 09/38] Display "NT" for rejected antibiotics in results entry --- src/senaite/ast/browser/results.py | 6 +++++- src/senaite/ast/config.py | 3 +++ src/senaite/ast/utils.py | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/senaite/ast/browser/results.py b/src/senaite/ast/browser/results.py index 49beef2..da02fc1 100644 --- a/src/senaite/ast/browser/results.py +++ b/src/senaite/ast/browser/results.py @@ -32,6 +32,7 @@ from senaite.ast import utils from senaite.ast.config import AST_POINT_OF_CAPTURE from senaite.ast.config import IDENTIFICATION_KEY +from senaite.ast.config import NOT_TESTED from senaite.ast.utils import get_ast_analyses from senaite.ast.utils import get_identified_microorganisms from senaite.core.browser.viewlets.sampleanalyses import LabAnalysesViewlet @@ -183,7 +184,10 @@ def folder_interim_fields(self, obj, item): item["allow_edit"] = editable # This interim will be displayed as readonly mode, display text - text = utils.get_interim_text(interim_field, default="") + if interim_field.get("status_rejected", False): + text = NOT_TESTED + else: + text = utils.get_interim_text(interim_field, default="") item["replace"][keyword] = text or " " def folderitems(self): diff --git a/src/senaite/ast/config.py b/src/senaite/ast/config.py index 10143ab..9c9fa6a 100644 --- a/src/senaite/ast/config.py +++ b/src/senaite/ast/config.py @@ -79,6 +79,9 @@ # Description for autogenerated contents AUTOGENERATED = _(u"Autogenerated by senaite.ast") +# Abbreviation for "Not tested" +NOT_TESTED = "NT" + # Id of the Diffusion Disk method METHOD_DIFFUSION_DISK_ID = "diffusion_disk" diff --git a/src/senaite/ast/utils.py b/src/senaite/ast/utils.py index 54fa5d7..583f6f8 100644 --- a/src/senaite/ast/utils.py +++ b/src/senaite/ast/utils.py @@ -802,7 +802,7 @@ def is_interim_editable(interim): if is_interim_empty(interim): return True - statuses = ["to_be_verified", "verified"] + statuses = ["to_be_verified", "verified", "rejected"] for status in statuses: status_id = "status_{}".format(status) if interim.get(status_id, False): From 0a1c1d169b514d3de949fbae9302dd37c3aaede4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sun, 10 Mar 2024 21:43:17 +0100 Subject: [PATCH 10/38] Set NT as result --- .../ast/browser/modals/rejectantibiotics.py | 56 ++++++++++++++++--- src/senaite/ast/utils.py | 2 + 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/src/senaite/ast/browser/modals/rejectantibiotics.py b/src/senaite/ast/browser/modals/rejectantibiotics.py index f99e50d..6428f58 100644 --- a/src/senaite/ast/browser/modals/rejectantibiotics.py +++ b/src/senaite/ast/browser/modals/rejectantibiotics.py @@ -19,11 +19,14 @@ # Some rights reserved, see README and LICENSE. import itertools + from bika.lims import api -from bika.lims.interfaces import IAnalysis from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from senaite.ast import logger from senaite.ast import utils +from senaite.ast.config import NOT_TESTED +from senaite.ast.config import REPORT_EXTRAPOLATED_KEY +from senaite.ast.config import REPORT_KEY from senaite.core.browser.modals import Modal @@ -43,12 +46,18 @@ def analyses(self): """Returns the analyses passed-in as UIDs through the request """ analyses = map(api.get_object_by_uid, self.uids) - # include the siblings (ast analyses from same microorganism) + # be sure we rely on AST analyses only + analyses = filter(utils.is_ast_analysis, analyses) + # extend with siblings (AST-like analyses from same microorganism) siblings = map(utils.get_ast_siblings, analyses) - # flatten the list of siblings siblings = list(itertools.chain.from_iterable(siblings)) analyses.extend(siblings) - return filter(IAnalysis.providedBy, set(analyses)) + # remove duplicates + analyses = set(analyses) + # exclude analyses meant for selective reporting + exclude = [REPORT_KEY, REPORT_EXTRAPOLATED_KEY] + analyses = filter(lambda an: an.getKeyword() not in exclude, analyses) + return analyses @property def antibiotics(self): @@ -83,15 +92,44 @@ def reject_antibiotics(self, analysis, antibiotics): """Flags the antibiotics passed-in for the given analysis as Not tested """ interims = [] - not_tested = map(api.get_uid, antibiotics) + name = api.get_title(analysis) + keyword = analysis.getKeyword() + to_reject = map(api.get_uid, antibiotics) for interim in analysis.getInterimFields(): abx_uid = interim.get("uid") - if abx_uid in not_tested: - logger.info("{}:{} Flagged as rejected".format( - api.get_title(analysis), interim.get("keyword") - )) + if abx_uid in to_reject: + logger.info("{}:{} -> rejected".format(name, keyword)) + + # set rejected status interim["status_rejected"] = True + # set the result value + self.set_not_tested_result(interim) + interims.append(interim) + # update the interims/antibiotics analysis.setInterimFields(interims) + + def set_not_tested_result(self, interim): + """Sets the 'Not tested' result to the interim field. If the interim + has choices, it uses '0' as the value for the Not Tested. Otherwise, + sets NT as the textual result + """ + choices = utils.get_choices(interim) + if not choices: + # no choices, set string result + interim["value"] = NOT_TESTED + interim["string_result"] = True + return + + # insert a new choice ("-1", "NT") + choice = ("-1", NOT_TESTED) + if choice not in choices: + choices.insert(0, choice) + choices = ["{}:{}".format(ch[0], ch[1]) for ch in choices] + interim["choices"] = "|".join(choices) + + # assign the result value + interim["value"] = "-1" + interim["string_result"] = True diff --git a/src/senaite/ast/utils.py b/src/senaite/ast/utils.py index 583f6f8..0a22cc3 100644 --- a/src/senaite/ast/utils.py +++ b/src/senaite/ast/utils.py @@ -726,6 +726,8 @@ def get_choices(interim): :rtype: list """ choices = interim.get("choices", "") + if not choices: + return [] choices = map(lambda choice: choice.split(":"), choices.split("|")) return map(lambda choice: (choice[0], choice[1]), choices) From c2c7388662fc8b231a513a0e7dd8f6141017634a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sun, 10 Mar 2024 21:43:28 +0100 Subject: [PATCH 11/38] Display an alert icon next to results from rejected antibiotics --- src/senaite/ast/browser/results.py | 10 +++++----- src/senaite/ast/i18n.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 src/senaite/ast/i18n.py diff --git a/src/senaite/ast/browser/results.py b/src/senaite/ast/browser/results.py index da02fc1..493c1d6 100644 --- a/src/senaite/ast/browser/results.py +++ b/src/senaite/ast/browser/results.py @@ -24,6 +24,7 @@ from bika.lims import api from bika.lims.browser.analyses import AnalysesView from bika.lims.interfaces import IVerified +from bika.lims.utils import get_image from bika.lims.utils import get_link from plone.memoize import view from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile @@ -32,9 +33,8 @@ from senaite.ast import utils from senaite.ast.config import AST_POINT_OF_CAPTURE from senaite.ast.config import IDENTIFICATION_KEY -from senaite.ast.config import NOT_TESTED from senaite.ast.utils import get_ast_analyses -from senaite.ast.utils import get_identified_microorganisms +from senaite.ast.i18n import translate as t from senaite.core.browser.viewlets.sampleanalyses import LabAnalysesViewlet @@ -184,10 +184,10 @@ def folder_interim_fields(self, obj, item): item["allow_edit"] = editable # This interim will be displayed as readonly mode, display text + text = utils.get_interim_text(interim_field, default="") if interim_field.get("status_rejected", False): - text = NOT_TESTED - else: - text = utils.get_interim_text(interim_field, default="") + icon = get_image('warning.png', title=t(_("Not tested"))) + text = "{}{}".format(text, icon) item["replace"][keyword] = text or " " def folderitems(self): diff --git a/src/senaite/ast/i18n.py b/src/senaite/ast/i18n.py new file mode 100644 index 0000000..a035e56 --- /dev/null +++ b/src/senaite/ast/i18n.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# +# This file is part of SENAITE.AST. +# +# SENAITE.AST is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright 2020-2024 by it's authors. +# Some rights reserved, see README and LICENSE. + +from senaite.core.i18n import translate as core_translate + + +def translate(msgid, **kwargs): + """Translate any zope i18n msgid returned from MessageFactory + """ + domain = kwargs.pop("domain", "senaite.ast") + return core_translate(msgid, domain=domain, **kwargs) From 2eb486be59ad890c126a221bace62dc67b268be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sun, 10 Mar 2024 22:24:53 +0100 Subject: [PATCH 12/38] Update sensitivity final result on antibiotic rejection --- .../ast/browser/modals/rejectantibiotics.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/senaite/ast/browser/modals/rejectantibiotics.py b/src/senaite/ast/browser/modals/rejectantibiotics.py index 6428f58..9b78334 100644 --- a/src/senaite/ast/browser/modals/rejectantibiotics.py +++ b/src/senaite/ast/browser/modals/rejectantibiotics.py @@ -19,14 +19,18 @@ # Some rights reserved, see README and LICENSE. import itertools +from datetime import datetime from bika.lims import api from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile from senaite.ast import logger from senaite.ast import utils +from senaite.ast.calc import update_sensitivity_result from senaite.ast.config import NOT_TESTED from senaite.ast.config import REPORT_EXTRAPOLATED_KEY from senaite.ast.config import REPORT_KEY +from senaite.ast.config import RESISTANCE_KEY +from senaite.core.api import dtime as dt from senaite.core.browser.modals import Modal @@ -92,16 +96,17 @@ def reject_antibiotics(self, analysis, antibiotics): """Flags the antibiotics passed-in for the given analysis as Not tested """ interims = [] - name = api.get_title(analysis) keyword = analysis.getKeyword() to_reject = map(api.get_uid, antibiotics) for interim in analysis.getInterimFields(): abx_uid = interim.get("uid") if abx_uid in to_reject: - logger.info("{}:{} -> rejected".format(name, keyword)) # set rejected status - interim["status_rejected"] = True + user_id = api.get_current_user().id + timestamp = dt.to_iso_format(datetime.now()) + interim["status_rejected"] = timestamp + interim["status_rejected_by"] = user_id # set the result value self.set_not_tested_result(interim) @@ -111,6 +116,16 @@ def reject_antibiotics(self, analysis, antibiotics): # update the interims/antibiotics analysis.setInterimFields(interims) + if keyword == RESISTANCE_KEY: + # Compute all combinations of interim/antibiotic and possible + # result and generate the result options for this analysis (the + # "Result" field is never displayed and is only used for reporting) + result_options = utils.get_result_options(analysis) + analysis.setResultOptions(result_options) + + # Update the final result to be reported + update_sensitivity_result(analysis) + def set_not_tested_result(self, interim): """Sets the 'Not tested' result to the interim field. If the interim has choices, it uses '0' as the value for the Not Tested. Otherwise, From 65966b7679683059ea86f847a328467b4f76fffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Mon, 11 Mar 2024 10:10:45 +0100 Subject: [PATCH 13/38] Added upgrade step --- src/senaite/ast/adapters/guards.py | 7 + src/senaite/ast/configure.zcml | 4 + src/senaite/ast/permissions.py | 21 ++ src/senaite/ast/permissions.zcml | 8 + src/senaite/ast/profiles/default/metadata.xml | 2 +- src/senaite/ast/profiles/default/rolemap.xml | 40 ++++ src/senaite/ast/setuphandlers.py | 182 +++++++++++++++++- src/senaite/ast/subscribers/__init__.py | 19 ++ src/senaite/ast/subscribers/configure.zcml | 8 + src/senaite/ast/subscribers/upgrade.py | 55 ++++++ src/senaite/ast/upgrade/v01_02_000.py | 40 ++++ src/senaite/ast/upgrade/v01_02_000.zcml | 11 +- 12 files changed, 393 insertions(+), 4 deletions(-) create mode 100644 src/senaite/ast/permissions.py create mode 100644 src/senaite/ast/permissions.zcml create mode 100644 src/senaite/ast/profiles/default/rolemap.xml create mode 100644 src/senaite/ast/subscribers/__init__.py create mode 100644 src/senaite/ast/subscribers/configure.zcml create mode 100644 src/senaite/ast/subscribers/upgrade.py diff --git a/src/senaite/ast/adapters/guards.py b/src/senaite/ast/adapters/guards.py index 74e7a6b..3741d18 100644 --- a/src/senaite/ast/adapters/guards.py +++ b/src/senaite/ast/adapters/guards.py @@ -26,6 +26,7 @@ from senaite.ast.config import DISK_CONTENT_KEY from senaite.ast.config import MIC_KEY from senaite.ast.config import ZONE_SIZE_KEY +from senaite.ast.utils import is_ast_analysis from zope.interface import implementer OPERATORS = ["<=", ">=", "<", ">"] @@ -135,3 +136,9 @@ def guard_submit(self): return False return True + + def guard_reject_antibiotics(self): + """Rejection of antibiotics is only possible for sensitivity testing + (AST) analyses + """ + return is_ast_analysis(self.context) diff --git a/src/senaite/ast/configure.zcml b/src/senaite/ast/configure.zcml index afa44bf..8aace74 100644 --- a/src/senaite/ast/configure.zcml +++ b/src/senaite/ast/configure.zcml @@ -13,10 +13,14 @@ + + + + diff --git a/src/senaite/ast/permissions.py b/src/senaite/ast/permissions.py new file mode 100644 index 0000000..292858c --- /dev/null +++ b/src/senaite/ast/permissions.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# +# This file is part of SENAITE.AST. +# +# SENAITE.AST is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright 2020-2024 by it's authors. +# Some rights reserved, see README and LICENSE. + +TransitionRejectAntibiotics = "senaite.ast: Transition: Reject Antibiotics" diff --git a/src/senaite/ast/permissions.zcml b/src/senaite/ast/permissions.zcml new file mode 100644 index 0000000..a3dd245 --- /dev/null +++ b/src/senaite/ast/permissions.zcml @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/senaite/ast/profiles/default/metadata.xml b/src/senaite/ast/profiles/default/metadata.xml index f785b9b..e53d446 100644 --- a/src/senaite/ast/profiles/default/metadata.xml +++ b/src/senaite/ast/profiles/default/metadata.xml @@ -6,7 +6,7 @@ dependencies before installing this add-on own profile. --> - 1200 + 1201 diff --git a/src/senaite/ast/profiles/default/rolemap.xml b/src/senaite/ast/profiles/default/rolemap.xml new file mode 100644 index 0000000..ccfb4a9 --- /dev/null +++ b/src/senaite/ast/profiles/default/rolemap.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/senaite/ast/setuphandlers.py b/src/senaite/ast/setuphandlers.py index 1aebce9..e6eded8 100644 --- a/src/senaite/ast/setuphandlers.py +++ b/src/senaite/ast/setuphandlers.py @@ -22,6 +22,7 @@ from bika.lims.api import security from plone.registry.interfaces import IRegistry from Products.CMFCore.permissions import ModifyPortalContent +from Products.DCWorkflow.Guard import Guard from senaite.ast import logger from senaite.ast import messageFactory as _ from senaite.ast import PRODUCT_NAME @@ -29,9 +30,10 @@ from senaite.ast.config import AST_CALCULATION_TITLE from senaite.ast.config import AST_POINT_OF_CAPTURE from senaite.ast.config import AUTOGENERATED -from senaite.ast.config import IDENTIFICATION_KEY from senaite.ast.config import SERVICE_CATEGORY from senaite.ast.config import SERVICES_SETTINGS +from senaite.ast.permissions import TransitionRejectAntibiotics +from senaite.core.workflow import ANALYSIS_WORKFLOW from zope.component import getUtility # Tuples of (folder_id, folder_name, type) @@ -47,6 +49,39 @@ ]) ] +WORKFLOWS_TO_UPDATE = { + ANALYSIS_WORKFLOW: { + "states": { + "assigned": { + "transitions": ["modal_reject_antibiotics"], + }, + "unassigned": { + "transitions": ["modal_reject_antibiotics"], + }, + "to_be_verified": { + "transitions": ["modal_reject_antibiotics"], + }, + "verified": { + "transitions": ["modal_reject_antibiotics"], + } + }, + "transitions": { + "modal_reject_antibiotics": { + "title": "Reject antibiotics", + "new_state": "", + "action": "Reject antibiotics", + "action_url": "%(content_url)s/reject_antibiotics", + "guard": { + "guard_permissions": TransitionRejectAntibiotics, + "guard_roles": "", + "guard_expr": + "python:here.guard_handler('reject_antibiotics')", + } + } + } + } +} + def setup_handler(context): """Generic setup handler @@ -71,6 +106,9 @@ def setup_handler(context): # Add behaviors setup_behaviors(portal) + # setup workflows + setup_workflows(portal) + logger.info("{} setup handler [DONE]".format(PRODUCT_NAME.upper())) @@ -254,6 +292,148 @@ def search_by_title(container, title): return filter(lambda obj: api.get_title(obj) == title, objs) +def setup_workflows(portal): + """Setup workflow changes (status, transitions, permissions, etc.) + """ + logger.info("Setup workflows ...") + for wf_id, settings in WORKFLOWS_TO_UPDATE.items(): + update_workflow(portal, wf_id, settings) + logger.info("Setup workflows [DONE]") + + +def update_workflow(portal, workflow_id, settings): + """Updates the workflow with workflow_id with the settings passed-in + """ + logger.info("Updating workflow '{}' ...".format(workflow_id)) + wf_tool = api.get_tool("portal_workflow") + workflow = wf_tool.getWorkflowById(workflow_id) + if not workflow: + logger.warn("Workflow '{}' not found [SKIP]".format(workflow_id)) + + # Update states + states = settings.get("states", {}) + for state_id, values in states.items(): + update_workflow_state(workflow, state_id, values) + + # Update transitions + transitions = settings.get("transitions", {}) + for transition_id, values in transitions.items(): + update_workflow_transition(workflow, transition_id, values) + + +def update_workflow_state(workflow, status_id, settings): + """Updates the status of a workflow in accordance with settings passed-in + """ + logger.info("Updating workflow '{}', status: '{}' ..." + .format(workflow.id, status_id)) + + # Create the status (if does not exist yet) + status = workflow.states.get(status_id) + if not status: + workflow.states.addState(status_id) + status = workflow.states.get(status_id) + + # Set basic info (title, description, etc.) + status.title = settings.get("title", status.title) + status.description = settings.get("description", status.description) + + # Set transitions + trans = settings.get("transitions", []) or [] + if isinstance(trans, list): + trans = set(trans) + trans.update(status.transitions) + trans = tuple(trans) + status.transitions = trans + + # Set permissions + update_workflow_state_permissions(workflow, status, settings) + + +def update_workflow_state_permissions(workflow, status, settings): + """Updates the permissions of a workflow status in accordance with the + settings passed-in + """ + # Copy permissions from another state? + permissions_copy_from = settings.get("permissions_copy_from", None) + if permissions_copy_from: + logger.info("Copying permissions from '{}' to '{}' ..." + .format(permissions_copy_from, status.id)) + copy_from_state = workflow.states.get(permissions_copy_from) + if not copy_from_state: + logger.info("State '{}' not found [SKIP]".format(copy_from_state)) + else: + for perm_id in copy_from_state.permissions: + perm_info = copy_from_state.getPermissionInfo(perm_id) + acquired = perm_info.get("acquired", 1) + roles = perm_info.get("roles", acquired and [] or ()) + logger.info("Setting permission '{}' (acquired={}): '{}'" + .format(perm_id, repr(acquired), ', '.join(roles))) + status.setPermission(perm_id, acquired, roles) + + # Override permissions + logger.info("Overriding permissions for '{}' ...".format(status.id)) + state_permissions = settings.get("permissions", {}) + if not state_permissions: + logger.info( + "No permissions set for '{}' [SKIP]".format(status.id)) + return + + for permission_id, roles in state_permissions.items(): + if isinstance(roles, tuple): + acq = 0 + else: + info = status.getPermissionInfo(permission_id) or {} + acq = info.get("acquired", 0) + roles = set(roles) + roles.update(info.get("roles", [])) + roles = tuple(roles) + + logger.info("Setting permission '{}' (acquired={}): '{}'" + .format(permission_id, repr(acq), + ', '.join(roles))) + + # Check if this permission is defined globally for this workflow + if permission_id not in workflow.permissions: + workflow.permissions = workflow.permissions + (permission_id,) + status.setPermission(permission_id, acq, roles) + + +def update_workflow_transition(workflow, transition_id, settings): + """Updates the workflow transition in accordance with settings passed-in + """ + logger.info("Updating workflow '{}', transition: '{}'" + .format(workflow.id, transition_id)) + if transition_id not in workflow.transitions: + workflow.transitions.addTransition(transition_id) + transition = workflow.transitions.get(transition_id) + + # Guard + guard = transition.guard or Guard() + + # Transition properties + title = settings.get("title", transition.title) + new_state_id = settings.get("new_state", transition.new_state_id) + if new_state_id in ["None", None]: + new_state_id = "" + after_script = settings.get("after_script", transition.after_script_name) + if after_script in ["None", None]: + after_script = "" + action = settings.get("action", title) + action_url = settings.get("action_url", "") + transition.setProperties( + title=title, + new_state_id=new_state_id, + after_script_name=after_script, + actbox_name=action, + actbox_url=action_url, + ) + + if "guard" in settings: + guard.changeFromProperties(settings.get("guard")) + + transition.guard = guard + + def pre_install(portal_setup): """Runs before the first import step of the *default* profile This handler is registered as a *pre_handler* in the generic setup profile diff --git a/src/senaite/ast/subscribers/__init__.py b/src/senaite/ast/subscribers/__init__.py new file mode 100644 index 0000000..6899a65 --- /dev/null +++ b/src/senaite/ast/subscribers/__init__.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# +# This file is part of SENAITE.AST. +# +# SENAITE.AST is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright 2020-2024 by it's authors. +# Some rights reserved, see README and LICENSE. diff --git a/src/senaite/ast/subscribers/configure.zcml b/src/senaite/ast/subscribers/configure.zcml new file mode 100644 index 0000000..6925721 --- /dev/null +++ b/src/senaite/ast/subscribers/configure.zcml @@ -0,0 +1,8 @@ + + + + + + diff --git a/src/senaite/ast/subscribers/upgrade.py b/src/senaite/ast/subscribers/upgrade.py new file mode 100644 index 0000000..f798cc5 --- /dev/null +++ b/src/senaite/ast/subscribers/upgrade.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# +# This file is part of SENAITE.AST. +# +# SENAITE.AST is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright 2020-2024 by it's authors. +# Some rights reserved, see README and LICENSE. + + +from bika.lims.api import get_portal +from senaite.ast import is_installed +from senaite.ast import logger +from senaite.ast import PRODUCT_NAME +from senaite.ast.setuphandlers import setup_behaviors +from senaite.ast.setuphandlers import setup_navigation_types +from senaite.ast.setuphandlers import setup_workflows + + +def afterUpgradeStepHandler(event): + """Event handler executed after running an upgrade step of senaite.core + """ + if not is_installed(): + return + + logger.info("Run {}.afterUpgradeStepHandler ...".format(PRODUCT_NAME)) + portal = get_portal() + setup = portal.portal_setup # noqa + + profile = "profile-{0}:default".format(PRODUCT_NAME) + setup.runImportStepFromProfile(profile, "typeinfo") + setup.runImportStepFromProfile(profile, "rolemap") + setup.runImportStepFromProfile(profile, "workflow") + + # Configure visible navigation items + setup_navigation_types(portal) + + # Setup additional behaviors + setup_behaviors(portal) + + # Setup workflows + setup_workflows(portal) + + logger.info("Run {}.afterUpgradeStepHandler [DONE]".format(PRODUCT_NAME)) diff --git a/src/senaite/ast/upgrade/v01_02_000.py b/src/senaite/ast/upgrade/v01_02_000.py index 8c0ba24..7df7de1 100644 --- a/src/senaite/ast/upgrade/v01_02_000.py +++ b/src/senaite/ast/upgrade/v01_02_000.py @@ -18,12 +18,17 @@ # Copyright 2020-2024 by it's authors. # Some rights reserved, see README and LICENSE. +from bika.lims import api from senaite.ast import logger from senaite.ast import PRODUCT_NAME +from senaite.ast.config import AST_POINT_OF_CAPTURE +from senaite.ast.setuphandlers import setup_workflows +from senaite.core.catalog import ANALYSIS_CATALOG from senaite.core.upgrade import upgradestep from senaite.core.upgrade.utils import UpgradeUtils version = "1.1.0" +profile = "profile-{0}:default".format(PRODUCT_NAME) @upgradestep(PRODUCT_NAME, version) @@ -45,3 +50,38 @@ def upgrade(tool): logger.info("{0} upgraded to version {1}".format(PRODUCT_NAME, version)) return True + + +def setup_reject_antibiotics(tool): + logger.info("Setup reject antibiotics transition ...") + portal = tool.aq_inner.aq_parent + + # import rolemap and workflow + setup = portal.portal_setup + setup.runImportStepFromProfile(profile, "rolemap") + setup.runImportStepFromProfile(profile, "workflow") + + # setup custom workflow modifs + setup_workflows(portal) + + # update role mappings + statuses = ["assigned", "unassigned", "to_be_verified", "verified"] + cat = api.get_tool(ANALYSIS_CATALOG) + brains = cat(portal_type="Analysis", review_state=statuses, + getPointOfCapture=AST_POINT_OF_CAPTURE) + map(update_role_mappings_for, brains) + + logger.info("Setup reject antibiotics transition [DONE]") + + +def update_role_mappings_for(object_or_brain): + """Update role mappings for the specified object + """ + obj = api.get_object(object_or_brain) + path = api.get_path(obj) + logger.info("Updating workflow role mappings for {} ...".format(path)) + tool = api.get_tool("portal_workflow") + for wf_id in api.get_workflows_for(obj): + wf = tool.getWorkflowById(wf_id) + wf.updateRoleMappingsFor(obj) + obj.reindexObject(idxs=["allowedRolesAndUsers"]) diff --git a/src/senaite/ast/upgrade/v01_02_000.zcml b/src/senaite/ast/upgrade/v01_02_000.zcml index ef1cb7d..253514b 100644 --- a/src/senaite/ast/upgrade/v01_02_000.zcml +++ b/src/senaite/ast/upgrade/v01_02_000.zcml @@ -1,7 +1,14 @@ + xmlns:genericsetup="http://namespaces.zope.org/genericsetup"> + + Date: Mon, 11 Mar 2024 10:32:59 +0100 Subject: [PATCH 14/38] Changelog and documentation --- docs/changelog.rst | 1 + docs/quickstart.rst | 25 ++++++++++++++++++++++++- docs/static/not_tested.png | Bin 0 -> 84744 bytes docs/static/reject_antibiotics.png | Bin 0 -> 77409 bytes 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 docs/static/not_tested.png create mode 100644 docs/static/reject_antibiotics.png diff --git a/docs/changelog.rst b/docs/changelog.rst index fdc8a55..07f00dc 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,7 @@ Changelog 1.2.0 (unreleased) ------------------ +- #34 Add transition "Reject antibiotics" - #33 Display the Antibiotic Sensitivity section only when necessary - #32 Compatibility with senaite.core#2492 (AnalysisProfile to DX) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 2e10e14..1187c24 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -175,7 +175,30 @@ From this view, user can choose the tuples Microorganism-Antibiotic to be reported in results. Once the button "Save" is pressed, the value for analyses with name "Report" for all microorganisms are updated accordingly. -.. Links + +.. _RejectAntibiotics: + +Flag antibiotics as Not Tested +------------------------------ + +Quite often, laboratory manager will want to report "Not tested" for some +antibiotics and microorganisms, while keeping them in the AST panel. This can +be easily achieved with the transition "Reject antibiotics". This transition is +available for analyses that are part of a sensitivity testing panel. Once +clicked, a modal view is displayed, where user can choose the antibiotics to be +flagged as "Not Tested": + +.. image:: static/reject_antibiotics.png + :width: 640 + :alt: Reject antibiotics + +Once done, "NT" is displayed as a result for the selected antibiotics, both in +results entry and in results report: + +.. image:: static/not_tested.png + :width: 640 + :alt: Antibiotics flagged as Not Tested + .. _SENAITE LIMS: https://www.senaite.com .. _senaite.ast: https://pypi.python.org/pypi/senaite.ast diff --git a/docs/static/not_tested.png b/docs/static/not_tested.png new file mode 100644 index 0000000000000000000000000000000000000000..99c3b0d92e7b42d0442359d6d54c8c8e196cdad2 GIT binary patch literal 84744 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%0Dm$pZ@?gHZ>4JI9T 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 literal 0 HcmV?d00001 diff --git a/docs/static/reject_antibiotics.png b/docs/static/reject_antibiotics.png new file mode 100644 index 0000000000000000000000000000000000000000..e56fd8f3bf3ab670478fde7acd6462f5329c3449 GIT binary patch literal 77409 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 >DuU@Ir7Uf2Tj!U4$nxUU!lRmh)!d>5x0-W@ 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%0Dj8i#Yf%2DO&jm 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 literal 0 HcmV?d00001 From 7cfa64b32677767bf9e670b8b422dbd49695dc92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Mon, 11 Mar 2024 10:44:01 +0100 Subject: [PATCH 15/38] Create .readthedocs.yaml --- .readthedocs.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..080b0a6 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +# Read the Docs configuration file for Sphinx projects +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the OS, Python version and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py From 27c6fec06c0771f1d23840c4bae9302b4ab4d81e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Tue, 12 Mar 2024 10:02:47 +0100 Subject: [PATCH 16/38] Allow to submit even when rejected antibiotics --- src/senaite/ast/adapters/guards.py | 4 ++++ src/senaite/ast/utils.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/senaite/ast/adapters/guards.py b/src/senaite/ast/adapters/guards.py index 3741d18..7e34a5c 100644 --- a/src/senaite/ast/adapters/guards.py +++ b/src/senaite/ast/adapters/guards.py @@ -104,6 +104,10 @@ def guard_submit(self): # Skip extrapolated antibiotics continue + if utils.is_rejected_interim(antibiotic): + # Skip rejected antibiotics + continue + if utils.is_interim_empty(antibiotic): # Cannot submit if no result return False diff --git a/src/senaite/ast/utils.py b/src/senaite/ast/utils.py index 0a22cc3..d3b33ce 100644 --- a/src/senaite/ast/utils.py +++ b/src/senaite/ast/utils.py @@ -744,6 +744,20 @@ def is_interim_empty(interim): return not text +def is_rejected_interim(interim): + """Returns whether the interim represents a rejected antibiotic + + :param interim: interim field + :type interim: dict + :returns: True if the value or text representation of this interim is empty + :rtype: bool + """ + rejected = interim.get("status_rejected", None) + if rejected: + return True + return False + + def is_extrapolated_interim(interim): """Returns whether the interim represents an extrapolated antibiotic From 9a7527ae7aeee9d0ab6f2cf0d212f3629f8e3bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Tue, 12 Mar 2024 11:14:01 +0100 Subject: [PATCH 17/38] Fix cannot submit analyses with rejected antibiotics --- src/senaite/ast/calc.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/senaite/ast/calc.py b/src/senaite/ast/calc.py index eb236f6..04fcfa9 100644 --- a/src/senaite/ast/calc.py +++ b/src/senaite/ast/calc.py @@ -97,7 +97,7 @@ def calc_sensitivity_categories(analysis): # The result for each antibiotic is stored as an interim field breakpoints = breakpoints_analysis.getInterimFields() values = target_analysis.getInterimFields() - categories = sensitivity.getInterimFields() + antibiotics = sensitivity.getInterimFields() # Get the mapping of Antibiotic -> BreakpointsTable breakpoints = dict(map(lambda b: (b['uid'], b['value']), breakpoints)) @@ -108,12 +108,16 @@ def calc_sensitivity_categories(analysis): # Get the microorganism this analysis is associated to microorganism = get_microorganism(analysis) - # Update sensitivity categories - for category in categories: + # Update sensitivity category for each antibiotic + for antibiotic in antibiotics: + # Skip non-editable antibiotics + if not utils.is_interim_editable(antibiotic): + continue + # If extrapolated, assume same zone size as representative - abx_uid = category.get("primary") + abx_uid = antibiotic.get("primary") if not api.is_uid(abx_uid): - abx_uid = category["uid"] + abx_uid = antibiotic["uid"] # Get the zone size / MIC value value = values.get(abx_uid) @@ -121,7 +125,7 @@ def calc_sensitivity_categories(analysis): # No value entered yet or not floatable continue - # Get the selected Breakpoints Table for this category + # Get the selected Breakpoints Table for this antibiotic breakpoints_uid = breakpoints.get(abx_uid) # Get the breakpoint for this microorganism and antibiotic @@ -133,10 +137,10 @@ def calc_sensitivity_categories(analysis): cat = get_sensitivity_category_value(key, default="") # Update the sensitivity category - category.update({"value": cat}) + antibiotic.update({"value": cat}) - # Assign the updated categories to the sensitivity category analysis - sensitivity.setInterimFields(categories) + # Assign the antibiotics with the updated sensitivity categories + sensitivity.setInterimFields(antibiotics) def calc_disk_dosages(analysis): @@ -171,12 +175,16 @@ def calc_disk_dosages(analysis): breakpoints = dict(map(lambda b: (b['uid'], b['value']), breakpoints)) # Dosages are stored as interim fields - disk_dosages = disk_dosages_analysis.getInterimFields() - for dosage in disk_dosages: + antibiotics = disk_dosages_analysis.getInterimFields() + for antibiotic in antibiotics: + # Skip non-editable antibiotics + if not utils.is_interim_editable(antibiotic): + continue + # If extrapolated, assume same zone size as representative - abx_uid = dosage.get("primary") + abx_uid = antibiotic.get("primary") if not api.is_uid(abx_uid): - abx_uid = dosage["uid"] + abx_uid = antibiotic["uid"] # Get the selected Breakpoints Table for this category breakpoints_uid = breakpoints.get(abx_uid) @@ -189,10 +197,10 @@ def calc_disk_dosages(analysis): # Update the dosage breakpoint_dosage = breakpoint.get("disk_content") if api.to_float(breakpoint_dosage, default=0) > 0: - dosage.update({"value": breakpoint_dosage}) + antibiotic.update({"value": breakpoint_dosage}) # Assign the inferred disk dosages - disk_dosages_analysis.setInterimFields(disk_dosages) + disk_dosages_analysis.setInterimFields(antibiotics) def update_extrapolated_antibiotics(analysis): From fd669cad314d82f622b771e874201277c8b980a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Tue, 12 Mar 2024 11:14:17 +0100 Subject: [PATCH 18/38] Fix NA results are overwritten on save when values previously set --- src/senaite/ast/datamanagers.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/senaite/ast/datamanagers.py b/src/senaite/ast/datamanagers.py index 3bdee16..3571c64 100644 --- a/src/senaite/ast/datamanagers.py +++ b/src/senaite/ast/datamanagers.py @@ -18,12 +18,15 @@ # Copyright 2020-2024 by it's authors. # Some rights reserved, see README and LICENSE. +from senaite.ast import logger from senaite.ast.config import BREAKPOINTS_TABLE_KEY from senaite.ast.config import DISK_CONTENT_KEY from senaite.ast.config import RESISTANCE_KEY from senaite.ast.config import ZONE_SIZE_KEY from senaite.ast.interfaces import IASTAnalysis from senaite.ast.utils import get_ast_siblings +from senaite.ast.utils import is_ast_analysis +from senaite.ast.utils import is_interim_editable from senaite.core.datamanagers.analysis import RoutineAnalysisDataManager from zope.component import adapter @@ -33,6 +36,32 @@ class ASTAnalysisDataManager(RoutineAnalysisDataManager): """Data Manager for AST-like analyses """ + def get_antibiotic_interim(self, keyword, default=None): + """Returns the interim that represents the antibiotic with the given + keyword, but only if the context is an AST-like analysis + """ + if not is_ast_analysis(self.context): + return default + + for interim in self.context.getInterimFields(): + if interim.get("keyword") == keyword: + return interim + + return default + + def set(self, name, value): + """Set analysis field/interim value + """ + # Check if an antibiotic/interim of an AST analysis + antibiotic = self.get_antibiotic_interim(name) + if antibiotic and not is_interim_editable(antibiotic): + logger.error("Interim field '{}' not writeable!".format(name)) + return [] + + # rely on the base class + base = super(ASTAnalysisDataManager, self) + return base.set(name, value) + def recalculate_results(self, obj, recalculated=None): recalculated = super(ASTAnalysisDataManager, self).\ recalculate_results(obj, recalculated=recalculated) From 8491c959b21e75c3900cc174a0edc30a2bef3cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Tue, 12 Mar 2024 13:53:29 +0100 Subject: [PATCH 19/38] Use update_workflow function from senaite.core --- src/senaite/ast/setuphandlers.py | 137 +------------------------------ 1 file changed, 2 insertions(+), 135 deletions(-) diff --git a/src/senaite/ast/setuphandlers.py b/src/senaite/ast/setuphandlers.py index e6eded8..83fe2db 100644 --- a/src/senaite/ast/setuphandlers.py +++ b/src/senaite/ast/setuphandlers.py @@ -22,7 +22,6 @@ from bika.lims.api import security from plone.registry.interfaces import IRegistry from Products.CMFCore.permissions import ModifyPortalContent -from Products.DCWorkflow.Guard import Guard from senaite.ast import logger from senaite.ast import messageFactory as _ from senaite.ast import PRODUCT_NAME @@ -34,6 +33,7 @@ from senaite.ast.config import SERVICES_SETTINGS from senaite.ast.permissions import TransitionRejectAntibiotics from senaite.core.workflow import ANALYSIS_WORKFLOW +from senaite.core.workflow import update_workflow from zope.component import getUtility # Tuples of (folder_id, folder_name, type) @@ -297,143 +297,10 @@ def setup_workflows(portal): """ logger.info("Setup workflows ...") for wf_id, settings in WORKFLOWS_TO_UPDATE.items(): - update_workflow(portal, wf_id, settings) + update_workflow(wf_id, **settings) logger.info("Setup workflows [DONE]") -def update_workflow(portal, workflow_id, settings): - """Updates the workflow with workflow_id with the settings passed-in - """ - logger.info("Updating workflow '{}' ...".format(workflow_id)) - wf_tool = api.get_tool("portal_workflow") - workflow = wf_tool.getWorkflowById(workflow_id) - if not workflow: - logger.warn("Workflow '{}' not found [SKIP]".format(workflow_id)) - - # Update states - states = settings.get("states", {}) - for state_id, values in states.items(): - update_workflow_state(workflow, state_id, values) - - # Update transitions - transitions = settings.get("transitions", {}) - for transition_id, values in transitions.items(): - update_workflow_transition(workflow, transition_id, values) - - -def update_workflow_state(workflow, status_id, settings): - """Updates the status of a workflow in accordance with settings passed-in - """ - logger.info("Updating workflow '{}', status: '{}' ..." - .format(workflow.id, status_id)) - - # Create the status (if does not exist yet) - status = workflow.states.get(status_id) - if not status: - workflow.states.addState(status_id) - status = workflow.states.get(status_id) - - # Set basic info (title, description, etc.) - status.title = settings.get("title", status.title) - status.description = settings.get("description", status.description) - - # Set transitions - trans = settings.get("transitions", []) or [] - if isinstance(trans, list): - trans = set(trans) - trans.update(status.transitions) - trans = tuple(trans) - status.transitions = trans - - # Set permissions - update_workflow_state_permissions(workflow, status, settings) - - -def update_workflow_state_permissions(workflow, status, settings): - """Updates the permissions of a workflow status in accordance with the - settings passed-in - """ - # Copy permissions from another state? - permissions_copy_from = settings.get("permissions_copy_from", None) - if permissions_copy_from: - logger.info("Copying permissions from '{}' to '{}' ..." - .format(permissions_copy_from, status.id)) - copy_from_state = workflow.states.get(permissions_copy_from) - if not copy_from_state: - logger.info("State '{}' not found [SKIP]".format(copy_from_state)) - else: - for perm_id in copy_from_state.permissions: - perm_info = copy_from_state.getPermissionInfo(perm_id) - acquired = perm_info.get("acquired", 1) - roles = perm_info.get("roles", acquired and [] or ()) - logger.info("Setting permission '{}' (acquired={}): '{}'" - .format(perm_id, repr(acquired), ', '.join(roles))) - status.setPermission(perm_id, acquired, roles) - - # Override permissions - logger.info("Overriding permissions for '{}' ...".format(status.id)) - state_permissions = settings.get("permissions", {}) - if not state_permissions: - logger.info( - "No permissions set for '{}' [SKIP]".format(status.id)) - return - - for permission_id, roles in state_permissions.items(): - if isinstance(roles, tuple): - acq = 0 - else: - info = status.getPermissionInfo(permission_id) or {} - acq = info.get("acquired", 0) - roles = set(roles) - roles.update(info.get("roles", [])) - roles = tuple(roles) - - logger.info("Setting permission '{}' (acquired={}): '{}'" - .format(permission_id, repr(acq), - ', '.join(roles))) - - # Check if this permission is defined globally for this workflow - if permission_id not in workflow.permissions: - workflow.permissions = workflow.permissions + (permission_id,) - status.setPermission(permission_id, acq, roles) - - -def update_workflow_transition(workflow, transition_id, settings): - """Updates the workflow transition in accordance with settings passed-in - """ - logger.info("Updating workflow '{}', transition: '{}'" - .format(workflow.id, transition_id)) - if transition_id not in workflow.transitions: - workflow.transitions.addTransition(transition_id) - transition = workflow.transitions.get(transition_id) - - # Guard - guard = transition.guard or Guard() - - # Transition properties - title = settings.get("title", transition.title) - new_state_id = settings.get("new_state", transition.new_state_id) - if new_state_id in ["None", None]: - new_state_id = "" - after_script = settings.get("after_script", transition.after_script_name) - if after_script in ["None", None]: - after_script = "" - action = settings.get("action", title) - action_url = settings.get("action_url", "") - transition.setProperties( - title=title, - new_state_id=new_state_id, - after_script_name=after_script, - actbox_name=action, - actbox_url=action_url, - ) - - if "guard" in settings: - guard.changeFromProperties(settings.get("guard")) - - transition.guard = guard - - def pre_install(portal_setup): """Runs before the first import step of the *default* profile This handler is registered as a *pre_handler* in the generic setup profile From dc306836db3b6777e284ad3813c5b3af5bdc0e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 14 Mar 2024 13:30:25 +0100 Subject: [PATCH 20/38] Function moved from senaite.core.workflow to senaite.core.api.workflow --- src/senaite/ast/setuphandlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/senaite/ast/setuphandlers.py b/src/senaite/ast/setuphandlers.py index 83fe2db..d9ad94e 100644 --- a/src/senaite/ast/setuphandlers.py +++ b/src/senaite/ast/setuphandlers.py @@ -32,8 +32,8 @@ from senaite.ast.config import SERVICE_CATEGORY from senaite.ast.config import SERVICES_SETTINGS from senaite.ast.permissions import TransitionRejectAntibiotics +from senaite.core.api.workflow import update_workflow from senaite.core.workflow import ANALYSIS_WORKFLOW -from senaite.core.workflow import update_workflow from zope.component import getUtility # Tuples of (folder_id, folder_name, type) From 80d9c3869be70674e9fb3e2ae7cfbed3e75a097c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Mon, 18 Mar 2024 11:34:06 +0100 Subject: [PATCH 21/38] Allow to reject antibiotics only for unassigned and assigned --- src/senaite/ast/setuphandlers.py | 6 ------ src/senaite/ast/upgrade/v01_02_000.py | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/senaite/ast/setuphandlers.py b/src/senaite/ast/setuphandlers.py index d9ad94e..829357b 100644 --- a/src/senaite/ast/setuphandlers.py +++ b/src/senaite/ast/setuphandlers.py @@ -58,12 +58,6 @@ "unassigned": { "transitions": ["modal_reject_antibiotics"], }, - "to_be_verified": { - "transitions": ["modal_reject_antibiotics"], - }, - "verified": { - "transitions": ["modal_reject_antibiotics"], - } }, "transitions": { "modal_reject_antibiotics": { diff --git a/src/senaite/ast/upgrade/v01_02_000.py b/src/senaite/ast/upgrade/v01_02_000.py index 7df7de1..1fe277d 100644 --- a/src/senaite/ast/upgrade/v01_02_000.py +++ b/src/senaite/ast/upgrade/v01_02_000.py @@ -65,7 +65,7 @@ def setup_reject_antibiotics(tool): setup_workflows(portal) # update role mappings - statuses = ["assigned", "unassigned", "to_be_verified", "verified"] + statuses = ["assigned", "unassigned"] cat = api.get_tool(ANALYSIS_CATALOG) brains = cat(portal_type="Analysis", review_state=statuses, getPointOfCapture=AST_POINT_OF_CAPTURE) From 662724dcefb0dd92a68eec7c138ff3c6b544921d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Fri, 12 Apr 2024 09:21:17 +0200 Subject: [PATCH 22/38] Do not display ast analyses for selection in Sample Template --- src/senaite/ast/adapters/configure.zcml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/senaite/ast/adapters/configure.zcml b/src/senaite/ast/adapters/configure.zcml index df979c8..b060282 100644 --- a/src/senaite/ast/adapters/configure.zcml +++ b/src/senaite/ast/adapters/configure.zcml @@ -30,8 +30,8 @@ From b1769d6a8202225273281f20726555af6e0175b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Fri, 12 Apr 2024 09:35:50 +0200 Subject: [PATCH 23/38] Ensure migration step handles new SampleTemplate properly --- src/senaite/ast/upgrade/v01_00_000.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/senaite/ast/upgrade/v01_00_000.py b/src/senaite/ast/upgrade/v01_00_000.py index 175377c..7550581 100644 --- a/src/senaite/ast/upgrade/v01_00_000.py +++ b/src/senaite/ast/upgrade/v01_00_000.py @@ -33,6 +33,7 @@ from senaite.ast.setuphandlers import setup_navigation_types from senaite.ast.utils import get_result_options from senaite.core.catalog import SETUP_CATALOG +from senaite.core.interfaces import ISampleTemplate from senaite.core.upgrade import upgradestep from senaite.core.upgrade.utils import UpgradeUtils @@ -160,11 +161,18 @@ def remove_ast_from_templates(portal): logger.info("Removing AST-like analyses from templates ...") ast_uids = get_ast_services_uids(portal) query = { - "portal_type": "ARTemplate" + "portal_type": ["ARTemplate", "SampleTemplate"] } brains = api.search(query, SETUP_CATALOG) for brain in brains: obj = api.get_object(brain) + if ISampleTemplate.providedBy(obj): + ans = obj.getRawServices() + ans = filter(lambda an: an.get("uid") not in ast_uids, ans) + obj.setServices(list(ans)) + continue + + # Old AT object (https://github.com/senaite/senaite.core/pull/2521) ans = obj.getAnalyses() ans = filter(lambda an: an.get("service_uid") not in ast_uids, ans) obj.setAnalyses(ans) From da387c9955739f689966d1795d3ccf524be21bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Fri, 12 Apr 2024 09:40:46 +0200 Subject: [PATCH 24/38] Changelog --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 07f00dc..8eff1cc 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,7 @@ Changelog 1.2.0 (unreleased) ------------------ +- #35 Compatibility with core#2521 - AT2DX ARTemplate/SampleTemplate - #34 Add transition "Reject antibiotics" - #33 Display the Antibiotic Sensitivity section only when necessary - #32 Compatibility with senaite.core#2492 (AnalysisProfile to DX) From 1fe2cbb43e4472bdc6422b9143f3f5b26992d9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Fri, 12 Apr 2024 09:41:45 +0200 Subject: [PATCH 25/38] Spelling --- src/senaite/ast/adapters/configure.zcml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/senaite/ast/adapters/configure.zcml b/src/senaite/ast/adapters/configure.zcml index b060282..e342915 100644 --- a/src/senaite/ast/adapters/configure.zcml +++ b/src/senaite/ast/adapters/configure.zcml @@ -28,7 +28,7 @@ provides="senaite.app.listing.interfaces.IListingViewAdapter" factory=".listing.services.NonASTServicesViewAdapter" /> - + Date: Thu, 2 May 2024 15:53:41 +0200 Subject: [PATCH 26/38] Fix user can edit ast built-in services after upgrades --- src/senaite/ast/profiles/default/metadata.xml | 2 +- src/senaite/ast/setuphandlers.py | 33 +++++++++++++++++++ src/senaite/ast/subscribers/upgrade.py | 4 +++ src/senaite/ast/upgrade/v01_02_000.py | 6 ++++ src/senaite/ast/upgrade/v01_02_000.zcml | 8 +++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/senaite/ast/profiles/default/metadata.xml b/src/senaite/ast/profiles/default/metadata.xml index e53d446..2bc3e64 100644 --- a/src/senaite/ast/profiles/default/metadata.xml +++ b/src/senaite/ast/profiles/default/metadata.xml @@ -6,7 +6,7 @@ dependencies before installing this add-on own profile. --> - 1201 + 1202 diff --git a/src/senaite/ast/setuphandlers.py b/src/senaite/ast/setuphandlers.py index 829357b..9ca39cf 100644 --- a/src/senaite/ast/setuphandlers.py +++ b/src/senaite/ast/setuphandlers.py @@ -33,6 +33,7 @@ from senaite.ast.config import SERVICES_SETTINGS from senaite.ast.permissions import TransitionRejectAntibiotics from senaite.core.api.workflow import update_workflow +from senaite.core.catalog import SETUP_CATALOG from senaite.core.workflow import ANALYSIS_WORKFLOW from zope.component import getUtility @@ -103,6 +104,9 @@ def setup_handler(context): # setup workflows setup_workflows(portal) + # Revoke edit permissions for ast setup objects + revoke_edition_permissions(portal) + logger.info("{} setup handler [DONE]".format(PRODUCT_NAME.upper())) @@ -279,6 +283,35 @@ def remove_behaviors(portal): logger.info("Removing Behaviors [DONE]") +def revoke_edition_permissions(portal): + """Revoke the 'Modify portal content' permission to 'ast' services + """ + logger.info("Revoking edition permissions to AST setup objects ...") + + def revoke_permission(obj): + obj = api.get_object(obj) + roles = security.get_valid_roles_for(obj) + security.revoke_permission_for(obj, ModifyPortalContent, roles) + obj.reindexObject() + + import pdb;pdb.set_trace() + + # analysis services + query = { + "portal_type": "AnalysisService", + "point_of_capture": AST_POINT_OF_CAPTURE + } + brains = api.search(query, SETUP_CATALOG) + map(revoke_permission, brains) + + # calculation + query = {"portal_type": "Calculation", "title": AST_CALCULATION_TITLE} + brains = api.search(query, SETUP_CATALOG) + map(revoke_permission, brains) + + logger.info("Revoking edition permissions to AST setup objects [DONE]") + + def search_by_title(container, title): """Returns the items from the container that match with the title passed-in """ diff --git a/src/senaite/ast/subscribers/upgrade.py b/src/senaite/ast/subscribers/upgrade.py index f798cc5..3ad8b4e 100644 --- a/src/senaite/ast/subscribers/upgrade.py +++ b/src/senaite/ast/subscribers/upgrade.py @@ -23,6 +23,7 @@ from senaite.ast import is_installed from senaite.ast import logger from senaite.ast import PRODUCT_NAME +from senaite.ast.setuphandlers import revoke_edition_permissions from senaite.ast.setuphandlers import setup_behaviors from senaite.ast.setuphandlers import setup_navigation_types from senaite.ast.setuphandlers import setup_workflows @@ -52,4 +53,7 @@ def afterUpgradeStepHandler(event): # Setup workflows setup_workflows(portal) + # Revoke edit permissions for ast setup objects + revoke_edition_permissions(portal) + logger.info("Run {}.afterUpgradeStepHandler [DONE]".format(PRODUCT_NAME)) diff --git a/src/senaite/ast/upgrade/v01_02_000.py b/src/senaite/ast/upgrade/v01_02_000.py index 1fe277d..547470f 100644 --- a/src/senaite/ast/upgrade/v01_02_000.py +++ b/src/senaite/ast/upgrade/v01_02_000.py @@ -22,6 +22,7 @@ from senaite.ast import logger from senaite.ast import PRODUCT_NAME from senaite.ast.config import AST_POINT_OF_CAPTURE +from senaite.ast.setuphandlers import revoke_edition_permissions from senaite.ast.setuphandlers import setup_workflows from senaite.core.catalog import ANALYSIS_CATALOG from senaite.core.upgrade import upgradestep @@ -85,3 +86,8 @@ def update_role_mappings_for(object_or_brain): wf = tool.getWorkflowById(wf_id) wf.updateRoleMappingsFor(obj) obj.reindexObject(idxs=["allowedRolesAndUsers"]) + + +def revoke_setup_permissions(tool): + portal = tool.aq_inner.aq_parent + revoke_edition_permissions(portal) diff --git a/src/senaite/ast/upgrade/v01_02_000.zcml b/src/senaite/ast/upgrade/v01_02_000.zcml index 253514b..b63486f 100644 --- a/src/senaite/ast/upgrade/v01_02_000.zcml +++ b/src/senaite/ast/upgrade/v01_02_000.zcml @@ -2,6 +2,14 @@ xmlns="http://namespaces.zope.org/zope" xmlns:genericsetup="http://namespaces.zope.org/genericsetup"> + + Date: Thu, 2 May 2024 15:56:40 +0200 Subject: [PATCH 27/38] Changelog --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 8eff1cc..34473aa 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,7 @@ Changelog 1.2.0 (unreleased) ------------------ +- #36 Fix user can edit ast built-in services after upgrades - #35 Compatibility with core#2521 - AT2DX ARTemplate/SampleTemplate - #34 Add transition "Reject antibiotics" - #33 Display the Antibiotic Sensitivity section only when necessary From 7aa447c9bc7444c2adf92e865b9bb813477bbc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 2 May 2024 15:57:17 +0200 Subject: [PATCH 28/38] Remove pdb --- src/senaite/ast/setuphandlers.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/senaite/ast/setuphandlers.py b/src/senaite/ast/setuphandlers.py index 9ca39cf..06e7813 100644 --- a/src/senaite/ast/setuphandlers.py +++ b/src/senaite/ast/setuphandlers.py @@ -294,8 +294,6 @@ def revoke_permission(obj): security.revoke_permission_for(obj, ModifyPortalContent, roles) obj.reindexObject() - import pdb;pdb.set_trace() - # analysis services query = { "portal_type": "AnalysisService", From 7a5c9935363b51bf6feee8ce8d40443c369b3cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 13 Jun 2024 11:09:33 +0200 Subject: [PATCH 29/38] Compatibility with core#2471 --- src/senaite/ast/tests/doctests/AST.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/senaite/ast/tests/doctests/AST.rst b/src/senaite/ast/tests/doctests/AST.rst index 33e69e3..0c5dfde 100644 --- a/src/senaite/ast/tests/doctests/AST.rst +++ b/src/senaite/ast/tests/doctests/AST.rst @@ -44,7 +44,7 @@ We need to create some basic objects for the test: >>> contact = api.create(client, "Contact", Firstname="Rita", Lastname="Mohale") >>> sampletype = api.create(setup.bika_sampletypes, "SampleType", title="Blood", Prefix="B") >>> labcontact = api.create(setup.bika_labcontacts, "LabContact", Firstname="Lab", Lastname="Manager") - >>> department = api.create(setup.bika_departments, "Department", title="Microbiology", Manager=labcontact) + >>> department = api.create(portal.setup.departments, "Department", title="Microbiology", Manager=labcontact) >>> category = api.create(setup.bika_analysiscategories, "AnalysisCategory", title="Microbiology", Department=department) >>> g = api.create(setup.bika_analysisservices, "AnalysisService", title="GRAM Test", Keyword="G", Price="15", Category=category.UID(), Accredited=True) From 64d4bcb70c4e56cc780d5beb86b2c32c1cff9ab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 13 Jun 2024 11:10:43 +0200 Subject: [PATCH 30/38] Travis --> Github actions --- .github/workflows/build-and-test.yml | 30 ++++++++ .travis.yml | 21 ------ README.rst | 4 +- buildout.cfg | 95 ++------------------------ requirements.txt | 2 +- src/senaite/ast/tests/base.py | 64 ++++++++++------- src/senaite/ast/tests/layers.py | 75 -------------------- src/senaite/ast/tests/test_doctests.py | 4 +- travis.cfg | 22 ------ 9 files changed, 78 insertions(+), 239 deletions(-) create mode 100644 .github/workflows/build-and-test.yml delete mode 100644 .travis.yml delete mode 100644 src/senaite/ast/tests/layers.py delete mode 100644 travis.cfg diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..d03c05a --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,30 @@ +name: build and test senaite.ast +on: + - push + - pull_request +env: + PLONE_VERSION: "5.2" +jobs: + build-and-test: + runs-on: 'ubuntu-20.04' + container: + image: python:2.7.18-buster + steps: + - uses: actions/checkout@v3 + - name: cache eggs + uses: actions/cache@v3 + with: + key: eggs-cache-${{ hashFiles('buildout.cfg', 'requirements.txt') }} + path: | + eggs/ + - name: install + run: | + pip install virtualenv + virtualenv -p `which python` . + bin/pip install --upgrade pip + bin/pip install -r requirements.txt + bin/buildout -N -t 3 annotate + bin/buildout -N -t 3 + - name: test + run: | + bin/test -s senaite.ast.tests diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f97fdaa..0000000 --- a/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: ~> 1.0 -language: python -os: linux -dist: xenial -cache: - pip: true - directories: - - eggs -matrix: - fast_finish: true - include: - - python: "2.7" - env: PLONE_VERSION="5.2" -before_install: - - virtualenv -p `which python` . - - bin/pip install -r requirements.txt - - bin/buildout -N -t 3 annotate -install: - - bin/buildout -N -t 3 -script: - - bin/test -s senaite.ast diff --git a/README.rst b/README.rst index 1e8c076..192ab42 100644 --- a/README.rst +++ b/README.rst @@ -4,8 +4,8 @@ Antibiotic Sensitivity Testing (AST) for SENAITE .. image:: https://img.shields.io/pypi/v/senaite.ast.svg?style=flat-square :target: https://pypi.python.org/pypi/senaite.ast -.. image:: https://img.shields.io/travis/com/senaite/senaite.ast/master.svg?style=flat-square - :target: https://app.travis-ci.com/github/senaite/senaite.ast +.. image:: https://img.shields.io/github/actions/workflow/status/senaite/senaite.ast/build-and-test.yml?branch=2.x + :target: https://github.com/senaite/senaite.ast/actions/workflows/build-and-test.yml?query=branch:2.x .. image:: https://readthedocs.org/projects/pip/badge/ :target: https://senaiteast.readthedocs.org diff --git a/buildout.cfg b/buildout.cfg index 3f7ef16..4d67720 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,105 +1,18 @@ [buildout] -index = https://pypi.org/simple/ -extends = https://dist.plone.org/release/5.2-latest/versions.cfg -find-links = - https://dist.plone.org/release/5.2-latest/ - https://dist.plone.org/thirdparty/ +extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.cfg + +package-name = senaite.ast parts = instance test omelette - i18ndude - zopepy update_translations write_code_headers -eggs = - senaite.core - senaite.app.listing - senaite.app.spotlight - senaite.app.supermodel - senaite.impress - senaite.jsonapi - senaite.lims - senaite.abx - senaite.microorganism - senaite.ast - plone.reload - Products.PrintingMailHost - -extensions = mr.developer - -package-name = senaite.ast - -versions = versions -show-picked-versions = true - -plone-user = admin:admin - -develop = . -sources = sources -auto-checkout = * - [sources] -senaite.core = git https://github.com/senaite/senaite.core.git branch=2.x -senaite.app.listing = git https://github.com/senaite/senaite.app.listing.git branch=2.x -senaite.app.spotlight = git https://github.com/senaite/senaite.app.spotlight.git branch=2.x -senaite.app.supermodel = git https://github.com/senaite/senaite.app.supermodel.git branch=2.x -senaite.impress = git https://github.com/senaite/senaite.impress.git branch=2.x -senaite.jsonapi = git https://github.com/senaite/senaite.jsonapi.git branch=2.x -senaite.lims = git https://github.com/senaite/senaite.lims.git branch=2.x -senaite.abx = git https://github.com/senaite/senaite.abx.git -senaite.microorganism = git https://github.com/senaite/senaite.microorganism.git - -[instance] -recipe = plone.recipe.zope2instance -http-address = 127.0.0.1:8080 -user = ${buildout:plone-user} -wsgi = on -eggs = - Plone - plone.app.upgrade - ${buildout:package-name} - ${buildout:eggs} -deprecation-warnings = on -environment-vars = - zope_i18n_compile_mo_files true -zcml = - -[i18ndude] -unzip = true -recipe = zc.recipe.egg -eggs = i18ndude - -[update_translations] -recipe = collective.recipe.template -output = ${buildout:directory}/bin/update_translations -input = ${buildout:directory}/templates/update_translations.in -mode = 755 - -[write_code_headers] -recipe = collective.recipe.template -output = ${buildout:directory}/bin/write_code_headers -input = ${buildout:directory}/templates/write_code_headers.py.in -mode = 755 +senaite.core = git https://github.com/senaite/senaite.core.git [test] -recipe = zc.recipe.testrunner -defaults = ['--auto-color', '--auto-progress'] eggs = senaite.ast [test] - -[omelette] -recipe = collective.recipe.omelette -eggs = ${buildout:eggs} - -[zopepy] -recipe = zc.recipe.egg -eggs = ${instance:eggs} -interpreter = zopepy -scripts = zopepy - -[versions] -setuptools = -zc.buildout = diff --git a/requirements.txt b/requirements.txt index b65a7a0..1e1b3ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -setuptools==42.0.2 +setuptools==44.1.1 zc.buildout==2.13.3 wheel diff --git a/src/senaite/ast/tests/base.py b/src/senaite/ast/tests/base.py index ad490c7..07ea9e4 100644 --- a/src/senaite/ast/tests/base.py +++ b/src/senaite/ast/tests/base.py @@ -18,31 +18,45 @@ # Copyright 2020-2024 by it's authors. # Some rights reserved, see README and LICENSE. -from plone.app.testing import TEST_USER_ID -from plone.app.testing import setRoles -from plone.app.testing.bbb_at import PloneTestCase -from plone.protect.authenticator import createToken -from senaite.ast.tests.layers import BASE_TESTING +import transaction +from plone.app.testing import applyProfile +from plone.app.testing import FunctionalTesting +from plone.testing import zope +from senaite.core.tests.base import BaseTestCase +from senaite.core.tests.layers import BaseLayer -class BaseTestCase(PloneTestCase): - """Use for test cases which do not rely on the demo data +class SimpleTestLayer(BaseLayer): + + def setUpZope(self, app, configurationContext): + super(SimpleTestLayer, self).setUpZope(app, configurationContext) + + # Load ZCML + import senaite.abx + import senaite.microorganism + self.loadZCML(package=senaite.abx) + self.loadZCML(package=senaite.microorganism) + self.loadZCML(package=senaite.ast) + + # Install product and call its initialize() function + zope.installProduct(app, "senaite.abx") + zope.installProduct(app, "senaite.microorganism") + zope.installProduct(app, "senaite.ast") + + def setUpPloneSite(self, portal): + super(SimpleTestLayer, self).setUpPloneSite(portal) + applyProfile(portal, "senaite.ast:default") + transaction.commit() + + +SIMPLE_TEST_LAYER_FIXTURE = SimpleTestLayer() +SIMPLE_TESTING = FunctionalTesting( + bases=(SIMPLE_TEST_LAYER_FIXTURE, ), + name="senaite.ast:SimpleTesting" +) + + +class SimpleTestCase(BaseTestCase): + """Use for test cases which do not rely on demo data """ - layer = BASE_TESTING - - def setUp(self): - super(BaseTestCase, self).setUp() - # Fixing CSRF protection - # https://github.com/plone/plone.protect/#fixing-csrf-protection-failures-in-tests - self.request = self.layer["request"] - # Disable plone.protect for these tests - self.request.form["_authenticator"] = createToken() - # Eventuelly you find this also useful - self.request.environ["REQUEST_METHOD"] = "POST" - - setRoles(self.portal, TEST_USER_ID, ["LabManager", "Manager"]) - - # Default skin is set to "Sunburst Theme"! - # => This causes an `AttributeError` when we want to access - # e.g. 'guard_handler' FSPythonScript - self.portal.changeSkin("Plone Default") + layer = SIMPLE_TESTING diff --git a/src/senaite/ast/tests/layers.py b/src/senaite/ast/tests/layers.py deleted file mode 100644 index dafc302..0000000 --- a/src/senaite/ast/tests/layers.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -# -# This file is part of SENAITE.AST. -# -# SENAITE.AST is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright 2020-2024 by it's authors. -# Some rights reserved, see README and LICENSE. - -import transaction -from plone.app.testing import applyProfile -from plone.app.testing import FunctionalTesting -from plone.app.testing import PLONE_FIXTURE -from plone.app.testing import PloneSandboxLayer -from plone.testing import zope - - -class BaseLayer(PloneSandboxLayer): - defaultBases = (PLONE_FIXTURE,) - - def setUpZope(self, app, configurationContext): - super(BaseLayer, self).setUpZope(app, configurationContext) - - # Load ZCML - import bika.lims - import senaite.app.listing - import senaite.app.spotlight - import senaite.core - import senaite.abx - import senaite.ast - import senaite.impress - import senaite.microorganism - - self.loadZCML(package=bika.lims) - self.loadZCML(package=senaite.core) - self.loadZCML(package=senaite.app.listing) - self.loadZCML(package=senaite.app.spotlight) - self.loadZCML(package=senaite.impress) - self.loadZCML(package=senaite.lims) - self.loadZCML(package=senaite.abx) - self.loadZCML(package=senaite.microorganism) - self.loadZCML(package=senaite.ast) - - # Install product and call its initialize() function - zope.installProduct(app, "bika.lims") - zope.installProduct(app, "senaite.core") - zope.installProduct(app, "senaite.app.listing") - zope.installProduct(app, "senaite.app.spotlight") - zope.installProduct(app, "senaite.impress") - zope.installProduct(app, "senaite.lims") - zope.installProduct(app, "senaite.abx") - zope.installProduct(app, "senaite.microorganism") - zope.installProduct(app, "senaite.ast") - - def setUpPloneSite(self, portal): - # Install into Plone site using portal_setup - applyProfile(portal, "senaite.core:default") - applyProfile(portal, "senaite.ast:default") - transaction.commit() - - -BASE_LAYER_FIXTURE = BaseLayer() -BASE_TESTING = FunctionalTesting( - bases=(BASE_LAYER_FIXTURE,), name="SENAITE.AST:BaseTesting") diff --git a/src/senaite/ast/tests/test_doctests.py b/src/senaite/ast/tests/test_doctests.py index 2cb7b28..a472506 100644 --- a/src/senaite/ast/tests/test_doctests.py +++ b/src/senaite/ast/tests/test_doctests.py @@ -25,7 +25,7 @@ import unittest2 as unittest from senaite.ast import PRODUCT_NAME -from senaite.ast.tests.base import BaseTestCase +from senaite.ast.tests.base import SimpleTestCase from Testing import ZopeTestCase as ztc # Option flags for doctests @@ -38,7 +38,7 @@ def test_suite(): suite.addTests([ ztc.ZopeDocFileSuite( doctestfile, - test_class=BaseTestCase, + test_class=SimpleTestCase, optionflags=flags ) ]) diff --git a/travis.cfg b/travis.cfg deleted file mode 100644 index 0a97142..0000000 --- a/travis.cfg +++ /dev/null @@ -1,22 +0,0 @@ -[buildout] -extends = - buildout.cfg - -parts = - instance - test - -[test] -recipe = collective.xmltestreport -defaults = ['--auto-color', '--auto-progress'] -eggs = - senaite.ast [test] - -# network speedup -socket-timeout = 5 -allow-hosts = - *.python.org - docutils.sourceforge.net - prdownloads.sourceforge.net - effbot.org - dist.plone.org From c6ebfaa1080c674b8fda2243c1694984cf483773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 13 Jun 2024 11:13:21 +0200 Subject: [PATCH 31/38] Added dependencies in buildout --- buildout.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildout.cfg b/buildout.cfg index 4d67720..5ff1726 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -11,7 +11,9 @@ parts = write_code_headers [sources] +senaite.abx = git https://github.com/senaite/senaite.abx.git senaite.core = git https://github.com/senaite/senaite.core.git +senaite.microorganism = git https://github.com/senaite.microorganism.git [test] eggs = From 431fef39e8860f1dc2bc7079ac6085c764c055b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 13 Jun 2024 11:13:47 +0200 Subject: [PATCH 32/38] Typo --- buildout.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildout.cfg b/buildout.cfg index 5ff1726..de87560 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -13,7 +13,7 @@ parts = [sources] senaite.abx = git https://github.com/senaite/senaite.abx.git senaite.core = git https://github.com/senaite/senaite.core.git -senaite.microorganism = git https://github.com/senaite.microorganism.git +senaite.microorganism = git https://github.com/senaite/senaite.microorganism.git [test] eggs = From 52c13d6cdf5a2046c871963df5fae97c2b0a6539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 13 Jun 2024 11:24:33 +0200 Subject: [PATCH 33/38] buildout redux --- buildout.cfg | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/buildout.cfg b/buildout.cfg index de87560..3cc3ee7 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,20 +1,10 @@ [buildout] -extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.cfg +#extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.cfg +extends = https://raw.githubusercontent.com/senaite/senaite.core/buildouts-redux/buildout.base.cfg package-name = senaite.ast -parts = - instance - test - omelette - update_translations - write_code_headers - [sources] senaite.abx = git https://github.com/senaite/senaite.abx.git senaite.core = git https://github.com/senaite/senaite.core.git senaite.microorganism = git https://github.com/senaite/senaite.microorganism.git - -[test] -eggs = - senaite.ast [test] From f21f0ccdee01138f065897138c8e6be3982caf37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Thu, 13 Jun 2024 11:33:13 +0200 Subject: [PATCH 34/38] sources of senaite.core already provided by baseline buildout.cfg --- buildout.cfg | 2 -- 1 file changed, 2 deletions(-) diff --git a/buildout.cfg b/buildout.cfg index 3cc3ee7..db62886 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,10 +1,8 @@ [buildout] #extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.cfg extends = https://raw.githubusercontent.com/senaite/senaite.core/buildouts-redux/buildout.base.cfg - package-name = senaite.ast [sources] senaite.abx = git https://github.com/senaite/senaite.abx.git -senaite.core = git https://github.com/senaite/senaite.core.git senaite.microorganism = git https://github.com/senaite/senaite.microorganism.git From 0da0abc02b1c50b722ca6c509eb73aeb3eba7009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 15 Jun 2024 10:02:57 +0200 Subject: [PATCH 35/38] Fix buildout --- buildout.cfg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/buildout.cfg b/buildout.cfg index db62886..09f40a9 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,6 +1,5 @@ [buildout] -#extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.cfg -extends = https://raw.githubusercontent.com/senaite/senaite.core/buildouts-redux/buildout.base.cfg +extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.cfg package-name = senaite.ast [sources] From f64d024f868e44e95b12411fbebc8d3776779e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 15 Jun 2024 10:16:44 +0200 Subject: [PATCH 36/38] Compatibility with core#2567 --- src/senaite/ast/setuphandlers.py | 17 +++++++++-------- src/senaite/ast/tests/doctests/AST.rst | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/senaite/ast/setuphandlers.py b/src/senaite/ast/setuphandlers.py index 06e7813..ab4f224 100644 --- a/src/senaite/ast/setuphandlers.py +++ b/src/senaite/ast/setuphandlers.py @@ -153,9 +153,10 @@ def setup_ast_category(portal): """ name = SERVICE_CATEGORY logger.info("Setup category '{}' ...".format(name)) - folder = api.get_setup().bika_analysiscategories - exists = filter(lambda c: api.get_title(c) == name, folder.objectValues()) - if exists: + setup = api.get_senaite_setup() + folder = setup.analysiscategories + categories = search_by_title(folder, name) + if categories: logger.info("Category '{}' exists already [SKIP]".format(name)) return @@ -199,15 +200,15 @@ def setup_ast_services(portal, update_existing=True): selective reporting """ logger.info("Setup AST services ...") + + # Get the category to apply to all AST services + cats_folder = api.get_senaite_setup().analysiscategories + category = search_by_title(cats_folder, SERVICE_CATEGORY)[0] + setup = api.get_setup() for key, settings in SERVICES_SETTINGS.items(): logger.info("Setup template service '{}' ...".format(key)) - # Get the category - cat_name = SERVICE_CATEGORY - categories = setup.bika_analysiscategories.objectValues() - category = filter(lambda c: api.get_title(c) == cat_name, categories)[0] - title = settings["title"] if "{}" in title: title = title.format(_("Antibiotic Sensitivity")) diff --git a/src/senaite/ast/tests/doctests/AST.rst b/src/senaite/ast/tests/doctests/AST.rst index 0c5dfde..e4206c9 100644 --- a/src/senaite/ast/tests/doctests/AST.rst +++ b/src/senaite/ast/tests/doctests/AST.rst @@ -45,7 +45,7 @@ We need to create some basic objects for the test: >>> sampletype = api.create(setup.bika_sampletypes, "SampleType", title="Blood", Prefix="B") >>> labcontact = api.create(setup.bika_labcontacts, "LabContact", Firstname="Lab", Lastname="Manager") >>> department = api.create(portal.setup.departments, "Department", title="Microbiology", Manager=labcontact) - >>> category = api.create(setup.bika_analysiscategories, "AnalysisCategory", title="Microbiology", Department=department) + >>> category = api.create(portal.setup.analysiscategories, "AnalysisCategory", title="Microbiology", Department=department) >>> g = api.create(setup.bika_analysisservices, "AnalysisService", title="GRAM Test", Keyword="G", Price="15", Category=category.UID(), Accredited=True) From 688ac5bbf5f96d71b7ecb6f8b5a28b14d881c3b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 15 Jun 2024 10:19:09 +0200 Subject: [PATCH 37/38] Changelog --- docs/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 34473aa..b341443 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,8 @@ Changelog 1.2.0 (unreleased) ------------------ +- #37 Compatibility with core#2567 (AnalysisCategory to DX) +- #37 Compatibility with core#2471 (Department to DX) - #36 Fix user can edit ast built-in services after upgrades - #35 Compatibility with core#2521 - AT2DX ARTemplate/SampleTemplate - #34 Add transition "Reject antibiotics" From e6d9dd6bf1825ed65747972f4329eed1949c1332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= Date: Sat, 15 Jun 2024 10:20:38 +0200 Subject: [PATCH 38/38] Fix buildout --- buildout.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildout.cfg b/buildout.cfg index 09f40a9..754c187 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,5 +1,5 @@ [buildout] -extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.cfg +extends = https://raw.githubusercontent.com/senaite/senaite.core/2.x/buildout.base.cfg package-name = senaite.ast [sources]