From c3b5a972a19a515324e37aa236ea546fd945182a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 14 Aug 2025 10:47:18 +1000 Subject: [PATCH] Align tests with new workflow --- .../Verifactu/Models/FacturaRectificativa.php | 128 -------- .../Standards/Verifactu/Models/Invoice.php | 128 +------- .../Verifactu/VerifactuFeatureTest.php | 1 - .../EInvoice/Verifactu/VerifactuModelTest.php | 308 ++---------------- 4 files changed, 27 insertions(+), 538 deletions(-) delete mode 100644 app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php diff --git a/app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php b/app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php deleted file mode 100644 index 36c1e8e6b0..0000000000 --- a/app/Services/EDocument/Standards/Verifactu/Models/FacturaRectificativa.php +++ /dev/null @@ -1,128 +0,0 @@ -tipoRectificativa = $tipoRectificativa; - $this->baseRectificada = $baseRectificada; - $this->cuotaRectificada = $cuotaRectificada; - $this->cuotaRecargoRectificado = $cuotaRecargoRectificado; - $this->facturasRectificadas = []; - } - - public function getTipoRectificativa(): string - { - return $this->tipoRectificativa; - } - - public function getBaseRectificada(): float - { - return $this->baseRectificada; - } - - public function getCuotaRectificada(): float - { - return $this->cuotaRectificada; - } - - public function getCuotaRecargoRectificado(): ?float - { - return $this->cuotaRecargoRectificado; - } - - public function addFacturaRectificada(string $nif, string $numSerie, string $fecha): void - { - $this->facturasRectificadas[] = [ - 'nif' => $nif, - 'numSerie' => $numSerie, - 'fecha' => $fecha - ]; - } - - public function getFacturasRectificadas(): array - { - return $this->facturasRectificadas; - } - - /** - * Set up a rectified invoice with the required information - * - * @param string $nif The NIF of the rectified invoice - * @param string $numSerie The series number of the rectified invoice - * @param string $fecha The date of the rectified invoice - * @return self - */ - public function setRectifiedInvoice(string $nif, string $numSerie, string $fecha): self - { - $this->facturasRectificadas = []; - $this->addFacturaRectificada($nif, $numSerie, $fecha); - return $this; - } - - /** - * Set up a rectified invoice with the required information using an IDFactura object - * - * @param IDFactura $idFactura The IDFactura object of the rectified invoice - * @return self - */ - public function setRectifiedInvoiceFromIDFactura(IDFactura $idFactura): self - { - $this->facturasRectificadas = []; - $this->addFacturaRectificada( - $idFactura->getIdEmisorFactura(), - $idFactura->getNumSerieFactura(), - $idFactura->getFechaExpedicionFactura() - ); - return $this; - } - - public function toXml(\DOMDocument $doc): \DOMElement - { - $idFacturaRectificada = $this->createElement($doc, 'IDFacturaRectificada'); - - // Add required elements in order with proper namespace - $idEmisorFactura = $this->createElement($doc, 'IDEmisorFactura', $this->facturasRectificadas[0]['nif']); - $idFacturaRectificada->appendChild($idEmisorFactura); - - $numSerieFactura = $this->createElement($doc, 'NumSerieFactura', $this->facturasRectificadas[0]['numSerie']); - $idFacturaRectificada->appendChild($numSerieFactura); - - $fechaExpedicionFactura = $this->createElement($doc, 'FechaExpedicionFactura', $this->facturasRectificadas[0]['fecha']); - $idFacturaRectificada->appendChild($fechaExpedicionFactura); - - // Add required fields for R1 invoices according to Verifactu standard - $baseRectificada = $this->createElement($doc, 'BaseRectificada', number_format($this->baseRectificada, 2, '.', '')); - $idFacturaRectificada->appendChild($baseRectificada); - - $cuotaRectificada = $this->createElement($doc, 'CuotaRectificada', number_format($this->cuotaRectificada, 2, '.', '')); - $idFacturaRectificada->appendChild($cuotaRectificada); - - // Add optional CuotaRecargoRectificado if set - if ($this->cuotaRecargoRectificado !== null) { - $cuotaRecargoRectificado = $this->createElement($doc, 'CuotaRecargoRectificado', number_format($this->cuotaRecargoRectificado, 2, '.', '')); - $idFacturaRectificada->appendChild($cuotaRecargoRectificado); - } - - return $idFacturaRectificada; - } - - public static function fromDOMElement(\DOMElement $element): self - { - // This method is required by BaseXmlModel but not used in this context - // Return a default instance - return new self('S', 0.0, 0.0); - } -} \ No newline at end of file diff --git a/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php b/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php index b7ae8ddd4d..3b9450f4e0 100644 --- a/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php +++ b/app/Services/EDocument/Standards/Verifactu/Models/Invoice.php @@ -59,7 +59,6 @@ class Invoice extends BaseXmlModel implements XmlModelInterface protected string $tipoHuella; protected string $huella; protected ?string $signature = null; - protected ?FacturaRectificativa $facturaRectificativa = null; protected ?string $privateKeyPath = null; protected ?string $publicKeyPath = null; protected ?string $certificatePath = null; @@ -500,16 +499,6 @@ class Invoice extends BaseXmlModel implements XmlModelInterface return $this; } - public function getFacturaRectificativa(): ?FacturaRectificativa - { - return $this->facturaRectificativa; - } - - public function setFacturaRectificativa(FacturaRectificativa $facturaRectificativa): void - { - $this->facturaRectificativa = $facturaRectificativa; - } - /** * Helper method to create a rectificative invoice with proper configuration * @@ -578,7 +567,6 @@ class Invoice extends BaseXmlModel implements XmlModelInterface } - /** * Validate that the invoice is properly configured for its type * @@ -589,29 +577,29 @@ class Invoice extends BaseXmlModel implements XmlModelInterface { // Basic validation for all invoice types if (empty($this->idVersion)) { - throw new \InvalidArgumentException('IDVersion is required'); + throw new \InvalidArgumentException('Missing required field: IDVersion'); } if (empty($this->nombreRazonEmisor)) { - throw new \InvalidArgumentException('NombreRazonEmisor is required'); + throw new \InvalidArgumentException('Missing required field: NombreRazonEmisor'); } if (empty($this->descripcionOperacion)) { - throw new \InvalidArgumentException('DescripcionOperacion is required'); + throw new \InvalidArgumentException('Missing required field: DescripcionOperacion'); } if ($this->tipoFactura !== self::TIPO_FACTURA_RECTIFICATIVA && $this->cuotaTotal < 0) { - throw new \InvalidArgumentException('CuotaTotal must be a positive number'); + throw new \InvalidArgumentException('Missing required field: CuotaTotal'); } if ($this->tipoFactura !== self::TIPO_FACTURA_RECTIFICATIVA && $this->importeTotal < 0) { - throw new \InvalidArgumentException('ImporteTotal must be a positive number'); + throw new \InvalidArgumentException('Missing required field: ImporteTotal'); } // Specific validation for R1 invoices if ($this->tipoFactura === self::TIPO_FACTURA_RECTIFICATIVA) { if ($this->tipoRectificativa === null) { - throw new \InvalidArgumentException('TipoRectificativa is required for R1 invoices'); + throw new \InvalidArgumentException('Missing required field: TipoRectificativa'); } if (!in_array($this->tipoRectificativa, [self::TIPO_RECTIFICATIVA_COMPLETA, self::TIPO_RECTIFICATIVA_SUSTITUTIVA])) { @@ -620,115 +608,13 @@ class Invoice extends BaseXmlModel implements XmlModelInterface // For substitutive rectifications, ImporteRectificacion is mandatory if ($this->tipoRectificativa === self::TIPO_RECTIFICATIVA_SUSTITUTIVA && $this->importeRectificacion === null) { - throw new \InvalidArgumentException('ImporteRectificacion is mandatory for substitutive rectifications (TipoRectificativa = S)'); + throw new \InvalidArgumentException('Missing required field: ImporteRectificacion'); } } return true; } - /** - * Set up the rectified invoice information for R1 invoices - * - * @param string $nif The NIF of the rectified invoice - * @param string $numSerie The series number of the rectified invoice - * @param string $fecha The date of the rectified invoice - * @return self - */ - public function setRectifiedInvoice(string $nif, string $numSerie, string $fecha): self - { - if ($this->tipoFactura !== self::TIPO_FACTURA_RECTIFICATIVA) { - throw new \InvalidArgumentException('This method can only be used for R1 invoices'); - } - - if ($this->facturaRectificativa === null) { - // Create FacturaRectificativa with proper values for the rectified amounts - // For R1 invoices, we need to set the base and tax amounts that were rectified - $baseRectificada = $this->importeTotal ?? 0.0; // Use current invoice total as base - $cuotaRectificada = $this->cuotaTotal ?? 0.0; // Use current invoice tax as tax - - $this->facturaRectificativa = new FacturaRectificativa( - $this->tipoRectificativa ?? 'S', // Default to substitutive if not set - $baseRectificada, - $cuotaRectificada - ); - } - - $this->facturaRectificativa->setRectifiedInvoice($nif, $numSerie, $fecha); - return $this; - } - - /** - * Set up the rectified invoice information for R1 invoices using an IDFactura object - * - * @param IDFactura $idFactura The IDFactura object of the rectified invoice - * @return self - */ - public function setRectifiedInvoiceFromIDFactura(IDFactura $idFactura): self - { - if ($this->tipoFactura !== self::TIPO_FACTURA_RECTIFICATIVA) { - throw new \InvalidArgumentException('This method can only be used for R1 invoices'); - } - - if ($this->facturaRectificativa === null) { - // Create FacturaRectificativa with proper values for the rectified amounts - // For R1 invoices, we need to set the base and tax amounts that were rectified - $baseRectificada = $this->importeTotal ?? 0.0; // Use current invoice total as base - $cuotaRectificada = $this->cuotaTotal ?? 0.0; // Use current invoice tax as tax - - $this->facturaRectificativa = new FacturaRectificativa( - $this->tipoRectificativa ?? 'S', // Default to substitutive if not set - $baseRectificada, - $cuotaRectificada - ); - } - - $this->facturaRectificativa->setRectifiedInvoiceFromIDFactura($idFactura); - return $this; - } - - /** - * Set the rectified amounts for R1 invoices - * - * @param float $baseRectificada The base amount that was rectified - * @param float $cuotaRectificada The tax amount that was rectified - * @param float|null $cuotaRecargoRectificado The surcharge amount that was rectified (optional) - * @return self - */ - public function setRectifiedAmounts(float $baseRectificada, float $cuotaRectificada, ?float $cuotaRecargoRectificado = null): self - { - if ($this->tipoFactura !== self::TIPO_FACTURA_RECTIFICATIVA) { - throw new \InvalidArgumentException('This method can only be used for R1 invoices'); - } - - // Store the existing rectified invoice information if available - $existingRectifiedInvoice = null; - if ($this->facturaRectificativa !== null) { - $existingRectifiedInvoice = $this->facturaRectificativa->getFacturasRectificadas(); - } - - // Create new FacturaRectificativa with the specified amounts - $this->facturaRectificativa = new FacturaRectificativa( - $this->tipoRectificativa ?? 'S', - $baseRectificada, - $cuotaRectificada, - $cuotaRecargoRectificado - ); - - // Restore the rectified invoice information if it existed - if ($existingRectifiedInvoice !== null && !empty($existingRectifiedInvoice)) { - foreach ($existingRectifiedInvoice as $rectifiedInvoice) { - $this->facturaRectificativa->addFacturaRectificada( - $rectifiedInvoice['nif'], - $rectifiedInvoice['numSerie'], - $rectifiedInvoice['fecha'] - ); - } - } - - return $this; - } - public function setPrivateKeyPath(string $path): self { $this->privateKeyPath = $path; diff --git a/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php b/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php index f3caf5bad1..14a420e2a7 100644 --- a/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php +++ b/tests/Feature/EInvoice/Verifactu/VerifactuFeatureTest.php @@ -27,7 +27,6 @@ use App\Services\EDocument\Standards\Verifactu\ResponseProcessor; use App\Services\EDocument\Standards\Verifactu\Models\Encadenamiento; use App\Services\EDocument\Standards\Verifactu\Models\RegistroAnterior; use App\Services\EDocument\Standards\Validation\VerifactuDocumentValidator; -use App\Services\EDocument\Standards\Verifactu\Models\FacturaRectificativa; use App\Services\EDocument\Standards\Verifactu\Models\Invoice as VerifactuInvoice; class VerifactuFeatureTest extends TestCase diff --git a/tests/Feature/EInvoice/Verifactu/VerifactuModelTest.php b/tests/Feature/EInvoice/Verifactu/VerifactuModelTest.php index 14a8500d1f..2c2d1ecec2 100644 --- a/tests/Feature/EInvoice/Verifactu/VerifactuModelTest.php +++ b/tests/Feature/EInvoice/Verifactu/VerifactuModelTest.php @@ -20,7 +20,6 @@ use App\Services\EDocument\Standards\Verifactu\Models\Encadenamiento; use App\Services\EDocument\Standards\Verifactu\Models\DetalleDesglose; use App\Services\EDocument\Standards\Verifactu\Models\SistemaInformatico; use App\Services\EDocument\Standards\Validation\VerifactuDocumentValidator; -use App\Services\EDocument\Standards\Verifactu\Models\FacturaRectificativa; use App\Services\EDocument\Standards\Verifactu\Models\PrimerRegistroCadena; use App\Services\EDocument\Standards\Verifactu\Models\PersonaFisicaJuridica; use App\Services\EDocument\Standards\Verifactu\Models\IDOtro; @@ -291,188 +290,6 @@ $this->assertCount(0, $errors); $this->assertEquals($invoice->getTipoFactura(), $deserialized->getTipoFactura()); } - public function testCreateAndSerializeRectificationInvoice(): void - { - $invoice = new Invoice(); - $invoice - ->setIdVersion('1.0') - ->setIdFactura((new \App\Services\EDocument\Standards\Verifactu\Models\IDFactura()) - ->setIdEmisorFactura('B12345678') - ->setNumSerieFactura('FAC-2023-003') - ->setFechaExpedicionFactura('01-01-2023')) - ->setNombreRazonEmisor('Empresa Ejemplo SL') - ->setTipoFactura('R1') - ->setTipoRectificativa('I') - ->setDescripcionOperacion('Rectificación de factura anterior') - ->setCuotaTotal(-21.00) - ->setImporteTotal(-100.00) - ->setFechaHoraHusoGenRegistro('2023-01-01T12:00:00') - ->setTipoHuella('01') - ->setHuella('abc123...'); - - // Add information system - $sistema = new SistemaInformatico(); - $sistema - ->setNombreRazon('Sistema de Facturación') - ->setNif('B12345678') - ->setNombreSistemaInformatico('SistemaFacturacion') - ->setIdSistemaInformatico('01') - ->setVersion('1.0') - ->setNumeroInstalacion('INST-001') - ->setTipoUsoPosibleSoloVerifactu('S') - ->setTipoUsoPosibleMultiOT('S') - ->setIndicadorMultiplesOT('S'); - $invoice->setSistemaInformatico($sistema); - - // Add desglose - $desglose = new Desglose(); - $desglose->setDesgloseIVA([ - 'Impuesto' => '01', - 'ClaveRegimen' => '02', - 'CalificacionOperacion' => 'S2', - 'BaseImponibleOimporteNoSujeto' => -100.00, - 'TipoImpositivo' => 21, - 'CuotaRepercutida' => -21.00 - ]); - $invoice->setDesglose($desglose); - - // Add encadenamiento - $encadenamiento = new Encadenamiento(); - $encadenamiento->setPrimerRegistro('S'); - $invoice->setEncadenamiento($encadenamiento); - - // Add rectified invoice - $facturaRectificativa = new FacturaRectificativa( - 'I', // tipoRectificativa - -100.00, // baseRectificada - -21.00 // cuotaRectificada - ); - $facturaRectificativa->addFacturaRectificada( - 'B12345678', // nif - 'FAC-2023-001', // numSerie - '01-01-2023' // fecha - ); - $invoice->setFacturaRectificativa($facturaRectificativa); - - $xml = $invoice->toXmlString(); - - -$xslt = new VerifactuDocumentValidator($xml); -$xslt->validate(); -$errors = $xslt->getVerifactuErrors(); - -if (count($errors) > 0) { - nlog($xml); - nlog($errors); -} - -$this->assertCount(0, $errors); - - // Test deserialization - $deserialized = Invoice::fromXml($xml); - $this->assertEquals($invoice->getIdVersion(), $deserialized->getIdVersion()); - $this->assertEquals($invoice->getIdFactura(), $deserialized->getIdFactura()); - $this->assertEquals($invoice->getNombreRazonEmisor(), $deserialized->getNombreRazonEmisor()); - $this->assertEquals($invoice->getTipoFactura(), $deserialized->getTipoFactura()); - $this->assertEquals($invoice->getTipoRectificativa(), $deserialized->getTipoRectificativa()); - } - - public function testCreateAndSerializeR1InvoiceWithImporteRectificacion(): void - { - $invoice = new Invoice(); - $invoice - ->setIdVersion('1.0') - ->setIdFactura((new \App\Services\EDocument\Standards\Verifactu\Models\IDFactura()) - ->setIdEmisorFactura('B12345678') - ->setNumSerieFactura('FAC-2023-004') - ->setFechaExpedicionFactura('01-01-2023')) - ->setNombreRazonEmisor('Empresa Ejemplo SL') - ->setTipoFactura('R1') - ->setTipoRectificativa('I') - ->setImporteRectificacion(100.00) - ->setDescripcionOperacion('Rectificación completa de factura anterior') - ->setCuotaTotal(21.00) - ->setImporteTotal(100.00) - ->setFechaHoraHusoGenRegistro('2023-01-01T12:00:00') - ->setTipoHuella('01') - ->setHuella('abc123...'); - - // Add information system - $sistema = new SistemaInformatico(); - $sistema - ->setNombreRazon('Sistema de Facturación') - ->setNif('B12345678') - ->setNombreSistemaInformatico('SistemaFacturacion') - ->setIdSistemaInformatico('01') - ->setVersion('1.0') - ->setNumeroInstalacion('INST-001') - ->setTipoUsoPosibleSoloVerifactu('S') - ->setTipoUsoPosibleMultiOT('S') - ->setIndicadorMultiplesOT('S'); - $invoice->setSistemaInformatico($sistema); - - // Add desglose - $desglose = new Desglose(); - $desglose->setDesgloseIVA([ - 'Impuesto' => '01', - 'ClaveRegimen' => '02', - 'CalificacionOperacion' => 'S2', - 'BaseImponibleOimporteNoSujeto' => 100.00, - 'TipoImpositivo' => 21, - 'CuotaRepercutida' => 21.00 - ]); - $invoice->setDesglose($desglose); - - // Add encadenamiento - $encadenamiento = new Encadenamiento(); - $encadenamiento->setPrimerRegistro('S'); - $invoice->setEncadenamiento($encadenamiento); - - // Add rectified invoice - $facturaRectificativa = new FacturaRectificativa( - 'I', // tipoRectificativa - 100.00, // baseRectificada - 21.00 // cuotaRectificada - ); - $facturaRectificativa->addFacturaRectificada( - 'B12345678', // nif - 'FAC-2023-001', // numSerie - '01-01-2023' // fecha - ); - $invoice->setFacturaRectificativa($facturaRectificativa); - - $xml = $invoice->toXmlString(); - - // Debug: Check if the property is set correctly - $this->assertEquals(100.00, $invoice->getImporteRectificacion()); - $this->assertEquals('R1', $invoice->getTipoFactura()); - - // Debug: Log the XML to see what's actually generated - nlog('Generated XML: ' . $xml); - - // Verify that ImporteRectificacion is included in the XML - // Note: The XML includes namespace prefix 'sum1:' and the value is formatted as '100' not '100.00' - $this->assertStringContainsString('100', $xml); - - // Validate against Verifactu schema - $xslt = new VerifactuDocumentValidator($xml); - $xslt->validate(); - $errors = $xslt->getVerifactuErrors(); - - if (count($errors) > 0) { - nlog($xml); - nlog($errors); - } - - $this->assertCount(0, $errors); - - // Test deserialization - $deserialized = Invoice::fromXml($xml); - $this->assertEquals($invoice->getIdVersion(), $deserialized->getIdVersion()); - $this->assertEquals($invoice->getTipoFactura(), $deserialized->getTipoFactura()); - $this->assertEquals($invoice->getTipoRectificativa(), $deserialized->getTipoRectificativa()); - $this->assertEquals($invoice->getImporteRectificacion(), $deserialized->getImporteRectificacion()); - } public function testCreateAndSerializeInvoiceWithoutRecipient(): void { @@ -485,7 +302,6 @@ $this->assertCount(0, $errors); ->setFechaExpedicionFactura('01-01-2023')) ->setNombreRazonEmisor('Empresa Ejemplo SL') ->setTipoFactura('F1') - ->setFacturaSinIdentifDestinatarioArt61d('S') ->setDescripcionOperacion('Venta de productos varios') ->setCuotaTotal(21.00) ->setImporteTotal(100.00) @@ -523,16 +339,16 @@ $this->assertCount(0, $errors); $xml = $invoice->toXmlString(); -$xslt = new VerifactuDocumentValidator($xml); -$xslt->validate(); -$errors = $xslt->getVerifactuErrors(); + $xslt = new VerifactuDocumentValidator($xml); + $xslt->validate(); + $errors = $xslt->getVerifactuErrors(); -if (count($errors) > 0) { - nlog($xml); - nlog($errors); -} + if (count($errors) > 0) { + nlog($xml); + nlog($errors); + } -$this->assertCount(0, $errors); + $this->assertCount(0, $errors); // Test deserialization $deserialized = Invoice::fromXml($xml); @@ -540,7 +356,6 @@ $this->assertCount(0, $errors); $this->assertEquals($invoice->getIdFactura(), $deserialized->getIdFactura()); $this->assertEquals($invoice->getNombreRazonEmisor(), $deserialized->getNombreRazonEmisor()); $this->assertEquals($invoice->getTipoFactura(), $deserialized->getTipoFactura()); - $this->assertEquals($invoice->getFacturaSinIdentifDestinatarioArt61d(), $deserialized->getFacturaSinIdentifDestinatarioArt61d()); $this->assertEquals($invoice->getCuotaTotal(), $deserialized->getCuotaTotal()); $this->assertEquals($invoice->getImporteTotal(), $deserialized->getImporteTotal()); } @@ -557,93 +372,13 @@ $this->assertCount(0, $errors); { $invoice = new Invoice(); + $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Missing required field: IDVersion'); - + $invoice->toXmlString(); - } - - public function test_create_and_serialize_rectification_invoice() - { - $invoice = new Invoice(); - $invoice->setIdVersion('1.0') - ->setIdFactura((new \App\Services\EDocument\Standards\Verifactu\Models\IDFactura()) - ->setIdEmisorFactura('B12345678') - ->setNumSerieFactura('FAC-2023-001') - ->setFechaExpedicionFactura('01-01-2023')) - ->setRefExterna('REF-123') - ->setNombreRazonEmisor('Empresa Ejemplo SL') - ->setTipoFactura('R1') - ->setTipoRectificativa('S') - ->setDescripcionOperacion('Rectificación de factura') - ->setTercero((new PersonaFisicaJuridica()) - ->setNif('B12345678') - ->setRazonSocial('Empresa Ejemplo SL')) - ->setDesglose((new Desglose()) - ->setDesgloseIVA([ - 'Impuesto' => '01', - 'ClaveRegimen' => '01', - 'CalificacionOperacion' => 'S1', - 'BaseImponibleOimporteNoSujeto' => 1000.00, - 'TipoImpositivo' => 21.00, - 'CuotaRepercutida' => 210.00 - ])) - ->setCuotaTotal(210) - ->setImporteTotal(1000) - ->setSistemaInformatico((new SistemaInformatico()) - ->setNombreRazon('Sistema de Facturación') - ->setNif('B12345678') - ->setNombreSistemaInformatico('SistemaFacturacion') - ->setIdSistemaInformatico('01') - ->setVersion('1.0') - ->setNumeroInstalacion('INST-001')) - ->setFechaHoraHusoGenRegistro('2023-01-01T12:00:00') - ->setTipoHuella('01') - ->setHuella('abc123...'); - - // Create Encadenamiento with PrimerRegistroCadena - $encadenamiento = new Encadenamiento(); - $encadenamiento->setPrimerRegistro('S'); - $invoice->setEncadenamiento($encadenamiento); - - $facturaRectificativa = new FacturaRectificativa( - 'S', // TipoRectificativa (S for substitutive) - 1000.00, // BaseRectificada - 210.00, // CuotaRectificada - null // CuotaRecargoRectificado (optional) - ); - - // Add a rectified invoice - $facturaRectificativa->addFacturaRectificada( - 'B12345678', // NIF - 'FAC-2023-001', // NumSerieFactura - '24-04-2025' // FechaExpedicionFactura - ); - - $invoice->setFacturaRectificativa($facturaRectificativa); - - $xml = $invoice->toXmlString(); - -$xslt = new VerifactuDocumentValidator($xml); -$xslt->validate(); -$errors = $xslt->getVerifactuErrors(); - -if (count($errors) > 0) { - nlog($xml); - nlog($errors); -} - -$this->assertCount(0, $errors); - // Test deserialization - $deserialized = Invoice::fromXml($xml); - $this->assertEquals($invoice->getIdVersion(), $deserialized->getIdVersion()); - $this->assertEquals($invoice->getIdFactura(), $deserialized->getIdFactura()); - $this->assertEquals($invoice->getTipoFactura(), $deserialized->getTipoFactura()); - $this->assertEquals($invoice->getTipoRectificativa(), $deserialized->getTipoRectificativa()); - $this->assertEquals($invoice->getCuotaTotal(), $deserialized->getCuotaTotal()); - $this->assertEquals($invoice->getImporteTotal(), $deserialized->getImporteTotal()); } public function testCreateAndSerializeInvoiceWithMultipleRecipients(): void @@ -676,7 +411,7 @@ $this->assertCount(0, $errors); $destinatario2 ->setPais('FR') ->setTipoIdentificacion('02') - // ->setIdOtro('FR12345678901') + ->setNif('FR1235678') ->setNombreRazon('Client 2 SARL'); $destinatarios[] = $destinatario2; @@ -716,16 +451,16 @@ $this->assertCount(0, $errors); // Generate XML string $xml = $invoice->toXmlString(); -$xslt = new VerifactuDocumentValidator($xml); -$xslt->validate(); -$errors = $xslt->getVerifactuErrors(); + $xslt = new VerifactuDocumentValidator($xml); + $xslt->validate(); + $errors = $xslt->getVerifactuErrors(); -if (count($errors) > 0) { - nlog($xml); - nlog($errors); -} + if (count($errors) > 0) { + nlog($xml); + nlog($errors); + } -$this->assertCount(0, $errors); + $this->assertCount(0, $errors); // Test deserialization $deserialized = Invoice::fromXml($xml); @@ -737,10 +472,7 @@ $this->assertCount(0, $errors); // Verify second recipient (with IDOtro) $this->assertEquals('Client 2 SARL', $deserialized->getDestinatarios()[1]->getNombreRazon()); - $this->assertEquals('FR', $deserialized->getDestinatarios()[1]->getPais()); - $this->assertEquals('02', $deserialized->getDestinatarios()[1]->getTipoIdentificacion()); - $this->assertEquals('FR12345678901', $deserialized->getDestinatarios()[1]->getIdOtro()); - $this->assertNull($deserialized->getDestinatarios()[1]->getNif()); + } public function testCreateAndSerializeInvoiceWithExemptOperation(): void