diff --git a/src/ebdtable2graph/graph_conversion.py b/src/ebdtable2graph/graph_conversion.py index b40b457..e88f01c 100644 --- a/src/ebdtable2graph/graph_conversion.py +++ b/src/ebdtable2graph/graph_conversion.py @@ -20,7 +20,11 @@ ToNoEdge, ToYesEdge, ) -from ebdtable2graph.models.errors import EbdCrossReferenceNotSupportedError, OutcomeNodeCreationError +from ebdtable2graph.models.errors import ( + EbdCrossReferenceNotSupportedError, + EndeInWrongColumnError, + OutcomeNodeCreationError, +) def _convert_sub_row_to_outcome_node(sub_row: EbdTableSubRow) -> Optional[OutcomeNode]: @@ -92,8 +96,14 @@ def get_all_edges(table: EbdTable) -> List[EbdGraphEdge]: else: outcome_node: Optional[OutcomeNode] = _convert_sub_row_to_outcome_node(sub_row) if outcome_node is None: - if all(sr.result_code is None for sr in row.sub_rows): + if all(sr.result_code is None for sr in row.sub_rows) and any( + sr.note is not None and sr.note.startswith("EBD ") for sr in row.sub_rows + ): raise EbdCrossReferenceNotSupportedError(row=row, decision_node=decision_node) + if all(sr.result_code is None for sr in row.sub_rows) and any( + sr.note is not None and sr.note.lower().startswith("ende") for sr in row.sub_rows + ): + raise EndeInWrongColumnError(row=row) raise OutcomeNodeCreationError(decision_node=decision_node, sub_row=sub_row) edge = _yes_no_edge( sub_row.check_result.result, diff --git a/src/ebdtable2graph/models/errors/__init__.py b/src/ebdtable2graph/models/errors/__init__.py index 5fa3c9c..ce4de07 100644 --- a/src/ebdtable2graph/models/errors/__init__.py +++ b/src/ebdtable2graph/models/errors/__init__.py @@ -88,6 +88,18 @@ def __init__(self, decision_node: DecisionNode, row: EbdTableRow): self.decision_node = decision_node +class EndeInWrongColumnError(ValueError): + """ + Raised when the subsequent step should be "Ende" but is not referenced in the respective column but as a note. + This could be easily fixed but still, it needs to be done. + I think this is more of a value error (because the raw source data are a mess) than a NotImplementedError. + """ + + def __init__(self, row: EbdTableRow): + super().__init__(f"'Ende' in wrong column for row {row}") + self.row = row + + class OutcomeNodeCreationError(ValueError): """ raised when the outcome node cannot be created from a sub row diff --git a/unittests/e0404.py b/unittests/e0404.py new file mode 100644 index 0000000..ae55d73 --- /dev/null +++ b/unittests/e0404.py @@ -0,0 +1,97 @@ +""" +Contains the raw data for E_0404 in the form of an EbdTable. +""" +from ebdtable2graph.models import EbdCheckResult, EbdTable, EbdTableMetaData, EbdTableRow, EbdTableSubRow + +e_0404 = EbdTable( + metadata=EbdTableMetaData(ebd_code="E_0404", chapter="GPKE", sub_chapter="6.4.4: AD: Lieferbeginn", role="NB"), + rows=[ + EbdTableRow( + step_number="1", + description="Wurde eine Abmeldeanfrage gestellt?", + sub_rows=[ + EbdTableSubRow( + check_result=EbdCheckResult(result=False, subsequent_step_number="6"), result_code=None, note=None + ), + EbdTableSubRow( + check_result=EbdCheckResult(result=True, subsequent_step_number="2"), result_code=None, note=None + ), + ], + use_cases=None, + ), + EbdTableRow( + step_number="2", + description="Hat der LFA fristgerecht geantwortet?", + sub_rows=[ + EbdTableSubRow( + check_result=EbdCheckResult(result=True, subsequent_step_number="3"), result_code=None, note=None + ), + EbdTableSubRow( + check_result=EbdCheckResult(result=False, subsequent_step_number="6"), result_code=None, note=None + ), + ], + use_cases=None, + ), + EbdTableRow( + step_number="3", + description="Hat der LFA der Abmeldeanfrage widersprochen?", + sub_rows=[ + EbdTableSubRow( + check_result=EbdCheckResult(result=True, subsequent_step_number="4"), result_code=None, note=None + ), + EbdTableSubRow( + check_result=EbdCheckResult(result=False, subsequent_step_number="6"), result_code=None, note=None + ), + ], + use_cases=None, + ), + EbdTableRow( + step_number="4", + description="Wurde in der Beantwortung der Abmeldeanfrage der Code A30 „Ablehnung: Die Belieferung wurde zu dem angefragten Termin aus der Abmeldeanfrage bereits beendet und eine Abmeldung von dem LFA bereits versendet, die durch den NB bereits bestätigt wurde.“ verwendet?", + sub_rows=[ + EbdTableSubRow( + check_result=EbdCheckResult(result=False, subsequent_step_number=None), + result_code="A50", + note="Cluster: Ablehnung\nDer LFA hat der Abmeldeanfrage widersprochen.", + ), + EbdTableSubRow( + check_result=EbdCheckResult(result=True, subsequent_step_number="5"), result_code=None, note=None + ), + ], + use_cases=None, + ), + EbdTableRow( + step_number="5", + description="Wurde die NN-Anmeldung des LFN bereits durch den NB beantwortet?", + sub_rows=[ + EbdTableSubRow( + check_result=EbdCheckResult(result=True, subsequent_step_number=None), + result_code=None, + note="Ende\nHinweis: Der vom LFN gestartete Lieferbeginn-prozess (Anmeldung), der beim NB zur Versen-dung der Abmeldeanfrage an den LFA führte, wurde bereits durch einen vom LFA gestarteten Lieferendeprozess, der vor dem Eingang der Antwort der Abmeldeanfrage abgeschlossen wurde, beendet. Das führte dazu, dass der NB die Anmeldung des LFN vor dem Eingang der Antwort der Abmeldeanfrage bestätigt hatte. Somit ist an den LFN keine weitere Antwort auf seine Anmeldung mehr zu senden.", + ), + EbdTableSubRow( + check_result=EbdCheckResult(result=False, subsequent_step_number="6"), result_code=None, note=None + ), + ], + use_cases=None, + ), + EbdTableRow( + step_number="6", + description="Liegt die notwendige Zuordnungsermächtigung (Bilanzkreis/Bilanzierungsverfahren) vor?", + sub_rows=[ + EbdTableSubRow( + check_result=EbdCheckResult(result=False, subsequent_step_number=None), + result_code="A52", + note="Cluster: Ablehnung\nZuordnungsermächtigung fehlt.", + ), + EbdTableSubRow( + check_result=EbdCheckResult(result=True, subsequent_step_number=None), + result_code="A51", + note="Cluster: Zustimmung\nBestätigung der Anmeldung", + ), + ], + use_cases=None, + ), + ], + multi_step_instructions=None, +) diff --git a/unittests/test_errors.py b/unittests/test_errors.py index d9a2a9b..3f30d2f 100644 --- a/unittests/test_errors.py +++ b/unittests/test_errors.py @@ -4,6 +4,7 @@ from ebdtable2graph.models import EbdTable from ebdtable2graph.models.errors import ( EbdCrossReferenceNotSupportedError, + EndeInWrongColumnError, GraphTooComplexForPlantumlError, NotExactlyTwoOutgoingEdgesError, PathsNotGreaterThanOneError, @@ -11,6 +12,7 @@ from .e0266 import table_e0266 from .e0401 import e_0401 +from .e0404 import e_0404 from .e0454 import table_e0454 from .e0459 import table_e0459 from .e0462 import table_e0462 @@ -43,6 +45,11 @@ def test_too_complex_for_plantuml(self, table: EbdTable): def test_key_error_because_first_node_has_key_other_than_1(self, table: EbdTable): _ = convert_table_to_graph(table) # must _not_ raise a key error anymore + @pytest.mark.parametrize("table", [pytest.param(e_0404)]) + def test_ende_in_wrong_column_error(self, table: EbdTable): + with pytest.raises(EndeInWrongColumnError): + _ = convert_table_to_graph(table) + @pytest.mark.parametrize("table", [pytest.param(table_e0462)]) def test_cross_reference_not_supported_error(self, table: EbdTable): with pytest.raises(EbdCrossReferenceNotSupportedError) as exc_info: