Updates for models

This commit is contained in:
David Bomba 2025-05-01 17:40:18 +10:00
parent 2444eacb13
commit 794a792b39
10 changed files with 439 additions and 263 deletions

View File

@ -4,35 +4,29 @@ namespace App\Services\EDocument\Standards\Verifactu\Types;
class Desglose class Desglose
{ {
/** @var Detalle[] */ /** @var array<DetalleDesglose> */
protected $detalle = []; protected $DetalleDesglose = [];
/** /**
* @return Detalle[] * @return array<DetalleDesglose>
*/ */
public function getDetalle(): array public function getDetalleDesglose(): array
{ {
return $this->detalle; return $this->DetalleDesglose;
} }
public function addDetalle(Detalle $detalle): self public function addDetalleDesglose(DetalleDesglose $detalle): self
{ {
if (count($this->detalle) >= 1000) { $this->DetalleDesglose[] = $detalle;
throw new \RuntimeException('Maximum number of Detalle (1000) exceeded');
}
$this->detalle[] = $detalle;
return $this; return $this;
} }
/** /**
* @param Detalle[] $detalle * @param array<DetalleDesglose> $detalles
*/ */
public function setDetalle(array $detalle): self public function setDetalleDesglose(array $detalles): self
{ {
if (count($detalle) > 1000) { $this->DetalleDesglose = $detalles;
throw new \RuntimeException('Maximum number of Detalle (1000) exceeded');
}
$this->detalle = $detalle;
return $this; return $this;
} }
} }

View File

@ -0,0 +1,159 @@
<?php
namespace App\Services\EDocument\Standards\Verifactu\Types;
class DetalleDesglose
{
/** @var string */
protected $ClaveRegimen;
/** @var string */
protected $CalificacionOperacion;
/** @var string|null */
protected $OperacionExenta;
/** @var float|null */
protected $TipoImpositivo;
/** @var float */
protected $BaseImponibleOimporteNoSujeto;
/** @var float|null */
protected $BaseImponibleACoste;
/** @var float|null */
protected $CuotaRepercutida;
/** @var float|null */
protected $TipoRecargoEquivalencia;
/** @var float|null */
protected $CuotaRecargoEquivalencia;
public function getClaveRegimen(): string
{
return $this->ClaveRegimen;
}
public function setClaveRegimen(string $claveRegimen): self
{
if (!preg_match('/^\d{2}$/', $claveRegimen)) {
throw new \InvalidArgumentException('ClaveRegimen must be a 2-digit number');
}
$this->ClaveRegimen = $claveRegimen;
return $this;
}
public function getCalificacionOperacion(): string
{
return $this->CalificacionOperacion;
}
public function setCalificacionOperacion(string $calificacionOperacion): self
{
if (!preg_match('/^[A-Z]\d$/', $calificacionOperacion)) {
throw new \InvalidArgumentException('CalificacionOperacion must be a letter followed by a digit');
}
if ($this->OperacionExenta !== null) {
throw new \InvalidArgumentException('Cannot set CalificacionOperacion when OperacionExenta is set');
}
$this->CalificacionOperacion = $calificacionOperacion;
return $this;
}
public function getOperacionExenta(): ?string
{
return $this->OperacionExenta;
}
public function setOperacionExenta(?string $operacionExenta): self
{
if ($operacionExenta !== null) {
if (!preg_match('/^[A-Z]\d$/', $operacionExenta)) {
throw new \InvalidArgumentException('OperacionExenta must be a letter followed by a digit');
}
if ($this->CalificacionOperacion !== null) {
throw new \InvalidArgumentException('Cannot set OperacionExenta when CalificacionOperacion is set');
}
}
$this->OperacionExenta = $operacionExenta;
return $this;
}
public function getTipoImpositivo(): ?float
{
return $this->TipoImpositivo;
}
public function setTipoImpositivo(?float $tipoImpositivo): self
{
if ($tipoImpositivo !== null) {
if ($tipoImpositivo < 0 || $tipoImpositivo > 100) {
throw new \InvalidArgumentException('TipoImpositivo must be between 0 and 100');
}
}
$this->TipoImpositivo = $tipoImpositivo;
return $this;
}
public function getBaseImponibleOimporteNoSujeto(): float
{
return $this->BaseImponibleOimporteNoSujeto;
}
public function setBaseImponibleOimporteNoSujeto(float $baseImponibleOimporteNoSujeto): self
{
$this->BaseImponibleOimporteNoSujeto = $baseImponibleOimporteNoSujeto;
return $this;
}
public function getBaseImponibleACoste(): ?float
{
return $this->BaseImponibleACoste;
}
public function setBaseImponibleACoste(?float $baseImponibleACoste): self
{
$this->BaseImponibleACoste = $baseImponibleACoste;
return $this;
}
public function getCuotaRepercutida(): ?float
{
return $this->CuotaRepercutida;
}
public function setCuotaRepercutida(?float $cuotaRepercutida): self
{
$this->CuotaRepercutida = $cuotaRepercutida;
return $this;
}
public function getTipoRecargoEquivalencia(): ?float
{
return $this->TipoRecargoEquivalencia;
}
public function setTipoRecargoEquivalencia(?float $tipoRecargoEquivalencia): self
{
if ($tipoRecargoEquivalencia !== null) {
if ($tipoRecargoEquivalencia < 0 || $tipoRecargoEquivalencia > 100) {
throw new \InvalidArgumentException('TipoRecargoEquivalencia must be between 0 and 100');
}
}
$this->TipoRecargoEquivalencia = $tipoRecargoEquivalencia;
return $this;
}
public function getCuotaRecargoEquivalencia(): ?float
{
return $this->CuotaRecargoEquivalencia;
}
public function setCuotaRecargoEquivalencia(?float $cuotaRecargoEquivalencia): self
{
$this->CuotaRecargoEquivalencia = $cuotaRecargoEquivalencia;
return $this;
}
}

View File

@ -5,29 +5,29 @@ namespace App\Services\EDocument\Standards\Verifactu\Types;
class IDFactura class IDFactura
{ {
/** @var string */ /** @var string */
protected $idEmisorFactura; protected $IDEmisorFactura;
/** @var string */ /** @var string */
protected $numSerieFactura; protected $NumSerieFactura;
/** @var string */ /** @var string */
protected $fechaExpedicionFactura; protected $FechaExpedicionFactura;
public function getIdEmisorFactura(): string public function getIDEmisorFactura(): string
{ {
return $this->idEmisorFactura; return $this->IDEmisorFactura;
} }
public function setIdEmisorFactura(string $idEmisorFactura): self public function setIDEmisorFactura(string $idEmisorFactura): self
{ {
// TODO: Add NIF validation // TODO: Add NIF validation
$this->idEmisorFactura = $idEmisorFactura; $this->IDEmisorFactura = $idEmisorFactura;
return $this; return $this;
} }
public function getNumSerieFactura(): string public function getNumSerieFactura(): string
{ {
return $this->numSerieFactura; return $this->NumSerieFactura;
} }
public function setNumSerieFactura(string $numSerieFactura): self public function setNumSerieFactura(string $numSerieFactura): self
@ -35,13 +35,13 @@ class IDFactura
if (strlen($numSerieFactura) > 60) { if (strlen($numSerieFactura) > 60) {
throw new \InvalidArgumentException('NumSerieFactura must not exceed 60 characters'); throw new \InvalidArgumentException('NumSerieFactura must not exceed 60 characters');
} }
$this->numSerieFactura = $numSerieFactura; $this->NumSerieFactura = $numSerieFactura;
return $this; return $this;
} }
public function getFechaExpedicionFactura(): string public function getFechaExpedicionFactura(): string
{ {
return $this->fechaExpedicionFactura; return $this->FechaExpedicionFactura;
} }
public function setFechaExpedicionFactura(string $fechaExpedicionFactura): self public function setFechaExpedicionFactura(string $fechaExpedicionFactura): self
@ -57,7 +57,7 @@ class IDFactura
throw new \InvalidArgumentException('Invalid date'); throw new \InvalidArgumentException('Invalid date');
} }
$this->fechaExpedicionFactura = $fechaExpedicionFactura; $this->FechaExpedicionFactura = $fechaExpedicionFactura;
return $this; return $this;
} }
} }

View File

@ -4,17 +4,20 @@ namespace App\Services\EDocument\Standards\Verifactu\Types;
class IDFacturaAR class IDFacturaAR
{ {
/** @var string NIF format */ /** @var string */
protected $idEmisorFactura; protected $idEmisorFactura;
/** @var string */ /** @var string */
protected $numSerieFactura; protected $numSerieFactura;
/** @var string Date format YYYY-MM-DD */ /** @var string */
protected $fechaExpedicionFactura; protected $fechaExpedicionFactura;
/** @var string|null */ /** @var string|null */
protected $numRegistroAcuerdoFacturacion; protected $numSerieFacturaOrigen;
/** @var string|null */
protected $fechaExpedicionFacturaOrigen;
public function getIdEmisorFactura(): string public function getIdEmisorFactura(): string
{ {
@ -35,6 +38,9 @@ class IDFacturaAR
public function setNumSerieFactura(string $numSerieFactura): self public function setNumSerieFactura(string $numSerieFactura): self
{ {
if (strlen($numSerieFactura) > 60) {
throw new \InvalidArgumentException('NumSerieFactura must not exceed 60 characters');
}
$this->numSerieFactura = $numSerieFactura; $this->numSerieFactura = $numSerieFactura;
return $this; return $this;
} }
@ -46,21 +52,56 @@ class IDFacturaAR
public function setFechaExpedicionFactura(string $fechaExpedicionFactura): self public function setFechaExpedicionFactura(string $fechaExpedicionFactura): self
{ {
if (!\DateTime::createFromFormat('Y-m-d', $fechaExpedicionFactura)) { // Validate date format DD-MM-YYYY
throw new \InvalidArgumentException('FechaExpedicionFactura must be in YYYY-MM-DD format'); if (!preg_match('/^\d{2}-\d{2}-\d{4}$/', $fechaExpedicionFactura)) {
throw new \InvalidArgumentException('FechaExpedicionFactura must be in DD-MM-YYYY format');
} }
// Validate date components
list($day, $month, $year) = explode('-', $fechaExpedicionFactura);
if (!checkdate((int)$month, (int)$day, (int)$year)) {
throw new \InvalidArgumentException('Invalid date');
}
$this->fechaExpedicionFactura = $fechaExpedicionFactura; $this->fechaExpedicionFactura = $fechaExpedicionFactura;
return $this; return $this;
} }
public function getNumRegistroAcuerdoFacturacion(): ?string public function getNumSerieFacturaOrigen(): ?string
{ {
return $this->numRegistroAcuerdoFacturacion; return $this->numSerieFacturaOrigen;
} }
public function setNumRegistroAcuerdoFacturacion(?string $numRegistroAcuerdoFacturacion): self public function setNumSerieFacturaOrigen(?string $numSerieFacturaOrigen): self
{ {
$this->numRegistroAcuerdoFacturacion = $numRegistroAcuerdoFacturacion; if ($numSerieFacturaOrigen !== null && strlen($numSerieFacturaOrigen) > 60) {
throw new \InvalidArgumentException('NumSerieFacturaOrigen must not exceed 60 characters');
}
$this->numSerieFacturaOrigen = $numSerieFacturaOrigen;
return $this;
}
public function getFechaExpedicionFacturaOrigen(): ?string
{
return $this->fechaExpedicionFacturaOrigen;
}
public function setFechaExpedicionFacturaOrigen(?string $fechaExpedicionFacturaOrigen): self
{
if ($fechaExpedicionFacturaOrigen !== null) {
// Validate date format DD-MM-YYYY
if (!preg_match('/^\d{2}-\d{2}-\d{4}$/', $fechaExpedicionFacturaOrigen)) {
throw new \InvalidArgumentException('FechaExpedicionFacturaOrigen must be in DD-MM-YYYY format');
}
// Validate date components
list($day, $month, $year) = explode('-', $fechaExpedicionFacturaOrigen);
if (!checkdate((int)$month, (int)$day, (int)$year)) {
throw new \InvalidArgumentException('Invalid date');
}
}
$this->fechaExpedicionFacturaOrigen = $fechaExpedicionFacturaOrigen;
return $this; return $this;
} }
} }

View File

@ -4,61 +4,57 @@ namespace App\Services\EDocument\Standards\Verifactu\Types;
class IDOtro class IDOtro
{ {
/** @var string|null ISO 3166-1 alpha-2 */ /** @var string */
protected $codigoPais; protected $CodigoPais;
/** @var string */ /** @var string */
protected $idType; protected $IDType;
/** @var string Max length 20 characters */ /** @var string */
protected $id; protected $ID;
public function getCodigoPais(): ?string public function getCodigoPais(): string
{ {
return $this->codigoPais; return $this->CodigoPais;
} }
public function setCodigoPais(?string $codigoPais): self public function setCodigoPais(string $codigoPais): self
{ {
if ($codigoPais !== null) {
if (strlen($codigoPais) !== 2) { if (strlen($codigoPais) !== 2) {
throw new \InvalidArgumentException('CodigoPais must be a 2-letter ISO country code'); throw new \InvalidArgumentException('CodigoPais must be a 2-character ISO country code');
} }
// Prevent using ES with IDType 01 $this->CodigoPais = $codigoPais;
if ($codigoPais === 'ES' && $this->idType === '01') {
throw new \InvalidArgumentException('Cannot use CodigoPais=ES with IDType=01, use NIF instead');
}
}
$this->codigoPais = $codigoPais;
return $this; return $this;
} }
public function getIdType(): string public function getIDType(): string
{ {
return $this->idType; return $this->IDType;
} }
public function setIdType(string $idType): self public function setIDType(string $idType): self
{ {
// Prevent using ES with IDType 01 if (!in_array($idType, ['02', '03', '04', '05', '06', '07'])) {
if ($this->codigoPais === 'ES' && $idType === '01') { throw new \InvalidArgumentException('Invalid IDType value');
throw new \InvalidArgumentException('Cannot use CodigoPais=ES with IDType=01, use NIF instead');
} }
$this->idType = $idType; if ($this->CodigoPais === 'ES' && $idType === '01') {
throw new \InvalidArgumentException('IDType 01 cannot be used with CodigoPais ES');
}
$this->IDType = $idType;
return $this; return $this;
} }
public function getId(): string public function getID(): string
{ {
return $this->id; return $this->ID;
} }
public function setId(string $id): self public function setID(string $id): self
{ {
if (strlen($id) > 20) { if (strlen($id) > 20) {
throw new \InvalidArgumentException('ID must not exceed 20 characters'); throw new \InvalidArgumentException('ID must not exceed 20 characters');
} }
$this->id = $id; $this->ID = $id;
return $this; return $this;
} }
} }

View File

@ -4,7 +4,10 @@ namespace App\Services\EDocument\Standards\Verifactu\Types;
class Incidencia class Incidencia
{ {
/** @var string Max length 2000 characters */ /** @var string */
protected $codigo;
/** @var string */
protected $descripcion; protected $descripcion;
/** @var string|null Max length 120 characters */ /** @var string|null Max length 120 characters */
@ -16,6 +19,20 @@ class Incidencia
/** @var string|null */ /** @var string|null */
protected $fechaHora; protected $fechaHora;
public function getCodigo(): string
{
return $this->codigo;
}
public function setCodigo(string $codigo): self
{
if (!preg_match('/^\d{3}$/', $codigo)) {
throw new \InvalidArgumentException('Codigo must be a 3-digit number');
}
$this->codigo = $codigo;
return $this;
}
public function getDescripcion(): string public function getDescripcion(): string
{ {
return $this->descripcion; return $this->descripcion;
@ -23,8 +40,8 @@ class Incidencia
public function setDescripcion(string $descripcion): self public function setDescripcion(string $descripcion): self
{ {
if (strlen($descripcion) > 2000) { if (strlen($descripcion) > 500) {
throw new \InvalidArgumentException('Descripcion must not exceed 2000 characters'); throw new \InvalidArgumentException('Descripcion must not exceed 500 characters');
} }
$this->descripcion = $descripcion; $this->descripcion = $descripcion;
return $this; return $this;

View File

@ -5,72 +5,72 @@ namespace App\Services\EDocument\Standards\Verifactu\Types;
class RegistroAlta class RegistroAlta
{ {
/** @var string */ /** @var string */
protected $idVersion; protected $IDVersion;
/** @var IDFactura */ /** @var IDFactura */
protected $idFactura; protected $IDFactura;
/** @var string */ /** @var string */
protected $nombreRazonEmisor; protected $NombreRazonEmisor;
/** @var string */ /** @var string */
protected $tipoFactura; protected $TipoFactura;
/** @var string */ /** @var string */
protected $descripcionOperacion; protected $DescripcionOperacion;
/** @var array<IDDestinatario> */ /** @var Destinatarios */
protected $destinatarios = []; protected $Destinatarios;
/** @var array<DetalleDesglose> */ /** @var Desglose */
protected $desglose = []; protected $Desglose;
/** @var float */ /** @var float */
protected $cuotaTotal; protected $CuotaTotal;
/** @var float */ /** @var float */
protected $importeTotal; protected $ImporteTotal;
/** @var RegistroAnterior|null */ /** @var Encadenamiento|null */
protected $encadenamiento; protected $Encadenamiento;
/** @var SistemaInformatico */ /** @var SistemaInformatico */
protected $sistemaInformatico; protected $SistemaInformatico;
/** @var string */ /** @var string */
protected $fechaHoraHusoGenRegistro; protected $FechaHoraHusoGenRegistro;
/** @var string */ /** @var string */
protected $tipoHuella; protected $TipoHuella;
/** @var string */ /** @var string */
protected $huella; protected $Huella;
public function getIdVersion(): string public function getIDVersion(): string
{ {
return $this->idVersion; return $this->IDVersion;
} }
public function setIdVersion(string $idVersion): self public function setIDVersion(string $idVersion): self
{ {
$this->idVersion = $idVersion; $this->IDVersion = $idVersion;
return $this; return $this;
} }
public function getIdFactura(): IDFactura public function getIDFactura(): IDFactura
{ {
return $this->idFactura; return $this->IDFactura;
} }
public function setIdFactura(IDFactura $idFactura): self public function setIDFactura(IDFactura $idFactura): self
{ {
$this->idFactura = $idFactura; $this->IDFactura = $idFactura;
return $this; return $this;
} }
public function getNombreRazonEmisor(): string public function getNombreRazonEmisor(): string
{ {
return $this->nombreRazonEmisor; return $this->NombreRazonEmisor;
} }
public function setNombreRazonEmisor(string $nombreRazonEmisor): self public function setNombreRazonEmisor(string $nombreRazonEmisor): self
@ -78,27 +78,27 @@ class RegistroAlta
if (strlen($nombreRazonEmisor) > 120) { if (strlen($nombreRazonEmisor) > 120) {
throw new \InvalidArgumentException('NombreRazonEmisor must not exceed 120 characters'); throw new \InvalidArgumentException('NombreRazonEmisor must not exceed 120 characters');
} }
$this->nombreRazonEmisor = $nombreRazonEmisor; $this->NombreRazonEmisor = $nombreRazonEmisor;
return $this; return $this;
} }
public function getTipoFactura(): string public function getTipoFactura(): string
{ {
return $this->tipoFactura; return $this->TipoFactura;
} }
public function setTipoFactura(string $tipoFactura): self public function setTipoFactura(string $tipoFactura): self
{ {
if (!in_array($tipoFactura, ['F1', 'F2', 'F3', 'F4', 'R1', 'R2', 'R3', 'R4'])) { if (!preg_match('/^F[1-4]$/', $tipoFactura)) {
throw new \InvalidArgumentException('Invalid TipoFactura value'); throw new \InvalidArgumentException('TipoFactura must be F1, F2, F3, or F4');
} }
$this->tipoFactura = $tipoFactura; $this->TipoFactura = $tipoFactura;
return $this; return $this;
} }
public function getDescripcionOperacion(): string public function getDescripcionOperacion(): string
{ {
return $this->descripcionOperacion; return $this->DescripcionOperacion;
} }
public function setDescripcionOperacion(string $descripcionOperacion): self public function setDescripcionOperacion(string $descripcionOperacion): self
@ -106,122 +106,113 @@ class RegistroAlta
if (strlen($descripcionOperacion) > 500) { if (strlen($descripcionOperacion) > 500) {
throw new \InvalidArgumentException('DescripcionOperacion must not exceed 500 characters'); throw new \InvalidArgumentException('DescripcionOperacion must not exceed 500 characters');
} }
$this->descripcionOperacion = $descripcionOperacion; $this->DescripcionOperacion = $descripcionOperacion;
return $this; return $this;
} }
/** public function getDestinatarios(): Destinatarios
* @return array<IDDestinatario>
*/
public function getDestinatarios(): array
{ {
return $this->destinatarios; return $this->Destinatarios;
} }
public function addDestinatario(IDDestinatario $destinatario): self public function setDestinatarios(Destinatarios $destinatarios): self
{ {
$this->destinatarios[] = $destinatario; $this->Destinatarios = $destinatarios;
return $this; return $this;
} }
/** public function getDesglose(): Desglose
* @return array<DetalleDesglose>
*/
public function getDesglose(): array
{ {
return $this->desglose; return $this->Desglose;
} }
public function addDesglose(DetalleDesglose $detalle): self public function setDesglose(Desglose $desglose): self
{ {
$this->desglose[] = $detalle; $this->Desglose = $desglose;
return $this; return $this;
} }
public function getCuotaTotal(): float public function getCuotaTotal(): float
{ {
return $this->cuotaTotal; return $this->CuotaTotal;
} }
public function setCuotaTotal(float $cuotaTotal): self public function setCuotaTotal(float $cuotaTotal): self
{ {
$this->cuotaTotal = $cuotaTotal; $this->CuotaTotal = $cuotaTotal;
return $this; return $this;
} }
public function getImporteTotal(): float public function getImporteTotal(): float
{ {
return $this->importeTotal; return $this->ImporteTotal;
} }
public function setImporteTotal(float $importeTotal): self public function setImporteTotal(float $importeTotal): self
{ {
$this->importeTotal = $importeTotal; $this->ImporteTotal = $importeTotal;
return $this; return $this;
} }
public function getEncadenamiento(): ?RegistroAnterior public function getEncadenamiento(): ?Encadenamiento
{ {
return $this->encadenamiento; return $this->Encadenamiento;
} }
public function setEncadenamiento(?RegistroAnterior $encadenamiento): self public function setEncadenamiento(?Encadenamiento $encadenamiento): self
{ {
$this->encadenamiento = $encadenamiento; $this->Encadenamiento = $encadenamiento;
return $this; return $this;
} }
public function getSistemaInformatico(): SistemaInformatico public function getSistemaInformatico(): SistemaInformatico
{ {
return $this->sistemaInformatico; return $this->SistemaInformatico;
} }
public function setSistemaInformatico(SistemaInformatico $sistemaInformatico): self public function setSistemaInformatico(SistemaInformatico $sistemaInformatico): self
{ {
$this->sistemaInformatico = $sistemaInformatico; $this->SistemaInformatico = $sistemaInformatico;
return $this; return $this;
} }
public function getFechaHoraHusoGenRegistro(): string public function getFechaHoraHusoGenRegistro(): string
{ {
return $this->fechaHoraHusoGenRegistro; return $this->FechaHoraHusoGenRegistro;
} }
public function setFechaHoraHusoGenRegistro(string $fechaHoraHusoGenRegistro): self public function setFechaHoraHusoGenRegistro(string $fechaHoraHusoGenRegistro): self
{ {
// Validate ISO 8601 format with timezone // Validate ISO 8601 date format with timezone
if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/', $fechaHoraHusoGenRegistro)) { if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/', $fechaHoraHusoGenRegistro)) {
throw new \InvalidArgumentException('FechaHoraHusoGenRegistro must be in ISO 8601 format with timezone (e.g. 2024-09-13T19:20:30+01:00)'); throw new \InvalidArgumentException('FechaHoraHusoGenRegistro must be in ISO 8601 format (YYYY-MM-DDThh:mm:ss±hh:mm)');
} }
$this->fechaHoraHusoGenRegistro = $fechaHoraHusoGenRegistro; $this->FechaHoraHusoGenRegistro = $fechaHoraHusoGenRegistro;
return $this; return $this;
} }
public function getTipoHuella(): string public function getTipoHuella(): string
{ {
return $this->tipoHuella; return $this->TipoHuella;
} }
public function setTipoHuella(string $tipoHuella): self public function setTipoHuella(string $tipoHuella): self
{ {
if (!in_array($tipoHuella, ['01', '02', '03', '04'])) { if (!preg_match('/^\d{2}$/', $tipoHuella)) {
throw new \InvalidArgumentException('Invalid TipoHuella value'); throw new \InvalidArgumentException('TipoHuella must be a 2-digit number');
} }
$this->tipoHuella = $tipoHuella; $this->TipoHuella = $tipoHuella;
return $this; return $this;
} }
public function getHuella(): string public function getHuella(): string
{ {
return $this->huella; return $this->Huella;
} }
public function setHuella(string $huella): self public function setHuella(string $huella): self
{ {
if (strlen($huella) > 100) { $this->Huella = $huella;
throw new \InvalidArgumentException('Huella must not exceed 100 characters');
}
$this->huella = $huella;
return $this; return $this;
} }
} }

View File

@ -0,0 +1,20 @@
<?php
namespace App\Services\EDocument\Standards\Verifactu\Types;
class RegistroAnterior extends IDFactura
{
/** @var string */
protected $Huella;
public function getHuella(): string
{
return $this->Huella;
}
public function setHuella(string $huella): self
{
$this->Huella = $huella;
return $this;
}
}

View File

@ -7,7 +7,7 @@ class RegistroFacturacionAnulacion
/** @var string */ /** @var string */
protected $idVersion; protected $idVersion;
/** @var IDFacturaExpedida */ /** @var IDFacturaAR */
protected $idFactura; protected $idFactura;
/** @var string|null Max length 70 characters */ /** @var string|null Max length 70 characters */
@ -22,7 +22,13 @@ class RegistroFacturacionAnulacion
/** @var SistemaInformatico */ /** @var SistemaInformatico */
protected $sistemaInformatico; protected $sistemaInformatico;
/** @var \DateTime */ /** @var string */
protected $huella;
/** @var string|null */
protected $signature;
/** @var string */
protected $fechaHoraHusoGenRegistro; protected $fechaHoraHusoGenRegistro;
/** @var string|null Max length 15 characters */ /** @var string|null Max length 15 characters */
@ -34,12 +40,6 @@ class RegistroFacturacionAnulacion
/** @var string */ /** @var string */
protected $tipoHuella; protected $tipoHuella;
/** @var string Max length 64 characters */
protected $huella;
/** @var string|null */
protected $signature;
public function getIdVersion(): string public function getIdVersion(): string
{ {
return $this->idVersion; return $this->idVersion;
@ -51,12 +51,12 @@ class RegistroFacturacionAnulacion
return $this; return $this;
} }
public function getIdFactura(): IDFacturaExpedida public function getIdFactura(): IDFacturaAR
{ {
return $this->idFactura; return $this->idFactura;
} }
public function setIdFactura(IDFacturaExpedida $idFactura): self public function setIdFactura(IDFacturaAR $idFactura): self
{ {
$this->idFactura = $idFactura; $this->idFactura = $idFactura;
return $this; return $this;
@ -115,13 +115,42 @@ class RegistroFacturacionAnulacion
return $this; return $this;
} }
public function getFechaHoraHusoGenRegistro(): \DateTime public function getHuella(): string
{
return $this->huella;
}
public function setHuella(string $huella): self
{
if (strlen($huella) > 100) {
throw new \InvalidArgumentException('Huella must not exceed 100 characters');
}
$this->huella = $huella;
return $this;
}
public function getSignature(): ?string
{
return $this->signature;
}
public function setSignature(?string $signature): self
{
$this->signature = $signature;
return $this;
}
public function getFechaHoraHusoGenRegistro(): string
{ {
return $this->fechaHoraHusoGenRegistro; return $this->fechaHoraHusoGenRegistro;
} }
public function setFechaHoraHusoGenRegistro(\DateTime $fechaHoraHusoGenRegistro): self public function setFechaHoraHusoGenRegistro(string $fechaHoraHusoGenRegistro): self
{ {
// Validate ISO 8601 format with timezone
if (!preg_match('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/', $fechaHoraHusoGenRegistro)) {
throw new \InvalidArgumentException('FechaHoraHusoGenRegistro must be in ISO 8601 format with timezone (e.g. 2024-09-13T19:20:30+01:00)');
}
$this->fechaHoraHusoGenRegistro = $fechaHoraHusoGenRegistro; $this->fechaHoraHusoGenRegistro = $fechaHoraHusoGenRegistro;
return $this; return $this;
} }
@ -164,29 +193,4 @@ class RegistroFacturacionAnulacion
$this->tipoHuella = $tipoHuella; $this->tipoHuella = $tipoHuella;
return $this; return $this;
} }
public function getHuella(): string
{
return $this->huella;
}
public function setHuella(string $huella): self
{
if (strlen($huella) > 64) {
throw new \InvalidArgumentException('Huella must not exceed 64 characters');
}
$this->huella = $huella;
return $this;
}
public function getSignature(): ?string
{
return $this->signature;
}
public function setSignature(?string $signature): self
{
$this->signature = $signature;
return $this;
}
} }

View File

@ -2,170 +2,124 @@
namespace App\Services\EDocument\Standards\Verifactu\Types; namespace App\Services\EDocument\Standards\Verifactu\Types;
class SistemaInformatico class SistemaInformatico extends PersonaFisicaJuridicaES
{ {
/** @var string Max length 120 characters */ /** @var string */
protected $nombreRazon; protected $NombreSistemaInformatico;
/** @var string|null NIF format */ /** @var string */
protected $nif; protected $IdSistemaInformatico;
/** @var array|null */ /** @var string */
protected $idOtro; protected $Version;
/** @var string Max length 30 characters */ /** @var string */
protected $nombreSistemaInformatico; protected $NumeroInstalacion;
/** @var string Max length 2 characters */ /** @var string */
protected $idSistemaInformatico; protected $TipoUsoPosibleSoloVerifactu;
/** @var string Max length 50 characters */ /** @var string */
protected $version; protected $TipoUsoPosibleMultiOT;
/** @var string Max length 100 characters */ /** @var string */
protected $numeroInstalacion; protected $IndicadorMultiplesOT;
/** @var string 'S' or 'N' */
protected $tipoUsoPosibleSoloVerifactu;
/** @var string 'S' or 'N' */
protected $tipoUsoPosibleMultiOT;
/** @var string 'S' or 'N' */
protected $indicadorMultiplesOT;
public function getNombreRazon(): string
{
return $this->nombreRazon;
}
public function setNombreRazon(string $nombreRazon): self
{
if (strlen($nombreRazon) > 120) {
throw new \InvalidArgumentException('NombreRazon must not exceed 120 characters');
}
$this->nombreRazon = $nombreRazon;
return $this;
}
public function getNif(): ?string
{
return $this->nif;
}
public function setNif(?string $nif): self
{
// TODO: Add NIF validation
$this->nif = $nif;
return $this;
}
public function getIdOtro(): ?array
{
return $this->idOtro;
}
public function setIdOtro(?array $idOtro): self
{
$this->idOtro = $idOtro;
return $this;
}
public function getNombreSistemaInformatico(): string public function getNombreSistemaInformatico(): string
{ {
return $this->nombreSistemaInformatico; return $this->NombreSistemaInformatico;
} }
public function setNombreSistemaInformatico(string $nombreSistemaInformatico): self public function setNombreSistemaInformatico(string $nombreSistemaInformatico): self
{ {
if (strlen($nombreSistemaInformatico) > 30) { if (strlen($nombreSistemaInformatico) > 120) {
throw new \InvalidArgumentException('NombreSistemaInformatico must not exceed 30 characters'); throw new \InvalidArgumentException('NombreSistemaInformatico must not exceed 120 characters');
} }
$this->nombreSistemaInformatico = $nombreSistemaInformatico; $this->NombreSistemaInformatico = $nombreSistemaInformatico;
return $this; return $this;
} }
public function getIdSistemaInformatico(): string public function getIdSistemaInformatico(): string
{ {
return $this->idSistemaInformatico; return $this->IdSistemaInformatico;
} }
public function setIdSistemaInformatico(string $idSistemaInformatico): self public function setIdSistemaInformatico(string $idSistemaInformatico): self
{ {
if (strlen($idSistemaInformatico) > 2) { if (strlen($idSistemaInformatico) > 20) {
throw new \InvalidArgumentException('IdSistemaInformatico must not exceed 2 characters'); throw new \InvalidArgumentException('IdSistemaInformatico must not exceed 20 characters');
} }
$this->idSistemaInformatico = $idSistemaInformatico; $this->IdSistemaInformatico = $idSistemaInformatico;
return $this; return $this;
} }
public function getVersion(): string public function getVersion(): string
{ {
return $this->version; return $this->Version;
} }
public function setVersion(string $version): self public function setVersion(string $version): self
{ {
if (strlen($version) > 50) { if (strlen($version) > 20) {
throw new \InvalidArgumentException('Version must not exceed 50 characters'); throw new \InvalidArgumentException('Version must not exceed 20 characters');
} }
$this->version = $version; $this->Version = $version;
return $this; return $this;
} }
public function getNumeroInstalacion(): string public function getNumeroInstalacion(): string
{ {
return $this->numeroInstalacion; return $this->NumeroInstalacion;
} }
public function setNumeroInstalacion(string $numeroInstalacion): self public function setNumeroInstalacion(string $numeroInstalacion): self
{ {
if (strlen($numeroInstalacion) > 100) { if (strlen($numeroInstalacion) > 20) {
throw new \InvalidArgumentException('NumeroInstalacion must not exceed 100 characters'); throw new \InvalidArgumentException('NumeroInstalacion must not exceed 20 characters');
} }
$this->numeroInstalacion = $numeroInstalacion; $this->NumeroInstalacion = $numeroInstalacion;
return $this; return $this;
} }
public function getTipoUsoPosibleSoloVerifactu(): string public function getTipoUsoPosibleSoloVerifactu(): string
{ {
return $this->tipoUsoPosibleSoloVerifactu; return $this->TipoUsoPosibleSoloVerifactu;
} }
public function setTipoUsoPosibleSoloVerifactu(string $value): self public function setTipoUsoPosibleSoloVerifactu(string $tipoUsoPosibleSoloVerifactu): self
{ {
if (!in_array($value, ['S', 'N'])) { if (!in_array($tipoUsoPosibleSoloVerifactu, ['S', 'N'])) {
throw new \InvalidArgumentException('TipoUsoPosibleSoloVerifactu must be either "S" or "N"'); throw new \InvalidArgumentException('TipoUsoPosibleSoloVerifactu must be either "S" or "N"');
} }
$this->tipoUsoPosibleSoloVerifactu = $value; $this->TipoUsoPosibleSoloVerifactu = $tipoUsoPosibleSoloVerifactu;
return $this; return $this;
} }
public function getTipoUsoPosibleMultiOT(): string public function getTipoUsoPosibleMultiOT(): string
{ {
return $this->tipoUsoPosibleMultiOT; return $this->TipoUsoPosibleMultiOT;
} }
public function setTipoUsoPosibleMultiOT(string $value): self public function setTipoUsoPosibleMultiOT(string $tipoUsoPosibleMultiOT): self
{ {
if (!in_array($value, ['S', 'N'])) { if (!in_array($tipoUsoPosibleMultiOT, ['S', 'N'])) {
throw new \InvalidArgumentException('TipoUsoPosibleMultiOT must be either "S" or "N"'); throw new \InvalidArgumentException('TipoUsoPosibleMultiOT must be either "S" or "N"');
} }
$this->tipoUsoPosibleMultiOT = $value; $this->TipoUsoPosibleMultiOT = $tipoUsoPosibleMultiOT;
return $this; return $this;
} }
public function getIndicadorMultiplesOT(): string public function getIndicadorMultiplesOT(): string
{ {
return $this->indicadorMultiplesOT; return $this->IndicadorMultiplesOT;
} }
public function setIndicadorMultiplesOT(string $value): self public function setIndicadorMultiplesOT(string $indicadorMultiplesOT): self
{ {
if (!in_array($value, ['S', 'N'])) { if (!in_array($indicadorMultiplesOT, ['S', 'N'])) {
throw new \InvalidArgumentException('IndicadorMultiplesOT must be either "S" or "N"'); throw new \InvalidArgumentException('IndicadorMultiplesOT must be either "S" or "N"');
} }
$this->indicadorMultiplesOT = $value; $this->IndicadorMultiplesOT = $indicadorMultiplesOT;
return $this; return $this;
} }
} }