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

Fix Samples not sorted in natural order when Worksheet Template is used #1673

Merged
merged 1 commit into from
Nov 5, 2020
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Changelog

**Fixed**

- #1673 Fix Samples not sorted in natural order when Worksheet Template is used
- #1656 Fix Maximum length of Choices subfield (interim) is set to 40
- #1651 Fix Error when invalidating a sample with contained retests
- #1633 Fix report section displays date pickers in Chinese
Expand Down
67 changes: 49 additions & 18 deletions bika/lims/content/worksheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -868,22 +868,30 @@ def _apply_worksheet_template_routine_analyses(self, wst):

# Map existing sample uids with slots
samples_slots = dict(self.get_containers_slots())
new_sample_uids = []

# Keep track of the UIDs of pre-existing Samples
existing = samples_slots.keys()

new_analyses = []

for analysis in analyses:
analysis = api.get_object(analysis)

if analysis.getWorksheet():
# TODO duplicate record or bad value for review_state?
continue

if instrument and not analysis.isInstrumentAllowed(instrument):
# WST's Instrument does not supports this analysis
# Template's Instrument does not support this analysis
continue

if method and not analysis.isMethodAllowed(method):
# WST's method does not supports this analysis
# Template's method does not support this analysis
continue

# Get the slot where analyses from this sample are located
sample_uid = analysis.getRequestUID()
sample = analysis.getRequest()
sample_uid = api.get_uid(sample)
slot = samples_slots.get(sample_uid)
if not slot:
if len(available_slots) == 0:
Expand All @@ -893,23 +901,46 @@ def _apply_worksheet_template_routine_analyses(self, wst):
# Pop next available slot
slot = available_slots.pop()

# Feed the samples_slots
samples_slots[sample_uid] = slot
new_sample_uids.append(sample_uid)
# Keep track of the slot where analyses from this sample must live
samples_slots[sample_uid] = slot

# Keep track of the analyses to add
new_analyses.append((analysis, sample_uid))

# Re-sort slots for new samples to display them in natural order
new_slots = map(lambda s: samples_slots.get(s), new_sample_uids)
sorted_slots = zip(sorted(new_sample_uids), sorted(new_slots))
for sample_id, slot in sorted_slots:
samples_slots[sample_uid] = slot
analysis_info = {
"analysis": analysis,
"sample_uid": sample_uid,
"sample_id": api.get_id(sample),
"slot": slot,
}
new_analyses.append(analysis_info)

if not new_analyses:
# No analyses to add
return

# Add analyses to the worksheet
for analysis, sample_uid in new_analyses:
slot = samples_slots[sample_uid]
self.addAnalysis(analysis, slot)
# No need to sort slots for analyses with a pre-existing sample/slot
with_samp = filter(lambda a: a["sample_uid"] in existing, new_analyses)
analyses_slots = map(lambda s: (s["analysis"], s["slot"]), with_samp)

# Re-sort slots for analyses without a pre-existing sample/slot
# Analyses retrieved from database are sorted by priority, but we want
# them to be displayed in natural order in the worksheet
without_samp = filter(lambda a: a not in with_samp, new_analyses)
# Sort the items by sample id
without_samp.sort(key=lambda a: a["sample_id"])
# Extract the list of analyses (sorted by sample id)
without_samp_analyses = map(lambda a: a["analysis"], without_samp)
# Extract the list of assigned slots and sort them in natural order
without_samp_slots = sorted(map(lambda a: a["slot"], without_samp))
# Generate the tuple (analysis, slot)
without_samp_slots = zip(without_samp_analyses, without_samp_slots)
# Append to those non sorted because of pre-existing slots
analyses_slots.extend(without_samp_slots)

# Add the analyses to the worksheet
map(lambda a: self.addAnalysis(a[0], a[1]), analyses_slots)

# Reindex the worksheet to update the WorksheetTemplate meta column
self.reindexObject()

def _apply_worksheet_template_duplicate_analyses(self, wst):
"""Add duplicate analyses to worksheet according to the worksheet template
Expand Down
8 changes: 8 additions & 0 deletions bika/lims/tests/doctests/WorksheetApplyTemplate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,14 @@ Create and receive 3 samples:
>>> samples = map(lambda i: create_analysisrequest(client, request, values, service_uids), range(3))
>>> success = map(lambda s: doActionFor(s, "receive"), samples)

Change the priority of Samples, so PrioritySortKey sorts their analyses in
reversed order:

>>> for priority, sample in enumerate(reversed(samples)):
... sample.setPriority(priority)
... sample.reindexObject()
... ans = map(lambda a: a.reindexObject(), sample.getAnalyses(full_objects=True))

Create a worksheet and apply the template:

>>> worksheet = api.create(portal.worksheets, "Worksheet")
Expand Down