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

Add Barcodes to Existing Kits #590

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
719a8f2
init create barcodes for existing kits
ayobi Mar 8, 2024
5846301
indent issues
ayobi Mar 8, 2024
16f2721
added validate admin access
ayobi Mar 18, 2024
846f978
update insert barcode test
ayobi Mar 18, 2024
f9db8b4
test
ayobi Mar 18, 2024
5d458d1
added user barcode field for create kits
ayobi Mar 25, 2024
ba0e51e
remove admin validate for generate barcodes
ayobi Mar 26, 2024
c8fef4b
added admin validate
ayobi Mar 26, 2024
3207886
lint
ayobi Mar 26, 2024
4fdc890
remove admin validate
ayobi Mar 26, 2024
1ceb9b9
add admin val again
ayobi Mar 26, 2024
43dc44f
test admin validate
ayobi Mar 26, 2024
87b1188
Merge branch 'biocore:master' into creates_barcodes_for_existing_kits
ayobi May 2, 2024
261d466
added admin validate
ayobi May 2, 2024
b8466d3
improvements per suggestions
ayobi Jun 21, 2024
190b99f
update tests
ayobi Jun 21, 2024
461b98d
test
ayobi Jun 22, 2024
0cef118
testv2
ayobi Jun 22, 2024
1f9ac09
testv3
ayobi Jun 22, 2024
686b335
testv4
ayobi Jun 22, 2024
d1f52a5
fixed test, flake
ayobi Jun 22, 2024
82493c3
Merge branch 'master' of https://github.com/biocore/microsetta-privat…
ayobi Jul 30, 2024
f5cfdd2
changes per suggestions
ayobi Aug 6, 2024
783abec
lint
ayobi Aug 6, 2024
224e5fe
removed debug statements
ayobi Aug 6, 2024
eacb78c
remove generate_barcodes
ayobi Aug 8, 2024
8dcf268
fixes and improvements
ayobi Aug 15, 2024
4c256bf
fixes
ayobi Aug 20, 2024
7dbe160
fix create kits for sample slots
ayobi Aug 23, 2024
373a24e
remove arg for create_kits
ayobi Aug 23, 2024
07fb798
changes based on latest feedback
ayobi Aug 30, 2024
0d3764a
missed 2 comments
ayobi Aug 30, 2024
47986b3
Merge branch 'biocore:master' into creates_barcodes_for_existing_kits
ayobi Oct 2, 2024
4a52bdc
Merge pull request #586 from ayobi/creates_barcodes_for_existing_kits
cassidysymons Oct 15, 2024
46346b3
Add barcodes to kits
cassidysymons Dec 16, 2024
34523d1
Merge branch 'master' into csymons_add_barcodes
cassidysymons Dec 16, 2024
c30b63f
Lint
cassidysymons Dec 16, 2024
4331479
Adjustments based on feedback
cassidysymons Jan 3, 2025
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
99 changes: 96 additions & 3 deletions microsetta_private_api/admin/admin_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def search_kit_id(token_info, kit_id):
admin_repo = AdminRepo(t)
diag = admin_repo.retrieve_diagnostics_by_kit_id(kit_id)
if diag is None:
return jsonify(code=404, message="Kit ID not found"), 404
return jsonify(code=404, message=f'Kit ID {kit_id} not found'), 404
return jsonify(diag), 200


Expand Down Expand Up @@ -267,13 +267,52 @@ def create_kits(body, token_info):
number_of_samples = body['number_of_samples']
kit_prefix = body.get('kit_id_prefix', None)
project_ids = body['project_ids']
# NB: The barcodes variable is a list of lists, structured with the notion
# of representing barcodes' constituent lists each representing one sample
# slot in the set of kits being created.
# len(barcodes) == number_of_samples && len(barcodes[x]) == number_of_kits
# This allows the creation of a set of kits with a mixture of
# system-generated and admin-provided barcodes.
barcodes = body['barcodes']

with Transaction() as t:
admin_repo = AdminRepo(t)

# Lock the barcode table for the duration of checking the existience
# of barcodes, then (hopefully) creating/inserting new ones
t.lock_table("barcodes.barcode")

# First, do some basic sanitation
errors = []
for barcode_list in barcodes:
Copy link
Member

Choose a reason for hiding this comment

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

What's the expected len of barcodes, is it == len(number_of_kits)? That's what I would expect, where the interpretation would be "use these samples for kit 0, use these samples for kit 1, etc", but it looks like the elements of barcodes are == len(number_of_kits)? Or should that be len(number_of_samples)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The length of barcodes is number of samples, and the length of each element of barcodes is the number of kits.

I've added a comment to the code to clarify the intended structure.

x = 1
if len(barcode_list) != 0:
# If barcodes were provided for a given slot, ensure the
# quantity matches the number of kits
if len(barcode_list) != number_of_kits:
errors.append(
f'Incorrect number of barcodes given for Sample {x}'
)

# And verify that the barcodes don't already exist
for barcode in barcode_list:
diag = admin_repo.check_exists_barcode(barcode)
if diag is True:
errors.append(f'Barcode {barcode} already exists')
x += 1

if len(errors) > 0:
error_str = "; ".join(errors)
return jsonify(code=422, message=error_str), 422

try:
kits = admin_repo.create_kits(number_of_kits, number_of_samples,
kit_prefix, project_ids)
kits = admin_repo.create_kits(
number_of_kits,
number_of_samples,
kit_prefix,
barcodes,
project_ids
)
except KeyError:
return jsonify(code=422, message="Unable to create kits"), 422
else:
Expand All @@ -282,6 +321,60 @@ def create_kits(body, token_info):
return jsonify(kits), 201


def add_barcodes_to_kits(body, token_info):
validate_admin_access(token_info)

kit_ids = body['kit_ids']
barcodes = body['barcodes']
generate_barcodes = body['generate_barcodes']

errors = []

with Transaction() as t:
admin_repo = AdminRepo(t)

# Lock the barcode table for the duration of checking the existience
# of barcodes, then (hopefully) adding them to kits
t.lock_table("barcodes.barcode")

# First, make sure all of the Kit IDs are valid
for kit_id in kit_ids:
diag = admin_repo.check_exists_kit(kit_id)
if diag is False:
errors.append(f'Kit ID {kit_id} not found')

if generate_barcodes is False:
# Next, check that the Barcodes are unique if we're not generating
# novel ones
for barcode in barcodes:
diag = admin_repo.check_exists_barcode(barcode)
if diag is True:
errors.append(f'Barcode {barcode} already exists')

# And verify that the number of barcodes and kit IDs are equal
if len(barcodes) != len(kit_ids):
Copy link
Member

Choose a reason for hiding this comment

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

This test should be performed before the checks against the database under the fail fast principle

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Given that this is an admin-facing tool with infrequent usage, I've opted to return a comprehensive set of errors so they can all be remedied at once, rather than simply returning the first error the API encounters. As such, the sequence of checks isn't important.

errors.append("Unequal number of Kit IDs and Barcodes")
else:
if len(barcodes) > 0:
errors.append(
"Barcodes may not be both generated and provided"
)

cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
# We found one or more issues with the supplied Kit IDs or Barcodes.
# Return the error message to microsetta-admin.
if len(errors) > 0:
error_str = "; ".join(errors)
return jsonify(
code=422,
message=error_str
), 422

diag = admin_repo.add_barcodes_to_kits(kit_ids, barcodes)
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be in a try/except given that create_kits is above

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm not following why this would be in a try/except block. It's a completely separate function/API path from creating kits, and all of the reasonable checks have been performed by the time we attempt to add barcodes to kits.

t.commit()

return jsonify(diag), 201


def get_account_events(account_id, token_info):
validate_admin_access(token_info)

Expand Down
Loading
Loading