From a9076b1d0e7c3868397e89dd12d3f7f16e92b4a1 Mon Sep 17 00:00:00 2001 From: Dominik Date: Thu, 20 Aug 2026 20:58:43 +0200 Subject: [PATCH] Fix TypeError when reading the minimal SEPA direct debit lead time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MinimaleVorlaufzeitSEPALastschrift::create() accepts the two coded fields as ?int, but the properties they are assigned to are typed non-nullable int. Every caller that omits them therefore raises TypeError: Cannot assign null to property MinimaleVorlaufzeitSEPALastschrift::$unterstuetzteSEPALastschriftartenCodiert of type int Three call sites inside the library do exactly that: - ParameterTerminierteSEPAEinzellastschriftEinreichenV1::getMinimalLeadTime() - ParameterTerminierteSEPAFirmenEinzellastschriftEinreichenV1::getMinimalLeadTime() - MinimaleVorlaufzeitSEPALastschrift::parseCodedB2B() So the lead time cannot be read for HIDSES/HIDMES/HIBSES/HIBMES in version 1 at all, nor for B2B in version 2. Postbank offers all four of those segments only in version 1 — its own response in the Postbank integration test fixtures reproduces the error. Version 1 does not transmit the two codes (it states the lead time per sequence type instead), and the B2B coded format has no field for the direct debit type, so null is the accurate value in both cases. Both properties are made nullable, matching the signature of create(). Neither is read anywhere in the library or its samples, so nothing downstream changes. --- ...MinimaleVorlaufzeitSEPALastschriftTest.php | 65 +++++++++++++++++++ .../MinimaleVorlaufzeitSEPALastschrift.php | 8 +-- 2 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 Tests/Unit/Segment/MinimaleVorlaufzeitSEPALastschriftTest.php diff --git a/Tests/Unit/Segment/MinimaleVorlaufzeitSEPALastschriftTest.php b/Tests/Unit/Segment/MinimaleVorlaufzeitSEPALastschriftTest.php new file mode 100644 index 00000000..8e95e436 --- /dev/null +++ b/Tests/Unit/Segment/MinimaleVorlaufzeitSEPALastschriftTest.php @@ -0,0 +1,65 @@ +getParameter(); + + $recurring = $parameter->getMinimalLeadTime('RCUR'); + $this->assertInstanceOf(MinimaleVorlaufzeitSEPALastschrift::class, $recurring); + $this->assertEquals(1, $recurring->minimaleSEPAVorlaufzeit); + + // Version 1 states the lead time per sequence type and carries neither of the two codes + // that version 2 encodes, so they stay unset. + $this->assertNull($recurring->unterstuetzteSEPALastschriftartenCodiert); + $this->assertNull($recurring->sequenceTypeCodiert); + + $this->assertEquals(1, $parameter->getMinimalLeadTime('FRST')->minimaleSEPAVorlaufzeit); + } + + public function testGetMinimalLeadTimeFromVersion1B2B() + { + $parameter = HIBMESv1::parse(static::REAL_POSTBANK_HIBMES)->getParameter(); + + $this->assertEquals(1, $parameter->getMinimalLeadTime('RCUR')->minimaleSEPAVorlaufzeit); + $this->assertEquals(1, $parameter->getMinimalLeadTime('OOFF')->minimaleSEPAVorlaufzeit); + } + + /** + * The B2B variant of the coded format has no field for the direct debit type, so the parser + * passes none. + */ + public function testParseCodedB2B() + { + $parsed = MinimaleVorlaufzeitSEPALastschrift::parseCodedB2B('1;2;120000'); + + $this->assertEquals(2, $parsed['B2B']['RCUR']->minimaleSEPAVorlaufzeit); + $this->assertEquals('120000', $parsed['B2B']['FNAL']->cutOffZeit); + $this->assertNull($parsed['B2B']['RCUR']->unterstuetzteSEPALastschriftartenCodiert); + $this->assertEquals(1, $parsed['B2B']['RCUR']->sequenceTypeCodiert); + } + + public function testParseCoded() + { + $parsed = MinimaleVorlaufzeitSEPALastschrift::parseCoded('0;1;2;120000'); + + $this->assertEquals(2, $parsed['CORE']['RCUR']->minimaleSEPAVorlaufzeit); + $this->assertEquals(0, $parsed['CORE']['RCUR']->unterstuetzteSEPALastschriftartenCodiert); + $this->assertEquals(1, $parsed['CORE']['RCUR']->sequenceTypeCodiert); + } +} diff --git a/src/Segment/DSE/MinimaleVorlaufzeitSEPALastschrift.php b/src/Segment/DSE/MinimaleVorlaufzeitSEPALastschrift.php index f50330eb..25c2cca9 100644 --- a/src/Segment/DSE/MinimaleVorlaufzeitSEPALastschrift.php +++ b/src/Segment/DSE/MinimaleVorlaufzeitSEPALastschrift.php @@ -24,11 +24,11 @@ class MinimaleVorlaufzeitSEPALastschrift ['FRST', 'OOFF'], ]; - /** Must be 0,1,2 */ - public int $unterstuetzteSEPALastschriftartenCodiert; + /** Must be 0,1,2, or null when the segment does not state it (version 1, and B2B in general) */ + public ?int $unterstuetzteSEPALastschriftartenCodiert = null; - /** Must be 0,1,2 */ - public int $sequenceTypeCodiert; + /** Must be 0,1,2, or null when the segment does not state it (version 1) */ + public ?int $sequenceTypeCodiert = null; /** In Days */ public int $minimaleSEPAVorlaufzeit;