Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catalog mapping for Samples and Analyses #2130

Merged
merged 11 commits into from
Sep 21, 2022
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changelog
2.3.0 (unreleased)
------------------

- #2130 Catalog mapping for Samples and Analyses
- #2131 Allow to edit the analysis service sort keys in the services listing
- #2133 Filter Contact and CCContact by Client on first click
- #2134 Render unit after result and interim fields
Expand Down
125 changes: 77 additions & 48 deletions src/senaite/core/setuphandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@
from senaite.core.api.catalog import get_columns
from senaite.core.api.catalog import get_indexes
from senaite.core.api.catalog import reindex_index
from senaite.core.catalog import ANALYSIS_CATALOG
from senaite.core.catalog import AUDITLOG_CATALOG
from senaite.core.catalog import AUTOIMPORTLOG_CATALOG
from senaite.core.catalog import REPORT_CATALOG
from senaite.core.catalog import SAMPLE_CATALOG
from senaite.core.catalog import SENAITE_CATALOG
from senaite.core.catalog import SETUP_CATALOG
from senaite.core.catalog import WORKSHEET_CATALOG
from senaite.core.catalog import AnalysisCatalog
from senaite.core.catalog import AuditlogCatalog
from senaite.core.catalog import AutoImportLogCatalog
Expand All @@ -57,6 +64,8 @@
class INonInstallable(Interface):
pass

PORTAL_CATALOG = "portal_catalog"


@implementer(INonInstallable)
class HiddenProfiles(object):
Expand Down Expand Up @@ -105,62 +114,82 @@ def getNonInstallableProfiles(self):

INDEXES = (
# catalog, id, indexed attribute, type
("portal_catalog", "Analyst", "", "FieldIndex"),
("portal_catalog", "analysisRequestTemplates", "", "FieldIndex"),
("portal_catalog", "getFullname", "", "FieldIndex"),
("portal_catalog", "getName", "", "FieldIndex"),
("portal_catalog", "getParentUID", "", "FieldIndex"),
("portal_catalog", "getUsername", "", "FieldIndex"),
("portal_catalog", "is_active", "", "BooleanIndex"),
("portal_catalog", "path", "getPhysicalPath", "ExtendedPathIndex"),
("portal_catalog", "review_state", "", "FieldIndex"),
("portal_catalog", "sample_uid", "", "KeywordIndex"),
("portal_catalog", "title", "", "FieldIndex"),
(PORTAL_CATALOG, "Analyst", "", "FieldIndex"),
(PORTAL_CATALOG, "analysisRequestTemplates", "", "FieldIndex"),
(PORTAL_CATALOG, "getFullname", "", "FieldIndex"),
(PORTAL_CATALOG, "getName", "", "FieldIndex"),
(PORTAL_CATALOG, "getParentUID", "", "FieldIndex"),
(PORTAL_CATALOG, "getUsername", "", "FieldIndex"),
(PORTAL_CATALOG, "is_active", "", "BooleanIndex"),
(PORTAL_CATALOG, "path", "getPhysicalPath", "ExtendedPathIndex"),
(PORTAL_CATALOG, "review_state", "", "FieldIndex"),
(PORTAL_CATALOG, "sample_uid", "", "KeywordIndex"),
(PORTAL_CATALOG, "title", "", "FieldIndex"),
)

COLUMNS = (
# catalog, column name
("portal_catalog", "analysisRequestTemplates"),
("portal_catalog", "review_state"),
("portal_catalog", "getClientID"),
("portal_catalog", "Analyst"),
(PORTAL_CATALOG, "analysisRequestTemplates"),
(PORTAL_CATALOG, "review_state"),
(PORTAL_CATALOG, "getClientID"),
(PORTAL_CATALOG, "Analyst"),
)

CATALOG_MAPPINGS = (
# portal_type, catalog_ids
("ARReport", ["senaite_catalog_report", "portal_catalog"]),
("ARTemplate", ["senaite_catalog_setup", "portal_catalog"]),
("AnalysisCategory", ["senaite_catalog_setup", "portal_catalog"]),
("AnalysisProfile", ["senaite_catalog_setup", "portal_catalog"]),
("AnalysisService", ["senaite_catalog_setup", "portal_catalog"]),
("AnalysisSpec", ["senaite_catalog_setup", "portal_catalog"]),
("Attachment", ["senaite_catalog", "portal_catalog"]),
("AttachmentType", ["senaite_catalog_setup", "portal_catalog"]),
("Batch", ["senaite_catalog", "portal_catalog"]),
("BatchLabel", ["senaite_catalog_setup", "portal_catalog"]),
("Calculation", ["senaite_catalog_setup", "portal_catalog"]),
("Container", ["senaite_catalog_setup", "portal_catalog"]),
("ContainerType", ["senaite_catalog_setup", "portal_catalog"]),
("Department", ["senaite_catalog_setup", "portal_catalog"]),
("Instrument", ["senaite_catalog_setup", "portal_catalog"]),
("InstrumentType", ["senaite_catalog_setup", "portal_catalog"]),
("LabContact", ["senaite_catalog_setup", "portal_catalog"]),
("LabProduct", ["senaite_catalog_setup", "portal_catalog"]),
("Manufacturer", ["senaite_catalog_setup", "portal_catalog"]),
("Method", ["senaite_catalog_setup", "portal_catalog"]),
("Multifile", ["senaite_catalog_setup", "portal_catalog"]),
("Preservation", ["senaite_catalog_setup", "portal_catalog"]),
("ReferenceDefinition", ["senaite_catalog_setup", "portal_catalog"]),
("ReferenceSample", ["senaite_catalog", "portal_catalog"]),
("SampleCondition", ["senaite_catalog_setup", "portal_catalog"]),
("SampleMatrix", ["senaite_catalog_setup", "portal_catalog"]),
("SamplePoint", ["senaite_catalog_setup", "portal_catalog"]),
("SampleType", ["senaite_catalog_setup", "portal_catalog"]),
("SamplingDeviation", ["senaite_catalog_setup", "portal_catalog"]),
("StorageLocation", ["senaite_catalog_setup", "portal_catalog"]),
("SubGroup", ["senaite_catalog_setup", "portal_catalog"]),
("Supplier", ["senaite_catalog_setup", "portal_catalog"]),
("WorksheetTemplate", ["senaite_catalog_setup", "portal_catalog"]),
("ARReport", [REPORT_CATALOG, PORTAL_CATALOG]),
("ARTemplate", [SETUP_CATALOG, PORTAL_CATALOG]),
("Analysis", [ANALYSIS_CATALOG]),
("AnalysisCategory", [SETUP_CATALOG, PORTAL_CATALOG]),
("AnalysisProfile", [SETUP_CATALOG, PORTAL_CATALOG]),
("AnalysisRequest", [SAMPLE_CATALOG]),
("AnalysisService", [SETUP_CATALOG, PORTAL_CATALOG]),
("AnalysisSpec", [SETUP_CATALOG, PORTAL_CATALOG]),
("Attachment", [SENAITE_CATALOG, PORTAL_CATALOG]),
("AttachmentType", [SETUP_CATALOG, PORTAL_CATALOG]),
("AutoImportLog", [AUTOIMPORTLOG_CATALOG, PORTAL_CATALOG]),
("Batch", [SENAITE_CATALOG, PORTAL_CATALOG]),
("BatchLabel", [SETUP_CATALOG, PORTAL_CATALOG]),
("Calculation", [SETUP_CATALOG, PORTAL_CATALOG]),
("Client", [PORTAL_CATALOG]),
("Contact", [PORTAL_CATALOG]),
("Container", [SETUP_CATALOG, PORTAL_CATALOG]),
("ContainerType", [SETUP_CATALOG, PORTAL_CATALOG]),
("Department", [SETUP_CATALOG, PORTAL_CATALOG]),
("DuplicateAnalysis", [ANALYSIS_CATALOG, PORTAL_CATALOG]),
("Instrument", [SETUP_CATALOG, PORTAL_CATALOG]),
("InstrumentCalibration", [SETUP_CATALOG, PORTAL_CATALOG]),
("InstrumentCertification", [SETUP_CATALOG, PORTAL_CATALOG]),
("InstrumentLocation", [SETUP_CATALOG, PORTAL_CATALOG]),
("InstrumentMaintenanceTask", [SETUP_CATALOG, PORTAL_CATALOG]),
("InstrumentScheduledTask", [SETUP_CATALOG, PORTAL_CATALOG]),
("InstrumentType", [SETUP_CATALOG, PORTAL_CATALOG]),
("InstrumentValidation", [SETUP_CATALOG, PORTAL_CATALOG]),
("Invoice", [SENAITE_CATALOG, PORTAL_CATALOG]),
("LabContact", [SETUP_CATALOG, PORTAL_CATALOG]),
("LabProduct", [SETUP_CATALOG, PORTAL_CATALOG]),
("Laboratory", [SETUP_CATALOG, PORTAL_CATALOG]),
("Manufacturer", [SETUP_CATALOG, PORTAL_CATALOG]),
("Method", [SETUP_CATALOG, PORTAL_CATALOG]),
("Multifile", [SETUP_CATALOG, PORTAL_CATALOG]),
("Preservation", [SETUP_CATALOG, PORTAL_CATALOG]),
("Pricelist", [SETUP_CATALOG, PORTAL_CATALOG]),
("ReferenceAnalysis", [ANALYSIS_CATALOG, PORTAL_CATALOG]),
("ReferenceDefinition", [SETUP_CATALOG, PORTAL_CATALOG]),
("ReferenceSample", [SENAITE_CATALOG, PORTAL_CATALOG]),
("RejectAnalysis", [ANALYSIS_CATALOG, PORTAL_CATALOG]),
("Report", [REPORT_CATALOG, PORTAL_CATALOG]),
("SampleCondition", [SETUP_CATALOG, PORTAL_CATALOG]),
("SampleMatrix", [SETUP_CATALOG, PORTAL_CATALOG]),
("SamplePoint", [SETUP_CATALOG, PORTAL_CATALOG]),
("SampleType", [SETUP_CATALOG, PORTAL_CATALOG]),
("SamplingDeviation", [SETUP_CATALOG, PORTAL_CATALOG]),
("StorageLocation", [SETUP_CATALOG, PORTAL_CATALOG]),
("SubGroup", [SETUP_CATALOG, PORTAL_CATALOG]),
("Supplier", [SETUP_CATALOG, PORTAL_CATALOG]),
("SupplierContact", [SETUP_CATALOG, PORTAL_CATALOG]),
("Worksheet", [WORKSHEET_CATALOG, PORTAL_CATALOG]),
("WorksheetTemplate", [SETUP_CATALOG, PORTAL_CATALOG]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some content types are missing, like Worksheet, DuplicateAnalysis, ReferenceAnalysis, Contact, InstrumentCalibration, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other types were added by the setuphandler setup_core_catalogs which maps the types from here:

TYPES = [
# portal_type name
"Analysis",
"ReferenceAnalysis",
"DuplicateAnalysis",
]

However, for completeness I added the missing types in 9adcd93 from here:
https://github.com/senaite/senaite.core/blob/2.x/src/bika/lims/__init__.py#L57-L121

)


Expand Down
80 changes: 80 additions & 0 deletions src/senaite/core/tests/doctests/Catalogs.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
Catalogs
--------

SENAITE comes with several catalogs to index specific objects.
For Archetype objects, the catalog mapping is done in `archetype_tool`.


Running this test from the buildout directory::

bin/test test_textual_doctests -t Catalogs


Test Setup
..........

Needed Imports::

>>> from bika.lims import api

>>> from senaite.core.catalog import ANALYSIS_CATALOG
>>> from senaite.core.catalog import AUDITLOG_CATALOG
>>> from senaite.core.catalog import SAMPLE_CATALOG
>>> from senaite.core.setuphandlers import CATALOG_MAPPINGS


Variables::

>>> portal = self.portal
>>> request = self.request
>>> archetype_tool = api.get_tool("archetype_tool")


Catalog Mappings
................

Catalogs should be mapped according to the catalog mappings:

>>> passed = {}

>>> for mapping in CATALOG_MAPPINGS:
... portal_type, catalogs = mapping
... mapped = archetype_tool.catalog_map.get(portal_type)
... passed[portal_type] = set(catalogs).issubset(mapped)

>>> all(passed.values())
True


Sample Catalog
..............

Samples should be registered in the sample catalog:

>>> catmap = archetype_tool.catalog_map.get("AnalysisRequest")

>>> len(catmap)
2

>>> SAMPLE_CATALOG in catmap
True

>>> AUDITLOG_CATALOG in catmap
True


Analysis Catalog
................

Analyses should be registered in the analysis catalog:

>>> catmap = archetype_tool.catalog_map.get("Analysis")

>>> len(catmap)
2

>>> ANALYSIS_CATALOG in catmap
True

>>> AUDITLOG_CATALOG in catmap
True
9 changes: 9 additions & 0 deletions src/senaite/core/upgrade/v02_03_000.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@
from senaite.core.catalog import SETUP_CATALOG
from senaite.core.catalog.report_catalog import ReportCatalog
from senaite.core.config import PROJECTNAME as product
from senaite.core.setuphandlers import CATALOG_MAPPINGS
from senaite.core.setuphandlers import _run_import_step
from senaite.core.setuphandlers import add_senaite_setup
from senaite.core.setuphandlers import setup_auditlog_catalog_mappings
from senaite.core.setuphandlers import setup_catalog_mappings
from senaite.core.setuphandlers import setup_core_catalogs
from senaite.core.upgrade import upgradestep
from senaite.core.upgrade.utils import UpgradeUtils
Expand Down Expand Up @@ -70,6 +73,12 @@ def upgrade(tool):
setup.runImportStepFromProfile(profile, "plone.app.registry")
setup.runImportStepFromProfile(profile, "controlpanel")

# Ensure the catalog mappings for Analyses and Samples is correct
# https://github.com/senaite/senaite.core/pull/2130
setup_catalog_mappings(portal, catalog_mappings=CATALOG_MAPPINGS)
# remap auditlog catalog
setup_auditlog_catalog_mappings(portal)

# Add new setup folder to portal
add_senaite_setup(portal)

Expand Down