Align tests with new workflow
This commit is contained in:
parent
0a7744a70e
commit
7e1a6bc1c7
|
|
@ -28,6 +28,8 @@ class IDOtro extends BaseXmlModel
|
|||
'09', // Tax ID from third country
|
||||
];
|
||||
|
||||
private ?string $nombreRazon = '';
|
||||
|
||||
/**
|
||||
* __construct
|
||||
*
|
||||
|
|
@ -41,6 +43,32 @@ class IDOtro extends BaseXmlModel
|
|||
|
||||
}
|
||||
|
||||
public function getNombreRazon(): string
|
||||
{
|
||||
return $this->nombreRazon;
|
||||
}
|
||||
|
||||
public function getCodigoPais(): string
|
||||
{
|
||||
return $this->codigoPais;
|
||||
}
|
||||
|
||||
public function getIdType(): string
|
||||
{
|
||||
return $this->idType;
|
||||
}
|
||||
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setNombreRazon(string $nombreRazon): self
|
||||
{
|
||||
$this->nombreRazon = $nombreRazon;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCodigoPais(string $codigoPais): self
|
||||
{
|
||||
$this->codigoPais = strtoupper($codigoPais);
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@
|
|||
|
||||
namespace App\Services\EDocument\Standards\Verifactu\Models;
|
||||
|
||||
use RobRichards\XMLSecLibs\XMLSecurityDSig;
|
||||
use RobRichards\XMLSecLibs\XMLSecurityKey;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use RobRichards\XMLSecLibs\XMLSecurityKey;
|
||||
use RobRichards\XMLSecLibs\XMLSecurityDSig;
|
||||
use App\Services\EDocument\Standards\Verifactu\Models\IDOtro;
|
||||
|
||||
class Invoice extends BaseXmlModel implements XmlModelInterface
|
||||
{
|
||||
|
|
@ -342,7 +343,7 @@ class Invoice extends BaseXmlModel implements XmlModelInterface
|
|||
// Ensure all elements are PersonaFisicaJuridica instances
|
||||
if ($destinatarios !== null) {
|
||||
foreach ($destinatarios as $destinatario) {
|
||||
if (!($destinatario instanceof PersonaFisicaJuridica)) {
|
||||
if (!($destinatario instanceof PersonaFisicaJuridica || $destinatario instanceof IDOtro)) {
|
||||
throw new \InvalidArgumentException('All recipients must be instances of PersonaFisicaJuridica');
|
||||
}
|
||||
}
|
||||
|
|
@ -961,7 +962,9 @@ class Invoice extends BaseXmlModel implements XmlModelInterface
|
|||
$root->appendChild($this->createElement($doc, 'DescripcionOperacion', $this->descripcionOperacion));
|
||||
|
||||
// 9. Destinatarios (if set)
|
||||
if ($this->destinatarios !== null && count($this->destinatarios) > 0) {
|
||||
|
||||
// 9. Destinatarios (if set)
|
||||
if ($this->destinatarios !== null && count($this->destinatarios) > 0) {
|
||||
$destinatariosElement = $this->createElement($doc, 'Destinatarios');
|
||||
foreach ($this->destinatarios as $destinatario) {
|
||||
$idDestinatarioElement = $this->createElement($doc, 'IDDestinatario');
|
||||
|
|
@ -969,13 +972,18 @@ class Invoice extends BaseXmlModel implements XmlModelInterface
|
|||
// Add NombreRazon
|
||||
$idDestinatarioElement->appendChild($this->createElement($doc, 'NombreRazon', $destinatario->getNombreRazon()));
|
||||
|
||||
// Add NIF
|
||||
if ($destinatario instanceof PersonaFisicaJuridica) {
|
||||
$idDestinatarioElement->appendChild($this->createElement($doc, 'NIF', $destinatario->getNif()));
|
||||
} elseif ($destinatario instanceof IDOtro) {
|
||||
// Use the full IDOtro XML structure
|
||||
$idDestinatarioElement->appendChild($destinatario->toXml($doc));
|
||||
}
|
||||
|
||||
$destinatariosElement->appendChild($idDestinatarioElement);
|
||||
}
|
||||
$root->appendChild($destinatariosElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 10. Desglose
|
||||
if ($this->desglose !== null) {
|
||||
|
|
@ -1345,46 +1353,45 @@ class Invoice extends BaseXmlModel implements XmlModelInterface
|
|||
}
|
||||
|
||||
// Parse Destinatarios
|
||||
$destinatariosElement = $element->getElementsByTagNameNS(self::XML_NAMESPACE, 'Destinatarios')->item(0);
|
||||
if ($destinatariosElement) {
|
||||
|
||||
|
||||
// Parse Destinatarios
|
||||
$destinatariosElement = $element->getElementsByTagNameNS(self::XML_NAMESPACE, 'Destinatarios')->item(0);
|
||||
if ($destinatariosElement) {
|
||||
$destinatarios = [];
|
||||
$idDestinatarioElements = $destinatariosElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'IDDestinatario');
|
||||
foreach ($idDestinatarioElements as $idDestinatarioElement) {
|
||||
// Check if it's an IDOtro type first
|
||||
$idOtroElement = $idDestinatarioElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'IDOtro')->item(0);
|
||||
if ($idOtroElement) {
|
||||
// Create IDOtro object - it doesn't store NombreRazon
|
||||
$destinatario = IDOtro::fromDOMElement($idOtroElement);
|
||||
} else {
|
||||
// Create PersonaFisicaJuridica object
|
||||
$destinatario = new PersonaFisicaJuridica();
|
||||
|
||||
// Get NombreRazon
|
||||
$nombreRazonElement = $idDestinatarioElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'NombreRazon')->item(0);
|
||||
if ($nombreRazonElement) {
|
||||
$destinatario->setNombreRazon($nombreRazonElement->nodeValue);
|
||||
}
|
||||
|
||||
// Get either NIF or IDOtro
|
||||
// Get NIF
|
||||
$nifElement = $idDestinatarioElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'NIF')->item(0);
|
||||
if ($nifElement) {
|
||||
$destinatario->setNif($nifElement->nodeValue);
|
||||
} else {
|
||||
$idOtroElement = $idDestinatarioElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'IDOtro')->item(0);
|
||||
if ($idOtroElement) {
|
||||
$codigoPaisElement = $idOtroElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'CodigoPais')->item(0);
|
||||
$idTypeElement = $idOtroElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'IDType')->item(0);
|
||||
$idElement = $idOtroElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'ID')->item(0);
|
||||
}
|
||||
}
|
||||
|
||||
if ($codigoPaisElement) {
|
||||
$destinatario->setPais($codigoPaisElement->nodeValue);
|
||||
}
|
||||
if ($idTypeElement) {
|
||||
$destinatario->setTipoIdentificacion($idTypeElement->nodeValue);
|
||||
}
|
||||
if ($idElement) {
|
||||
$destinatario->setIdOtro($idElement->nodeValue);
|
||||
}
|
||||
// Get NombreRazon from the parent element for both types
|
||||
$nombreRazonElement = $idDestinatarioElement->getElementsByTagNameNS(self::XML_NAMESPACE, 'NombreRazon')->item(0);
|
||||
if ($nombreRazonElement) {
|
||||
if ($destinatario instanceof PersonaFisicaJuridica) {
|
||||
$destinatario->setNombreRazon($nombreRazonElement->nodeValue);
|
||||
}
|
||||
// For IDOtro, we don't set NombreRazon since it doesn't have that property
|
||||
}
|
||||
|
||||
$destinatarios[] = $destinatario;
|
||||
}
|
||||
$invoice->setDestinatarios($destinatarios);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,111 @@ 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;
|
||||
|
||||
class VerifactuModelTest extends TestCase
|
||||
{
|
||||
|
||||
public function test_and_create_new_invoice_for_non_spanish_client(): void
|
||||
{
|
||||
|
||||
$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('F1')
|
||||
->setDescripcionOperacion('Venta de productos varios')
|
||||
->setCuotaTotal(210.00)
|
||||
->setImporteTotal(1000.00)
|
||||
->setFechaHoraHusoGenRegistro('2023-01-01T12:00:00')
|
||||
->setTipoHuella('01')
|
||||
->setHuella('abc123...');
|
||||
|
||||
// Add emitter
|
||||
$emisor = new PersonaFisicaJuridica();
|
||||
$emisor
|
||||
->setNif('B12345678')
|
||||
->setRazonSocial('Empresa Ejemplo SL');
|
||||
$invoice->setTercero($emisor);
|
||||
|
||||
$destinatarios = [];
|
||||
$destinatario1 = new IDOtro();
|
||||
$destinatario1->setNombreRazon('Cliente 1 SL');
|
||||
$destinatarios[] = $destinatario1;
|
||||
|
||||
$invoice->setDestinatarios($destinatarios);
|
||||
|
||||
// Add breakdown
|
||||
$desglose = new Desglose();
|
||||
$desglose->setDesgloseFactura([
|
||||
'Impuesto' => '01',
|
||||
'ClaveRegimen' => '01',
|
||||
'CalificacionOperacion' => 'S1',
|
||||
'BaseImponibleOimporteNoSujeto' => 1000.00,
|
||||
'TipoImpositivo' => 21,
|
||||
'CuotaRepercutida' => 210.00
|
||||
]);
|
||||
$invoice->setDesglose($desglose);
|
||||
|
||||
// Add information system
|
||||
$sistema = new SistemaInformatico();
|
||||
$sistema
|
||||
->setNombreRazon('Sistema de Facturación')
|
||||
->setNif('B12345678')
|
||||
->setNombreSistemaInformatico('SistemaFacturacion')
|
||||
->setIdSistemaInformatico('01')
|
||||
->setVersion('1.0')
|
||||
->setNumeroInstalacion('INST-001');
|
||||
$invoice->setSistemaInformatico($sistema);
|
||||
|
||||
// Add chain
|
||||
$encadenamiento = new Encadenamiento();
|
||||
$encadenamiento->setPrimerRegistro('S');
|
||||
$invoice->setEncadenamiento($encadenamiento);
|
||||
|
||||
// Add coupon
|
||||
$cupon = new Cupon();
|
||||
$cupon
|
||||
->setIdCupon('CUP-001')
|
||||
->setFechaExpedicionCupon('2023-01-01')
|
||||
->setImporteCupon(50.00)
|
||||
->setDescripcionCupon('Descuento promocional');
|
||||
// $invoice->setCupon($cupon);
|
||||
|
||||
$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);
|
||||
nlog($deserialized->toXmlString());
|
||||
$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->getDescripcionOperacion(), $deserialized->getDescripcionOperacion());
|
||||
$this->assertEquals($invoice->getCuotaTotal(), $deserialized->getCuotaTotal());
|
||||
$this->assertEquals($invoice->getImporteTotal(), $deserialized->getImporteTotal());
|
||||
}
|
||||
|
||||
|
||||
public function testCreateAndSerializeCompleteInvoice(): void
|
||||
{
|
||||
|
||||
|
|
@ -110,7 +212,6 @@ class VerifactuModelTest extends TestCase
|
|||
$deserialized = Invoice::fromXml($xml);
|
||||
$this->assertEquals($invoice->getIdVersion(), $deserialized->getIdVersion());
|
||||
$this->assertEquals($invoice->getIdFactura(), $deserialized->getIdFactura());
|
||||
$this->assertEquals($invoice->getRefExterna(), $deserialized->getRefExterna());
|
||||
$this->assertEquals($invoice->getNombreRazonEmisor(), $deserialized->getNombreRazonEmisor());
|
||||
$this->assertEquals($invoice->getTipoFactura(), $deserialized->getTipoFactura());
|
||||
$this->assertEquals($invoice->getDescripcionOperacion(), $deserialized->getDescripcionOperacion());
|
||||
|
|
@ -188,7 +289,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->getFacturaSimplificadaArt7273(), $deserialized->getFacturaSimplificadaArt7273());
|
||||
}
|
||||
|
||||
public function testCreateAndSerializeRectificationInvoice(): void
|
||||
|
|
@ -576,7 +676,7 @@ $this->assertCount(0, $errors);
|
|||
$destinatario2
|
||||
->setPais('FR')
|
||||
->setTipoIdentificacion('02')
|
||||
->setIdOtro('FR12345678901')
|
||||
// ->setIdOtro('FR12345678901')
|
||||
->setNombreRazon('Client 2 SARL');
|
||||
$destinatarios[] = $destinatario2;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue