Skip to content

Commit

Permalink
Validate father in same case as child (#3492)
Browse files Browse the repository at this point in the history
  • Loading branch information
seallard authored Jul 30, 2024
1 parent 75844c4 commit e72c8c3
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 1 deletion.
5 changes: 5 additions & 0 deletions cg/services/order_validation_service/models/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ class InvalidFatherSexError(CaseSampleError):
message: str = "Father must be male"


class FatherNotInCaseError(CaseSampleError):
field: str = "father"
message: str = "Father must be in the same case"


class InvalidMotherSexError(CaseSampleError):
field: str = "mother"
message: str = "Mother must be female"
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from cg.constants.subject import Sex
from cg.services.order_validation_service.models.errors import (
FatherNotInCaseError,
InvalidFatherSexError,
InvalidMotherSexError,
OccupiedWellError,
Expand All @@ -12,7 +13,9 @@
_get_errors,
_get_excess_samples,
_get_plate_samples,
get_father_case_errors,
get_father_sex_errors,
get_mother_sex_errors,
get_repeated_case_name_errors,
get_repeated_sample_name_errors,
)
Expand Down Expand Up @@ -44,6 +47,14 @@ def validate_fathers_are_male(order: TomteOrder) -> list[InvalidFatherSexError]:
return errors


def validate_fathers_in_same_case_as_children(order: TomteOrder) -> list[FatherNotInCaseError]:
errors = []
for case in order.cases:
case_errors = get_father_case_errors(case)
errors.extend(case_errors)
return errors


def validate_mothers_are_female(order: TomteOrder) -> list[InvalidMotherSexError]:
errors: list[InvalidMotherSexError] = []
for case in order.cases:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from cg.constants.subject import Sex
from cg.models.orders.sample_base import ContainerEnum
from cg.services.order_validation_service.models.errors import (
FatherNotInCaseError,
InvalidFatherSexError,
InvalidMotherSexError,
OccupiedWellError,
Expand Down Expand Up @@ -98,6 +99,17 @@ def create_father_sex_error(case: TomteCase, sample: TomteSample) -> InvalidFath
return InvalidFatherSexError(sample_name=sample.name, case_name=case.name)


def get_father_case_errors(case: TomteCase) -> list[FatherNotInCaseError]:
errors = []
children: list[TomteSample] = case.get_samples_with_father()
for child in children:
father: TomteSample | None = case.get_sample(child.father)
if not father:
error = create_father_case_error(case=case, sample=child)
errors.append(error)
return errors


def get_mother_sex_errors(case: TomteCase) -> list[InvalidMotherSexError]:
errors = []
children: list[TomteSample] = case.get_samples_with_mother()
Expand All @@ -108,6 +120,10 @@ def get_mother_sex_errors(case: TomteCase) -> list[InvalidMotherSexError]:
return errors


def create_father_case_error(case: TomteCase, sample: TomteSample) -> FatherNotInCaseError:
return FatherNotInCaseError(case_name=case.name, sample_name=sample.name)


def is_mother_sex_invalid(child: TomteSample, case: TomteCase) -> bool:
mother: TomteSample | None = case.get_sample(child.mother)
return mother and mother.sex != Sex.FEMALE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
)
from cg.services.order_validation_service.workflows.tomte.validation.inter_field.rules import (
validate_fathers_are_male,
validate_fathers_in_same_case_as_children,
validate_mothers_are_female,
validate_no_repeated_case_names,
validate_no_repeated_sample_names,
Expand All @@ -27,6 +28,7 @@
validate_no_repeated_case_names,
validate_no_repeated_sample_names,
validate_fathers_are_male,
validate_fathers_in_same_case_as_children,
validate_mothers_are_female,
validate_application_exists,
validate_application_compatibility,
Expand Down
11 changes: 10 additions & 1 deletion tests/services/order_validation_service/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def order_with_repeated_sample_names(
@pytest.fixture
def case() -> TomteCase:
sample_1: TomteSample = create_sample(1)
sample_2: TomteSample = create_sample(1)
sample_2: TomteSample = create_sample(2)
return create_case([sample_1, sample_2])


Expand All @@ -114,3 +114,12 @@ def order_with_invalid_father_sex(case: TomteCase):
child.father = father.name
father.sex = SexEnum.female
return create_order([case])


@pytest.fixture
def order_with_father_in_wrong_case(case: TomteCase):
child = case.samples[0]
father = case.samples[1]
child.father = father.name
case.samples = [child]
return create_order([case])
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from cg.services.order_validation_service.models.errors import (
FatherNotInCaseError,
InvalidFatherSexError,
OccupiedWellError,
RepeatedCaseNameError,
Expand All @@ -7,6 +8,7 @@
from cg.services.order_validation_service.workflows.tomte.models.order import TomteOrder
from cg.services.order_validation_service.workflows.tomte.validation.inter_field.rules import (
validate_fathers_are_male,
validate_fathers_in_same_case_as_children,
validate_no_repeated_case_names,
validate_no_repeated_sample_names,
validate_wells_contain_at_most_one_sample,
Expand Down Expand Up @@ -85,3 +87,17 @@ def test_no_father_sex_error_when_no_father_present(valid_order: TomteOrder):

# THEN no errors are returned
assert not errors


def test_father_in_wrong_case(order_with_father_in_wrong_case: TomteOrder):

# GIVEN an order with the father sample in the wrong case

# WHEN validating the order
errors = validate_fathers_in_same_case_as_children(order_with_father_in_wrong_case)

# THEN an error is returned
assert errors

# THEN the error is about the father being in the wrong case
assert isinstance(errors[0], FatherNotInCaseError)

0 comments on commit e72c8c3

Please sign in to comment.