diff --git a/src/bo4e/bo/buendelvertrag.py b/src/bo4e/bo/buendelvertrag.py new file mode 100644 index 000000000..33912c773 --- /dev/null +++ b/src/bo4e/bo/buendelvertrag.py @@ -0,0 +1,41 @@ +""" +Contains Buendelvertrag class and corresponding marshmallow schema for de-/serialization +""" +from typing import List + +import attr +from marshmallow import fields + +from bo4e.bo.geschaeftsobjekt import Geschaeftsobjekt, GeschaeftsobjektSchema +from bo4e.bo.vertrag import Vertrag, VertragSchema +from bo4e.enum.botyp import BoTyp +from bo4e.validators import check_list_length_at_least_one + + +# pylint: disable=too-few-public-methods +@attr.s(auto_attribs=True, kw_only=True) +class Buendelvertrag(Geschaeftsobjekt): + """ + Abbildung eines Bündelvertrags. + Es handelt sich hierbei um eine Liste von Einzelverträgen, die in einem Vertragsobjekt gebündelt sind. + """ + + # required attributes + bo_typ: BoTyp = attr.ib(default=BoTyp.BUENDELVERTRAG) + #: Die Liste mit den Einzelverträgen zu den Abnahmestellen + einzelvertraege: List[Vertrag] = attr.ib( + validator=attr.validators.deep_iterable( + member_validator=attr.validators.instance_of(Vertrag), iterable_validator=check_list_length_at_least_one + ) + ) + + +class BuendelvertragSchema(GeschaeftsobjektSchema): + """ + Schema for de-/serialization of Buendelvertrag + """ + + class_name = Buendelvertrag + + # required attributes + einzelvertraege = fields.List(fields.Nested(VertragSchema)) diff --git a/src/bo4e/enum/botyp.py b/src/bo4e/enum/botyp.py index 26a7e0b4c..fd57e50b5 100644 --- a/src/bo4e/enum/botyp.py +++ b/src/bo4e/enum/botyp.py @@ -10,6 +10,7 @@ class BoTyp(StrEnum): ANGEBOT = "ANGEBOT" ANSPRECHPARTNER = "ANSPRECHPARTNER" AUSSCHREIBUNG = "AUSSCHREIUNG" + BUENDELVERTRAG = "BUENDELVERTRAG" ENERGIEMENGE = "ENERGIEMENGE" # It is practical to use the BoTyp Enum as discriminator in the database. # Therefore, we added one additional entry for GESCHAEFTSOBJEKT diff --git a/tests/test_buendelvertrag.py b/tests/test_buendelvertrag.py new file mode 100644 index 000000000..d651de92c --- /dev/null +++ b/tests/test_buendelvertrag.py @@ -0,0 +1,22 @@ +import pytest # type:ignore[import] + +from bo4e.bo.buendelvertrag import Buendelvertrag, BuendelvertragSchema +from tests.serialization_helper import assert_serialization_roundtrip # type:ignore[import] +from tests.test_vertrag import TestVertrag # type:ignore[import] + + +class TestBuendelvertrag: + @pytest.mark.parametrize( + "buendelvertrag", + [ + pytest.param(Buendelvertrag(einzelvertraege=[TestVertrag().get_example_vertrag()])), + ], + ) + def test_serialization_roundtrip(self, buendelvertrag: Buendelvertrag): + assert_serialization_roundtrip(buendelvertrag, BuendelvertragSchema()) + + def test_missing_required_attribute(self): + with pytest.raises(TypeError) as excinfo: + _ = Buendelvertrag() + + assert "missing 1 required" in str(excinfo.value) diff --git a/tests/test_vertrag.py b/tests/test_vertrag.py index 106f57f4e..a84e434c7 100644 --- a/tests/test_vertrag.py +++ b/tests/test_vertrag.py @@ -62,11 +62,8 @@ class TestVertrag: ) ] - def test_serialisation_only_required_attributes(self): - """ - Test de-/serialisation of Vertrag with minimal attributes. - """ - vertrag = Vertrag( + def get_example_vertrag(self) -> Vertrag: + return Vertrag( vertragsnummer=self._vertragsnummer, vertragsart=self._vertragsart, vertragsstatus=self._vertragsstatus, @@ -78,6 +75,12 @@ def test_serialisation_only_required_attributes(self): vertragsteile=self._vertragsteile, ) + def test_serialisation_only_required_attributes(self): + """ + Test de-/serialisation of Vertrag with minimal attributes. + """ + vertrag = self.get_example_vertrag() + schema = VertragSchema() json_string = schema.dumps(vertrag, ensure_ascii=False)