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

Purge stale metadata and indexes from analysis catalog #1724

Merged
merged 13 commits into from
Jan 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
2.0.0rc3 (unreleased)
---------------------

- #1724 Purge stale metadata and indexes from analysis catalog
- #1720 Fix UnicodeDecodeError for Instrument Import Log View
- #1719 Service/Method/Calculation relationship handling
- #1717 Port workflow definitions to senaite namespace
Expand Down
5 changes: 2 additions & 3 deletions src/bika/lims/browser/worksheet/views/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,8 @@ def checkInstrumentsValidity(self):
invalid = []
ans = self.context.getAnalyses()
for an in ans:
valid = an.isInstrumentValid()
if not valid:
instrument = an.getInstrument()
instrument = an.getInstrument()
if instrument and not instrument.isValid():
inv = "%s (%s)" % (
safe_unicode(an.Title()), safe_unicode(instrument.Title()))
if inv not in invalid:
Expand Down
14 changes: 0 additions & 14 deletions src/bika/lims/catalog/analysis_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
# Defining the indexes for this catalog
_indexes_dict = {
"sortable_title": "FieldIndex",
"getParentUID": "FieldIndex",
"getDueDate": "DateIndex",
"getDateReceived": "DateIndex",
"getResultCaptureDate": "DateIndex",
Expand All @@ -50,17 +49,13 @@
"getCategoryUID": "FieldIndex",
"getPointOfCapture": "FieldIndex",
"getSampleTypeUID": "FieldIndex",
# TODO Index "getSamplePointUID" is only used in reports/selection_macros
"getSamplePointUID": "FieldIndex",
"getReferenceAnalysesGroupID": "FieldIndex",
"getMethodUID": "FieldIndex",
"getInstrumentUID": "FieldIndex",
"getWorksheetUID": "FieldIndex",
"getOriginalReflexedAnalysisUID": "FieldIndex",
"getPrioritySortkey": "FieldIndex",
"getAncestorsUIDs": "KeywordIndex",
"isSampleReceived": "BooleanIndex",
"isRetest": "BooleanIndex",
}
# Defining the columns for this catalog
_columns_list = [
Expand All @@ -69,13 +64,10 @@
"getResultCaptureDate",
"getParentURL",
"getRequestURL",
"getParentTitle",
"getParentUID",
"getClientTitle",
"getClientURL",
"getRequestTitle",
"getResult",
"getCalculationUID",
"getUnit",
"getKeyword",
"getCategoryTitle",
Expand All @@ -86,12 +78,9 @@
"getReferenceResults",
# Used in duplicated analysis objects
"getAnalysisPortalType",
"isInstrumentValid",
# Columns from method
"getMethodUID",
"getMethodTitle",
"getMethodURL",
"getAllowedMethodUIDs",
"getAnalyst",
"getAnalystName",
"getNumberOfRequiredVerifications",
Expand All @@ -106,9 +95,6 @@
# defined as a service metacolumn instead of an analysis one
"getResultOptions",
"getServiceUID",
"getInstrumentEntryOfResults",
"getAllowedInstrumentUIDs",
"getInstrumentUID",
"getSampleTypeUID",
"getClientOrderNumber",
"getDateReceived",
Expand Down
2 changes: 0 additions & 2 deletions src/bika/lims/catalog/analysisrequest_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@
"getContactFullName",
"getSampleTypeUID",
"getSampleTypeTitle",
# TODO Index "getSamplePointUID" is only used in reports/selection_macros
"getSamplePointUID",
"getSamplePointTitle",
"getStorageLocationUID",
"getStorageLocationTitle",
Expand Down
53 changes: 2 additions & 51 deletions src/bika/lims/content/abstractanalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -675,18 +675,6 @@ def getLateness(self):
"""
return -self.getEarliness()

@security.public
def isInstrumentValid(self):
"""Checks if the instrument selected for this analysis is valid.
Returns false if an out-of-date or uncalibrated instrument is
assigned.
:return: True if the Analysis has no instrument assigned or is valid
:rtype: bool
"""
if self.getInstrument():
return self.getInstrument().isValid()
return True

@security.public
def isInstrumentAllowed(self, instrument):
"""Checks if the specified instrument can be set for this analysis,
Expand All @@ -696,7 +684,7 @@ def isInstrumentAllowed(self, instrument):
:rtype: bool
"""
uid = api.get_uid(instrument)
return uid in self.getAllowedInstrumentUIDs()
return uid in map(api.get_uid, self.getAllowedInstruments())

@security.public
def isMethodAllowed(self, method):
Expand All @@ -707,7 +695,7 @@ def isMethodAllowed(self, method):
:rtype: bool
"""
uid = api.get_uid(method)
return uid in self.getAllowedMethodUIDs()
return uid in map(api.get_uid, self.getAllowedMethods())

@security.public
def getAllowedMethods(self):
Expand All @@ -724,15 +712,6 @@ def getAllowedMethods(self):
# get the available methods of the service
return service.getMethods()

@security.public
def getAllowedMethodUIDs(self):
"""Used to populate getAllowedMethodUIDs metadata. Delegates to
method getAllowedMethods() for the retrieval of the methods allowed.
:return: A list with the UIDs of the methods allowed for this analysis
:rtype: list of strings
"""
return map(api.get_uid, self.getAllowedMethods())

@security.public
def getAllowedInstruments(self):
"""Returns the allowed instruments from the service
Expand All @@ -745,15 +724,6 @@ def getAllowedInstruments(self):
return []
return service.getInstruments()

@security.public
def getAllowedInstrumentUIDs(self):
"""Used to populate getAllowedInstrumentUIDs metadata. Delegates to
getAllowedInstruments() for the retrieval of the instruments allowed.
:return: List of instruments' UIDs allowed for this analysis
:rtype: list of strings
"""
return map(api.get_uid, self.getAllowedInstruments())

@security.public
def getExponentialFormatPrecision(self, result=None):
""" Returns the precision for the Analysis Service and result
Expand Down Expand Up @@ -1039,15 +1009,6 @@ def getStartProcessDate(self):
"""
return self.created()

@security.public
def getParentUID(self):
"""This method is used to populate catalog values
This function returns the analysis' parent UID
"""
parent = self.aq_parent
if parent:
return parent.UID()

@security.public
def getParentURL(self):
"""This method is used to populate catalog values
Expand Down Expand Up @@ -1088,16 +1049,6 @@ def getWorksheet(self):
% self.getId())
return worksheet[0]

@security.public
def getInstrumentValid(self):
"""Used to populate catalog values. Delegates to isInstrumentValid()
Returns false if an out-of-date or uncalibrated instrument is
assigned.
:return: True if the Analysis has no instrument assigned or is valid
:rtype: bool
"""
return self.isInstrumentValid()

@security.public
def remove_duplicates(self, ws):
"""When this analysis is unassigned from a worksheet, this function
Expand Down
8 changes: 0 additions & 8 deletions src/bika/lims/content/abstractbaseanalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -898,14 +898,6 @@ def _getNumberOfRequiredVerificationsVocabulary(self):
items = [(-1, bsval), (1, '1'), (2, '2'), (3, '3'), (4, '4')]
return IntDisplayList(list(items))

@security.public
def getInstrumentEntryOfResults(self):
"""XXX: ALWAYS ALLOW INSTRUMENT RESULTS

TODO: Remove if refactored
"""
return True

@security.public
def getMethodTitle(self):
"""This is used to populate catalog values
Expand Down
16 changes: 0 additions & 16 deletions src/bika/lims/content/abstractroutineanalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,14 +247,6 @@ def getSamplePoint(self):
return request.getSamplePoint()
return None

@security.public
def getSamplePointUID(self):
"""Used to populate catalog values.
"""
sample_point = self.getSamplePoint()
if sample_point:
return api.get_uid(sample_point)

@security.public
def getDueDate(self):
"""Used to populate getDueDate index and metadata.
Expand Down Expand Up @@ -354,14 +346,6 @@ def getCalculation(self):
return None
return calculation

@security.public
def getCalculationUID(self):
"""Used to populate catalog values
"""
calculation = self.getCalculation()
if calculation:
return calculation.UID()

@security.public
def getDependents(self, with_retests=False, recursive=False):
"""
Expand Down
2 changes: 1 addition & 1 deletion src/bika/lims/workflow/duplicateanalysis/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def after_retract(duplicate_analysis):
worksheet.setAnalyses(worksheet.getAnalyses() + [retest, ])

# Reindex
retest.reindexObject(idxs=["getAnalyst", "getWorksheetUID", "isRetest",
retest.reindexObject(idxs=["getAnalyst", "getWorksheetUID",
"getReferenceAnalysesGroupID"])
worksheet.reindexObject(idxs=["getAnalysesUIDs"])

Expand Down
3 changes: 0 additions & 3 deletions src/bika/lims/workflow/indexes.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
"getAnalyst",
"getDueDate",
"getInstrumentUID",
"getMethodUID",
"getResultCaptureDate",
],
"unassign": [
Expand All @@ -62,7 +61,6 @@
"getAnalyst",
"getDueDate",
"getInstrumentUID",
"getMethodUID",
"getResultCaptureDate",
],
"unassign": None,
Expand All @@ -79,7 +77,6 @@
"getAnalyst",
"getDueDate",
"getInstrumentUID",
"getMethodUID",
"getResultCaptureDate",
"review_state",
],
Expand Down
1 change: 0 additions & 1 deletion src/senaite/core/tests/doctests/WorksheetApplyTemplate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,6 @@ Re-assign the worksheet template:

The worksheet now contains the two analyses:

>>> worksheet.applyWorksheetTemplate(method_template)
>>> ws_analyses = worksheet.getAnalyses()
>>> len(ws_analyses)
2
Expand Down
41 changes: 40 additions & 1 deletion src/senaite/core/upgrade/v02_00_000.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,30 @@
(SETUP_CATALOG, "department_id", "KeywordIndex"),
]

INDEXES_TO_REMOVE = [
# List of tuples (catalog_name, index_name)
(CATALOG_ANALYSIS_LISTING, "getMethodUID"),
(CATALOG_ANALYSIS_LISTING, "isRetest"),
(CATALOG_ANALYSIS_LISTING, "getSamplePointUID"),
(CATALOG_ANALYSIS_LISTING, "getParentUID"),
]

METADATA_TO_REMOVE = [
# Only used in Analyses listing and it's behavior is bizarre, probably
# because is a dict and requires special care with ZODB
(CATALOG_ANALYSIS_LISTING, "getInterimFields"),
# No longer used, see https://github.com/senaite/senaite.core/pull/1709/
(CATALOG_ANALYSIS_LISTING, "getAttachmentUIDs")
(CATALOG_ANALYSIS_LISTING, "getAttachmentUIDs"),
(CATALOG_ANALYSIS_LISTING, "getInstrumentEntryOfResults"),
(CATALOG_ANALYSIS_LISTING, "getCalculationUID"),
(CATALOG_ANALYSIS_LISTING, "getAllowedInstrumentUIDs"),
(CATALOG_ANALYSIS_LISTING, "getMethodUID"),
(CATALOG_ANALYSIS_LISTING, "getAllowedMethodUIDs"),
(CATALOG_ANALYSIS_LISTING, "getInstrumentUID"),
(CATALOG_ANALYSIS_REQUEST_LISTING, "getSamplePointUID"),
(CATALOG_ANALYSIS_LISTING, "getParentUID"),
(CATALOG_ANALYSIS_LISTING, "getParentTitle"),
(CATALOG_ANALYSIS_LISTING, "isInstrumentValid"),
]

STALE_WORKFLOW_DEFINITIONS = [
Expand Down Expand Up @@ -177,6 +195,9 @@ def upgrade(tool):
remove_supplyorder_typeinfo(portal)
remove_supplyorder_workflow(portal)

# Remove stale indexes
remove_stale_indexes(portal)

# Remove stale metadata
remove_stale_metadata(portal)

Expand Down Expand Up @@ -497,6 +518,24 @@ def del_metadata(catalog_id, column):
catalog.delColumn(column)


def remove_stale_indexes(portal):
logger.info("Removing stale indexes ...")
for catalog_id, index_name in INDEXES_TO_REMOVE:
del_index(portal, catalog_id, index_name)
logger.info("Removing stale indexes ... [DONE]")


def del_index(portal, catalog_id, index_name):
logger.info("Removing '{}' index from '{}' ..."
.format(index_name, catalog_id))
catalog = api.get_tool(catalog_id)
if index_name not in catalog.indexes():
logger.info("Index '{}' not in catalog '{}' [SKIP]"
.format(index_name, catalog_id))
return
catalog.delIndex(index_name)


def remove_at_portal_types(portal):
"""Remove AT portal type information
"""
Expand Down