Skip to content

Commit ff1102e

Browse files
xisparamonski
andauthored
Fix samples w/o active analyses are displayed under "unassigned" filter (senaite#2066)
* Fix samples w/o active analyses are displayed under "unassigned" filter * Whitespace end of file * Take partitions into consideration Co-authored-by: Ramon Bartl <[email protected]>
1 parent 696054e commit ff1102e

File tree

3 files changed

+77
-11
lines changed

3 files changed

+77
-11
lines changed

CHANGES.rst

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Changelog
55
2.3.0 (unreleased)
66
------------------
77

8+
- #2066 Fix samples w/o active analyses are displayed under "unassigned" filter
89
- #2065 Fix "Create Worksheet" modal visible for samples w/o unassigned analyses
910
- #2063 Allow to customize email publication template in setup
1011
- #2062 Fix listing not updated after instrument assignment in Worksheet's view

src/senaite/core/catalog/indexer/sample.py

+48-11
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,56 @@
1010

1111
@indexer(IAnalysisRequest)
1212
def assigned_state(instance):
13-
"""Returns `assigned` or `unassigned` depending on the state of the
14-
analyses the analysisrequest contains. Return `unassigned` if the Analysis
15-
Request has at least one analysis in `unassigned` state.
16-
Otherwise, returns `assigned`
13+
"""Returns `assigned`, `unassigned` or 'not_applicable' depending on the
14+
state of the analyses the analysisrequest contains. Return `unassigned` if
15+
the Analysis Request has at least one 'active' analysis in `unassigned`
16+
status. Returns 'assigned' if all 'active' analyses of the sample are
17+
assigned to a Worksheet. Returns 'not_applicable' if no 'active' analyses
18+
for the given sample exist
1719
"""
18-
analyses = instance.getAnalyses()
19-
if not analyses:
20-
return "unassigned"
21-
for analysis in analyses:
22-
analysis_object = api.get_object(analysis)
23-
if not analysis_object.getWorksheet():
20+
assigned = False
21+
skip_statuses = ["retracted", "rejected", "cancelled"]
22+
23+
# Retrieve analyses directly from the instance container instead of relying
24+
# on ARAnalysesField getter, that performs a catalog query. Reason is, that
25+
# we never know if the sample is indexed before the analyses or any other
26+
# dependent catalog
27+
for analysis in instance.objectValues(spec="Analysis"):
28+
status = api.get_review_status(analysis)
29+
30+
if status == "unassigned":
31+
# One unassigned found, no need to go further
2432
return "unassigned"
25-
return "assigned"
33+
34+
if status in skip_statuses:
35+
# Skip "inactive" analyses
36+
continue
37+
38+
if analysis.getWorksheetUID():
39+
# At least one analysis with a worksheet assigned
40+
assigned = True
41+
42+
# ARAnalysesField getter returns all the analyses from the sample, those
43+
# from partitions included. Since we do not rely on the getter, we need to
44+
# manually extract the analyses from the partitions
45+
# Pity is, that for the retrieval of partitions we need to rely on
46+
# getBackReferences, that is a query against reference_catalog
47+
for partition in instance.getDescendants():
48+
# Note we call this same index, but for the partition
49+
partition_status = assigned_state(partition)()
50+
if partition_status == "unassigned":
51+
# One of the partitions with unassigned, no need to go further
52+
return "unassigned"
53+
54+
elif partition_status == "assigned":
55+
assigned = True
56+
57+
if assigned:
58+
# All "active" analyses assigned to a worksheet
59+
return "assigned"
60+
61+
# Sample without "active" assigned/unassigned analyses
62+
return "not_applicable"
2663

2764

2865
@indexer(IAnalysisRequest)

src/senaite/core/upgrade/v02_03_000.py

+28
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ def upgrade(tool):
7373
fix_worksheets_analyses(portal)
7474
fix_cannot_create_partitions(portal)
7575
fix_interface_interpretation_template(portal)
76+
fix_unassigned_samples(portal)
7677

7778
logger.info("{0} upgraded to version {1}".format(product, version))
7879
return True
@@ -176,3 +177,30 @@ def fix_interface_interpretation_template(portal):
176177
fti = pt.get("InterpretationTemplate")
177178
fti.schema = "senaite.core.content.interpretationtemplate.IInterpretationTemplateSchema"
178179
logger.info("Fix interface for InterpretationTemplate FTI ...")
180+
181+
182+
def fix_unassigned_samples(portal):
183+
"""Reindex the 'assigned_state' index for samples
184+
"""
185+
logger.info("Fix unassigned samples ...")
186+
indexes = ["assigned_state"]
187+
query = {
188+
"portal_type": "AnalysisRequest",
189+
"assigned_state": "unassigned",
190+
}
191+
cat = api.get_tool(SAMPLE_CATALOG)
192+
samples = api.search(query, SAMPLE_CATALOG)
193+
total = len(samples)
194+
for num, sample in enumerate(samples):
195+
196+
if num and num % 100 == 0:
197+
logger.info("Fix unassigned samples {0}/{1}".format(num, total))
198+
199+
obj = api.get_object(sample)
200+
obj_url = api.get_path(sample)
201+
cat.catalog_object(obj, obj_url, idxs=indexes, update_metadata=1)
202+
203+
# Flush the object from memory
204+
obj._p_deactivate() # noqa
205+
206+
logger.info("Fix unassigned samples ...")

0 commit comments

Comments
 (0)