diff --git a/alembic/versions/2.1.0_extend_qc_state_dict.py b/alembic/versions/2.1.0_extend_qc_state_dict.py new file mode 100644 index 0000000..8844d8d --- /dev/null +++ b/alembic/versions/2.1.0_extend_qc_state_dict.py @@ -0,0 +1,22 @@ +"""extend_qc_state_dict + +Revision ID: 2.1.0 +Revises: 2.0.0 +Create Date: 2024-03-19 12:31:26.359652 + +""" +from alembic import op + +# revision identifiers, used by Alembic. +revision = "2.1.0" +down_revision = "2.0.0" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.execute("INSERT INTO qc_state_dict VALUES ('On hold external', NULL)") + + +def downgrade() -> None: + op.execute("DELETE FROM qc_state_dict WHERE state='On hold external'") diff --git a/lang_qc/db/helper/wells.py b/lang_qc/db/helper/wells.py index 8e56a0a..976dd63 100644 --- a/lang_qc/db/helper/wells.py +++ b/lang_qc/db/helper/wells.py @@ -169,10 +169,10 @@ class PacBioPagedWellsFactory(WellWh, PagedResponse): # For MySQL it's OK to use case-sensitive comparison operators since # its string comparisons for the collation we use are case-insensitive. FILTERS: ClassVar = { - QcFlowStatusEnum.ON_HOLD.name: (QcStateDict.state == "On hold"), + QcFlowStatusEnum.ON_HOLD.name: (QcStateDict.state.ilike("On hold%")), QcFlowStatusEnum.QC_COMPLETE.name: (QcState.is_preliminary == 0), QcFlowStatusEnum.IN_PROGRESS.name: and_( - QcState.is_preliminary == 1, QcStateDict.state != "On hold" + QcState.is_preliminary == 1, QcStateDict.state.notilike("On hold%") ), QcFlowStatusEnum.ABORTED.name: or_( PacBioRunWellMetrics.well_status.like("Abort%"), diff --git a/lang_qc/endpoints/config.py b/lang_qc/endpoints/config.py index 2436ab1..0f8dbb1 100644 --- a/lang_qc/endpoints/config.py +++ b/lang_qc/endpoints/config.py @@ -65,6 +65,8 @@ def _states_for_update(session) -> List: states = [] for (name, row) in qc_state_dict(session).items(): if name not in ["Aborted", "Claimed"]: - states.append({"description": name, "only_prelim": row.state == "On hold"}) + states.append( + {"description": name, "only_prelim": "on hold" in row.state.lower()} + ) return states diff --git a/tests/endpoints/test_config.py b/tests/endpoints/test_config.py index 85f6355..97ab9e7 100644 --- a/tests/endpoints/test_config.py +++ b/tests/endpoints/test_config.py @@ -23,6 +23,7 @@ def test_get_config(test_client: TestClient, load_dicts_and_users): {"description": "Failed, Instrument", "only_prelim": False}, {"description": "Failed, SMRT cell", "only_prelim": False}, {"description": "On hold", "only_prelim": True}, + {"description": "On hold external", "only_prelim": True}, {"description": "Undecided", "only_prelim": False}, ], } diff --git a/tests/endpoints/test_dump_qc_states.py b/tests/endpoints/test_dump_qc_states.py index 057fe3d..49247ee 100644 --- a/tests/endpoints/test_dump_qc_states.py +++ b/tests/endpoints/test_dump_qc_states.py @@ -41,7 +41,7 @@ def test_get_qc_by_product_id(test_client: TestClient, load_data4well_retrieval) assert SECOND_GOOD_CHECKSUM in response_data list_1 = response_data[FIRST_GOOD_CHECKSUM] list_2 = response_data[SECOND_GOOD_CHECKSUM] - qc_states = ["On hold", "Failed, Instrument"] + qc_states = ["On hold external", "Failed, Instrument"] for index, l in enumerate([list_1, list_2]): assert len(l) == 2 # The list of QC state objects contains QC states diff --git a/tests/endpoints/test_filtered_wells.py b/tests/endpoints/test_filtered_wells.py index c65bd71..4ea86ed 100644 --- a/tests/endpoints/test_filtered_wells.py +++ b/tests/endpoints/test_filtered_wells.py @@ -81,7 +81,10 @@ def test_on_hold_filter(test_client: TestClient, load_data4well_retrieval): """Test passing `on_hold` filter.""" status = "on_hold" - expected_data = [{"TRACTION_RUN_1:D1": "On hold"}, {"TRACTION_RUN_1:B1": "On hold"}] + expected_data = [ + {"TRACTION_RUN_1:D1": "On hold external"}, + {"TRACTION_RUN_1:B1": "On hold"}, + ] num_total = len(expected_data) response = test_client.get( diff --git a/tests/endpoints/test_wells4run.py b/tests/endpoints/test_wells4run.py index 518e1c2..1347fce 100644 --- a/tests/endpoints/test_wells4run.py +++ b/tests/endpoints/test_wells4run.py @@ -26,7 +26,7 @@ def test_existing_run(test_client: TestClient, load_data4well_retrieval): label_list = [well["label"] for well in resp["wells"]] assert label_list == ["A1", "B1", "C1", "D1"] qc_states = [well["qc_state"]["qc_state"] for well in resp["wells"]] - assert qc_states == ["Claimed", "On hold", "Claimed", "On hold"] + assert qc_states == ["Claimed", "On hold", "Claimed", "On hold external"] assert ( resp["wells"][0]["instrument_name"] == "64016" diff --git a/tests/fixtures/well_data.py b/tests/fixtures/well_data.py index abb99a3..3754c92 100644 --- a/tests/fixtures/well_data.py +++ b/tests/fixtures/well_data.py @@ -30,6 +30,7 @@ {"state": "Passed", "outcome": 1}, {"state": "Claimed", "outcome": None}, {"state": "On hold", "outcome": None}, + {"state": "On hold external", "outcome": None}, ] PLATFORMS = [ @@ -66,7 +67,7 @@ ["TRACTION_RUN_1", "A1", "Claimed", True, "2022-12-07 07:15:19", None], ["TRACTION_RUN_1", "B1", "On hold", True, "2022-12-08 07:15:19", None], ["TRACTION_RUN_1", "C1", "Claimed", True, "2022-12-08 08:15:19", None], - ["TRACTION_RUN_1", "D1", "On hold", True, "2022-12-08 09:15:19", None], + ["TRACTION_RUN_1", "D1", "On hold external", True, "2022-12-08 09:15:19", None], ["TRACTION_RUN_1", "E1", "Claimed", True, "2022-12-07 09:15:19", None], ["TRACTION_RUN_2", "A1", "Failed, Instrument", True, "2022-12-07 15:13:56", 1], ["TRACTION_RUN_2", "B1", "Failed, Instrument", False, "2022-12-08 15:18:56", 1], diff --git a/tests/test_pb_wells_factory.py b/tests/test_pb_wells_factory.py index c9bbc92..dc02f61 100644 --- a/tests/test_pb_wells_factory.py +++ b/tests/test_pb_wells_factory.py @@ -31,7 +31,7 @@ def test_query_for_status( assert isinstance(state, QcState) assert state.is_preliminary == 1 assert state.qc_type.qc_type == "sequencing" - assert state.qc_state_dict.state == "On hold" + assert state.qc_state_dict.state in ("On hold", "On hold external") compare_dates(state.date_updated, update_dates[index]) factory = PacBioPagedWellsFactory( @@ -400,8 +400,13 @@ def test_known_run_names_input( label_list = [well.label for well in wells] assert label_list == ["A1", "B1", "C1", "D1"] - qc_states = [well.qc_state.qc_state for well in wells] - expected_qc_states = ["Claimed", "On hold", "Claimed", "On hold"] + qc_states = sorted([well.qc_state.qc_state for well in wells]) + expected_qc_states = [ + "Claimed", + "Claimed", + "On hold", + "On hold external", + ] assert qc_states == expected_qc_states factory = PacBioPagedWellsFactory( diff --git a/tests/test_qc_state_retrieval.py b/tests/test_qc_state_retrieval.py index 7babe28..6d5813e 100644 --- a/tests/test_qc_state_retrieval.py +++ b/tests/test_qc_state_retrieval.py @@ -30,7 +30,7 @@ def test_bulk_retrieval(qcdb_test_session, load_data4well_retrieval): # product IDs is performed. assert get_qc_states_by_id_product_list(qcdb_test_session, ["dodo"]) == {} - qc_state_descriptions = ["On hold", "Failed, Instrument"] + qc_state_descriptions = ["On hold external", "Failed, Instrument"] qc_states = get_qc_states_by_id_product_list(qcdb_test_session, two_good_ids_list) assert len(qc_states) == 2 @@ -140,7 +140,7 @@ def test_product_qc_state_retrieval(qcdb_test_session, load_data4well_retrieval) assert qc_state is not None assert qc_state.seq_product.id_product == FIRST_GOOD_CHECKSUM assert qc_state.qc_type.qc_type == "sequencing" - assert qc_state.qc_state_dict.state == "On hold" + assert qc_state.qc_state_dict.state == "On hold external" qc_state = get_qc_state_for_product( session=qcdb_test_session, id_product=FIRST_GOOD_CHECKSUM, qc_type="sequencing" @@ -148,7 +148,7 @@ def test_product_qc_state_retrieval(qcdb_test_session, load_data4well_retrieval) assert qc_state is not None assert qc_state.seq_product.id_product == FIRST_GOOD_CHECKSUM assert qc_state.qc_type.qc_type == "sequencing" - assert qc_state.qc_state_dict.state == "On hold" + assert qc_state.qc_state_dict.state == "On hold external" qc_state = get_qc_state_for_product( session=qcdb_test_session, id_product=FIRST_GOOD_CHECKSUM, qc_type="library" @@ -156,7 +156,7 @@ def test_product_qc_state_retrieval(qcdb_test_session, load_data4well_retrieval) assert qc_state is not None assert qc_state.seq_product.id_product == FIRST_GOOD_CHECKSUM assert qc_state.qc_type.qc_type == "library" - assert qc_state.qc_state_dict.state == "On hold" + assert qc_state.qc_state_dict.state == "On hold external" qc_state = get_qc_state_for_product(qcdb_test_session, SECOND_GOOD_CHECKSUM) assert qc_state is not None @@ -183,6 +183,7 @@ def test_dict_helper(qcdb_test_session, load_dicts_and_users): "Failed, SMRT cell", "Claimed", "On hold", + "On hold external", "Undecided", ] assert list(qc_state_dict(qcdb_test_session).keys()) == expected_sorted_states