Ensure tax codes that are sent are correct
This commit is contained in:
parent
084f0fea25
commit
70dea557f5
|
|
@ -158,12 +158,16 @@ class EntityLevel implements EntityLevelInterface
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($field == 'vat_number' && $client->classification == 'individual') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$errors[] = ['field' => $field, 'label' => ctrans("texts.{$field}")];
|
$errors[] = ['field' => $field, 'label' => ctrans("texts.{$field}")];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//If not an individual, you MUST have a VAT number if you are in the EU
|
//If not an individual, you MUST have a VAT number if you are in the EU
|
||||||
if (!$this->validString($client->vat_number)) {
|
if ($client->classification != 'individual' && !$this->validString($client->vat_number)) {
|
||||||
$errors[] = ['field' => 'vat_number', 'label' => ctrans("texts.vat_number")];
|
$errors[] = ['field' => 'vat_number', 'label' => ctrans("texts.vat_number")];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,17 @@ class Desglose extends BaseXmlModel
|
||||||
{
|
{
|
||||||
$root = $this->createElement($doc, 'Desglose');
|
$root = $this->createElement($doc, 'Desglose');
|
||||||
|
|
||||||
// If we have a DetalleDesglose object, use it
|
// If we have DetalleDesglose objects in the desgloseIVA array, use them
|
||||||
|
if ($this->desgloseIVA !== null && is_array($this->desgloseIVA) && count($this->desgloseIVA) > 0) {
|
||||||
|
foreach ($this->desgloseIVA as $detalleDesglose) {
|
||||||
|
if ($detalleDesglose instanceof DetalleDesglose) {
|
||||||
|
$root->appendChild($detalleDesglose->toXml($doc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $root;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a single DetalleDesglose object, use it
|
||||||
if ($this->detalleDesglose !== null) {
|
if ($this->detalleDesglose !== null) {
|
||||||
$root->appendChild($this->detalleDesglose->toXml($doc));
|
$root->appendChild($this->detalleDesglose->toXml($doc));
|
||||||
return $root;
|
return $root;
|
||||||
|
|
@ -36,7 +46,7 @@ class Desglose extends BaseXmlModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ClaveRegimen if present
|
// Add ClaveRegimen if present
|
||||||
if (isset($this->desgloseFactura['ClaveRegimen'])) {
|
if (isset($this->desgloseFactura['ClaveRegimen']) ) {
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'ClaveRegimen', $this->desgloseFactura['ClaveRegimen']));
|
$detalleDesglose->appendChild($this->createElement($doc, 'ClaveRegimen', $this->desgloseFactura['ClaveRegimen']));
|
||||||
} else {
|
} else {
|
||||||
// Default ClaveRegimen
|
// Default ClaveRegimen
|
||||||
|
|
@ -48,29 +58,28 @@ class Desglose extends BaseXmlModel
|
||||||
$this->desgloseFactura['CalificacionOperacion'] ?? 'S1'));
|
$this->desgloseFactura['CalificacionOperacion'] ?? 'S1'));
|
||||||
|
|
||||||
// Add TipoImpositivo if present
|
// Add TipoImpositivo if present
|
||||||
if (isset($this->desgloseFactura['TipoImpositivo'])) {
|
if (isset($this->desgloseFactura['TipoImpositivo']) && $this->desgloseFactura['CalificacionOperacion'] == 'S1') {
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'TipoImpositivo',
|
$detalleDesglose->appendChild($this->createElement($doc, 'TipoImpositivo',
|
||||||
number_format((float)$this->desgloseFactura['TipoImpositivo'], 2, '.', '')));
|
number_format((float)$this->desgloseFactura['TipoImpositivo'], 2, '.', '')));
|
||||||
} else {
|
}
|
||||||
// Default TipoImpositivo
|
// else {
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'TipoImpositivo', '21.00'));
|
// // Default TipoImpositivo
|
||||||
}
|
// $detalleDesglose->appendChild($this->createElement($doc, 'TipoImpositivo', '0'));
|
||||||
|
// }
|
||||||
|
|
||||||
// Convert BaseImponible to BaseImponibleOimporteNoSujeto if needed
|
// Convert BaseImponible to BaseImponibleOimporteNoSujeto if needed
|
||||||
$baseImponible = isset($this->desgloseFactura['BaseImponible'])
|
$baseImponible = isset($this->desgloseFactura['BaseImponible'])
|
||||||
? $this->desgloseFactura['BaseImponible']
|
? $this->desgloseFactura['BaseImponible']
|
||||||
: ($this->desgloseFactura['BaseImponibleOimporteNoSujeto'] ?? '100.00');
|
: ($this->desgloseFactura['BaseImponibleOimporteNoSujeto'] ?? '0');
|
||||||
|
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto',
|
$detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto',
|
||||||
number_format((float)$baseImponible, 2, '.', '')));
|
number_format((float)$baseImponible, 2, '.', '')));
|
||||||
|
|
||||||
// Convert Cuota to CuotaRepercutida if needed
|
|
||||||
$cuota = isset($this->desgloseFactura['Cuota'])
|
|
||||||
? $this->desgloseFactura['Cuota']
|
|
||||||
: ($this->desgloseFactura['CuotaRepercutida'] ?? '21.00');
|
|
||||||
|
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida',
|
if(isset($this->desgloseFactura['Cuota']) && $this->desgloseFactura['CalificacionOperacion'] == 'S1'){
|
||||||
number_format((float)$cuota, 2, '.', '')));
|
$detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida',
|
||||||
|
number_format((float)$this->desgloseFactura['Cuota'], 2, '.', '')));
|
||||||
|
}
|
||||||
|
|
||||||
// Add TipoRecargoEquivalencia if present
|
// Add TipoRecargoEquivalencia if present
|
||||||
if (isset($this->desgloseFactura['TipoRecargoEquivalencia'])) {
|
if (isset($this->desgloseFactura['TipoRecargoEquivalencia'])) {
|
||||||
|
|
@ -110,7 +119,7 @@ class Desglose extends BaseXmlModel
|
||||||
// Convert BaseImponible to BaseImponibleOimporteNoSujeto if needed
|
// Convert BaseImponible to BaseImponibleOimporteNoSujeto if needed
|
||||||
$baseImponible = isset($desglose['BaseImponible'])
|
$baseImponible = isset($desglose['BaseImponible'])
|
||||||
? $desglose['BaseImponible']
|
? $desglose['BaseImponible']
|
||||||
: ($desglose['BaseImponibleOimporteNoSujeto'] ?? '100.00');
|
: ($desglose['BaseImponibleOimporteNoSujeto'] ?? '0');
|
||||||
|
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto',
|
$detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto',
|
||||||
number_format((float)$baseImponible, 2, '.', '')));
|
number_format((float)$baseImponible, 2, '.', '')));
|
||||||
|
|
@ -118,7 +127,7 @@ class Desglose extends BaseXmlModel
|
||||||
// Convert Cuota to CuotaRepercutida if needed
|
// Convert Cuota to CuotaRepercutida if needed
|
||||||
$cuota = isset($desglose['Cuota'])
|
$cuota = isset($desglose['Cuota'])
|
||||||
? $desglose['Cuota']
|
? $desglose['Cuota']
|
||||||
: ($desglose['CuotaRepercutida'] ?? '21.00');
|
: ($desglose['CuotaRepercutida'] ?? '0');
|
||||||
|
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida',
|
$detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida',
|
||||||
number_format((float)$cuota, 2, '.', '')));
|
number_format((float)$cuota, 2, '.', '')));
|
||||||
|
|
@ -147,7 +156,7 @@ class Desglose extends BaseXmlModel
|
||||||
// Convert BaseImponible to BaseImponibleOimporteNoSujeto if needed
|
// Convert BaseImponible to BaseImponibleOimporteNoSujeto if needed
|
||||||
$baseImponible = isset($this->desgloseIVA['BaseImponible'])
|
$baseImponible = isset($this->desgloseIVA['BaseImponible'])
|
||||||
? $this->desgloseIVA['BaseImponible']
|
? $this->desgloseIVA['BaseImponible']
|
||||||
: ($this->desgloseIVA['BaseImponibleOimporteNoSujeto'] ?? '100.00');
|
: ($this->desgloseIVA['BaseImponibleOimporteNoSujeto'] ?? '');
|
||||||
|
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto',
|
$detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto',
|
||||||
number_format((float)$baseImponible, 2, '.', '')));
|
number_format((float)$baseImponible, 2, '.', '')));
|
||||||
|
|
@ -155,7 +164,7 @@ class Desglose extends BaseXmlModel
|
||||||
// Convert Cuota to CuotaRepercutida if needed
|
// Convert Cuota to CuotaRepercutida if needed
|
||||||
$cuota = isset($this->desgloseIVA['Cuota'])
|
$cuota = isset($this->desgloseIVA['Cuota'])
|
||||||
? $this->desgloseIVA['Cuota']
|
? $this->desgloseIVA['Cuota']
|
||||||
: ($this->desgloseIVA['CuotaRepercutida'] ?? '21.00');
|
: ($this->desgloseIVA['CuotaRepercutida'] ?? '0');
|
||||||
|
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida',
|
$detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida',
|
||||||
number_format((float)$cuota, 2, '.', '')));
|
number_format((float)$cuota, 2, '.', '')));
|
||||||
|
|
@ -164,16 +173,16 @@ class Desglose extends BaseXmlModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we still don't have any data, create a default DetalleDesglose
|
// // If we still don't have any data, create a default DetalleDesglose
|
||||||
if (!$detalleDesglose->hasChildNodes()) {
|
// if (!$detalleDesglose->hasChildNodes()) {
|
||||||
// Create a default DetalleDesglose with basic IVA information
|
// // Create a default DetalleDesglose with basic IVA information
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'Impuesto', '01'));
|
// $detalleDesglose->appendChild($this->createElement($doc, 'Impuesto', '01'));
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'ClaveRegimen', '01'));
|
// $detalleDesglose->appendChild($this->createElement($doc, 'ClaveRegimen', '01'));
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'CalificacionOperacion', 'S1'));
|
// $detalleDesglose->appendChild($this->createElement($doc, 'CalificacionOperacion', 'S1'));
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'TipoImpositivo', '21.00'));
|
// $detalleDesglose->appendChild($this->createElement($doc, 'TipoImpositivo', '0'));
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto', '100.00'));
|
// $detalleDesglose->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto', '0'));
|
||||||
$detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida', '21.00'));
|
// $detalleDesglose->appendChild($this->createElement($doc, 'CuotaRepercutida', '0'));
|
||||||
}
|
// }
|
||||||
|
|
||||||
$root->appendChild($detalleDesglose);
|
$root->appendChild($detalleDesglose);
|
||||||
return $root;
|
return $root;
|
||||||
|
|
@ -291,6 +300,12 @@ class Desglose extends BaseXmlModel
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addDesgloseIVA(DetalleDesglose $desgloseIVA): self
|
||||||
|
{
|
||||||
|
$this->desgloseIVA[] = $desgloseIVA;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function getDesgloseIGIC(): ?array
|
public function getDesgloseIGIC(): ?array
|
||||||
{
|
{
|
||||||
return $this->desgloseIGIC;
|
return $this->desgloseIGIC;
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,21 @@ class DetalleDesglose extends BaseXmlModel
|
||||||
|
|
||||||
// Add IVA details directly under DetalleDesglose
|
// Add IVA details directly under DetalleDesglose
|
||||||
$root->appendChild($this->createElement($doc, 'Impuesto', $this->desgloseIVA['Impuesto']));
|
$root->appendChild($this->createElement($doc, 'Impuesto', $this->desgloseIVA['Impuesto']));
|
||||||
$root->appendChild($this->createElement($doc, 'ClaveRegimen', $this->desgloseIVA['ClaveRegimen']));
|
|
||||||
$root->appendChild($this->createElement($doc, 'CalificacionOperacion', $this->desgloseIVA['CalificacionOperacion'] ?? 'S1'));
|
if(isset($this->desgloseIVA['ClaveRegimen']) && in_array($this->desgloseIVA['ClaveRegimen'], ['01','03'])){
|
||||||
$root->appendChild($this->createElement($doc, 'TipoImpositivo', (string)$this->desgloseIVA['TipoImpositivo']));
|
$root->appendChild($this->createElement($doc, 'ClaveRegimen', $this->desgloseIVA['ClaveRegimen']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$root->appendChild($this->createElement($doc, 'CalificacionOperacion', $this->desgloseIVA['CalificacionOperacion']));
|
||||||
|
|
||||||
|
if(isset($this->desgloseIVA['TipoImpositivo']) && $this->desgloseIVA['CalificacionOperacion'] == 'S1') {
|
||||||
|
$root->appendChild($this->createElement($doc, 'TipoImpositivo', (string)$this->desgloseIVA['TipoImpositivo']));
|
||||||
|
}
|
||||||
$root->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto', (string)$this->desgloseIVA['BaseImponible']));
|
$root->appendChild($this->createElement($doc, 'BaseImponibleOimporteNoSujeto', (string)$this->desgloseIVA['BaseImponible']));
|
||||||
$root->appendChild($this->createElement($doc, 'CuotaRepercutida', (string)$this->desgloseIVA['Cuota']));
|
|
||||||
|
if(isset($this->desgloseIVA['Cuota']) && $this->desgloseIVA['CalificacionOperacion'] == 'S1') {
|
||||||
|
$root->appendChild($this->createElement($doc, 'CuotaRepercutida', (string)$this->desgloseIVA['Cuota']));
|
||||||
|
}
|
||||||
|
|
||||||
return $root;
|
return $root;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ class IDOtro extends BaseXmlModel
|
||||||
* @param string $id Identifier value, e.g., passport number, tax ID, or placeholder
|
* @param string $id Identifier value, e.g., passport number, tax ID, or placeholder
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(private string $codigoPais = 'ES', private string $idType = '07', private string $id = 'NO_DISPONIBLE')
|
public function __construct(private string $codigoPais = 'ES', private string $idType = '06', private string $id = 'NO_DISPONIBLE')
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ use App\Services\EDocument\Standards\Verifactu\Models\IDOtro;
|
||||||
use App\Services\EDocument\Standards\Verifactu\Models\Desglose;
|
use App\Services\EDocument\Standards\Verifactu\Models\Desglose;
|
||||||
use App\Services\EDocument\Standards\Verifactu\Models\IDFactura;
|
use App\Services\EDocument\Standards\Verifactu\Models\IDFactura;
|
||||||
use App\Services\EDocument\Standards\Verifactu\Models\Encadenamiento;
|
use App\Services\EDocument\Standards\Verifactu\Models\Encadenamiento;
|
||||||
|
use App\Services\EDocument\Standards\Verifactu\Models\DetalleDesglose;
|
||||||
use App\Services\EDocument\Standards\Verifactu\Models\RegistroAnterior;
|
use App\Services\EDocument\Standards\Verifactu\Models\RegistroAnterior;
|
||||||
use App\Services\EDocument\Standards\Verifactu\Models\SistemaInformatico;
|
use App\Services\EDocument\Standards\Verifactu\Models\SistemaInformatico;
|
||||||
use App\Services\EDocument\Standards\Verifactu\Models\PersonaFisicaJuridica;
|
use App\Services\EDocument\Standards\Verifactu\Models\PersonaFisicaJuridica;
|
||||||
|
|
@ -58,7 +59,9 @@ class RegistroAlta
|
||||||
'01' => 'IVA (Impuesto sobre el Valor Añadido)', // Value Added Tax - Standard Spanish VAT
|
'01' => 'IVA (Impuesto sobre el Valor Añadido)', // Value Added Tax - Standard Spanish VAT
|
||||||
'02' => 'IPSI (Impuesto sobre la Producción, los Servicios y la Importación)', // Production, Services and Import Tax - Ceuta and Melilla
|
'02' => 'IPSI (Impuesto sobre la Producción, los Servicios y la Importación)', // Production, Services and Import Tax - Ceuta and Melilla
|
||||||
'03' => 'IGIC (Impuesto General Indirecto Canario)', // Canary Islands General Indirect Tax
|
'03' => 'IGIC (Impuesto General Indirecto Canario)', // Canary Islands General Indirect Tax
|
||||||
'05' => 'Otros (Others)' // Other taxes
|
'05' => 'Otros (Others)', // Other taxes
|
||||||
|
'06' => 'IAE', //local taxes - rarely used
|
||||||
|
'07' => 'Non-Vat / Exempt operations'
|
||||||
];
|
];
|
||||||
|
|
||||||
private array $clave_regimen_codes = [
|
private array $clave_regimen_codes = [
|
||||||
|
|
@ -141,9 +144,10 @@ class RegistroAlta
|
||||||
->setNombreRazon($this->invoice->client->present()->name());
|
->setNombreRazon($this->invoice->client->present()->name());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$locationData = $this->invoice->location();
|
$locationData = $this->invoice->service()->location();
|
||||||
|
|
||||||
$destinatario = new IDOtro();
|
$destinatario = new IDOtro();
|
||||||
|
$destinatario->setNombreRazon($this->invoice->client->present()->name());
|
||||||
$destinatario->setCodigoPais($locationData['country_code']);
|
$destinatario->setCodigoPais($locationData['country_code']);
|
||||||
|
|
||||||
$br = new \App\DataMapper\Tax\BaseRule();
|
$br = new \App\DataMapper\Tax\BaseRule();
|
||||||
|
|
@ -168,18 +172,60 @@ class RegistroAlta
|
||||||
|
|
||||||
foreach ($taxes as $tax) {
|
foreach ($taxes as $tax) {
|
||||||
|
|
||||||
$desglose_iva[] = [
|
$desglose_iva = [
|
||||||
'Impuesto' => $this->calculateTaxType($tax['name']), //tax type
|
'Impuesto' => $this->calculateTaxType($tax['name']), //tax type
|
||||||
'ClaveRegimen' => '01', //tax regime classification code
|
'ClaveRegimen' => $this->calculateRegimeClassification($tax['name']), //tax regime classification code
|
||||||
'CalificacionOperacion' => 'S1', //operation classification code
|
'CalificacionOperacion' => $this->calculateOperationClassification($tax['name']), //operation classification code
|
||||||
'BaseImponibleOimporteNoSujeto' => $tax['base_amount'] ?? $this->calc->getNetSubtotal(), // taxable base amount
|
'BaseImponible' => $tax['base_amount'] ?? $this->calc->getNetSubtotal(), // taxable base amount - fixed: key matches DetalleDesglose::toXml()
|
||||||
'TipoImpositivo' => $tax['tax_rate'], // Tax Rate
|
'TipoImpositivo' => $tax['tax_rate'], // Tax Rate
|
||||||
'CuotaRepercutida' => $tax['total'] // Tax Amount
|
'Cuota' => $tax['total'] // Tax Amount - fixed: key matches DetalleDesglose::toXml()
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$detalle_desglose = new DetalleDesglose();
|
||||||
|
$detalle_desglose->setDesgloseIVA($desglose_iva);
|
||||||
|
$desglose->addDesgloseIVA($detalle_desglose);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$desglose->setDesgloseIVA($desglose_iva);
|
if(count($taxes) == 0) {
|
||||||
|
nlog("tax count = 0");
|
||||||
|
$client_country_code = $this->invoice->client->country->iso_3166_2;
|
||||||
|
|
||||||
|
$impuesto = 'S2';
|
||||||
|
$clave_regimen = '08';
|
||||||
|
$calificacion = 'S1';
|
||||||
|
|
||||||
|
$br = new \App\DataMapper\Tax\BaseRule();
|
||||||
|
|
||||||
|
if (in_array($client_country_code, $br->eu_country_codes) && $this->invoice->client->classification != 'individual') {
|
||||||
|
$impuesto = '05';
|
||||||
|
$clave_regimen = '05';
|
||||||
|
$calificacion = 'N2';
|
||||||
|
}
|
||||||
|
elseif (in_array($client_country_code, $br->eu_country_codes) && $this->invoice->client->classification == 'individual') {
|
||||||
|
$impuesto = '08';
|
||||||
|
$clave_regimen = '05';
|
||||||
|
$calificacion = 'N2';
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$impuesto = '08';
|
||||||
|
$clave_regimen = '01';
|
||||||
|
$calificacion = 'N2';
|
||||||
|
}
|
||||||
|
|
||||||
|
$desglose_iva = [
|
||||||
|
'Impuesto' => $impuesto, //tax type
|
||||||
|
'ClaveRegimen' => $clave_regimen, //tax regime classification code
|
||||||
|
'CalificacionOperacion' => $calificacion, //operation classification code
|
||||||
|
'BaseImponible' => $this->calc->getNetSubtotal(), // taxable base amount - fixed: key matches DetalleDesglose::toXml()
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
$detalle_desglose = new DetalleDesglose();
|
||||||
|
$detalle_desglose->setDesgloseIVA($desglose_iva);
|
||||||
|
$desglose->addDesgloseIVA($detalle_desglose);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
$this->v_invoice->setDesglose($desglose);
|
$this->v_invoice->setDesglose($desglose);
|
||||||
|
|
||||||
|
|
@ -261,25 +307,85 @@ class RegistroAlta
|
||||||
return $this->v_invoice;
|
return $this->v_invoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function calculateTaxType(string $tax_name): string
|
private function calculateRegimeClassification(string $tax_name): string
|
||||||
{
|
{
|
||||||
if(stripos($tax_name, 'iva') !== false) {
|
$client_country_code = $this->invoice->client->country->iso_3166_2;
|
||||||
|
|
||||||
|
if($client_country_code == 'ES') {
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'iva') !== false) {
|
||||||
|
return '01';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'igic') !== false) {
|
||||||
|
return '03';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'ipsi') !== false) {
|
||||||
|
return '02';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'otros') !== false) {
|
||||||
|
return '05';
|
||||||
|
}
|
||||||
|
|
||||||
return '01';
|
return '01';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(stripos($tax_name, 'igic') !== false) {
|
$br = new \App\DataMapper\Tax\BaseRule();
|
||||||
return '03';
|
if (in_array($client_country_code, $br->eu_country_codes) && $this->invoice->client->classification != 'individual') {
|
||||||
}
|
return '08';
|
||||||
|
} elseif (in_array($client_country_code, $br->eu_country_codes) && $this->invoice->client->classification == 'individual') {
|
||||||
if(stripos($tax_name, 'ipsi') !== false) {
|
|
||||||
return '02';
|
|
||||||
}
|
|
||||||
|
|
||||||
if(stripos($tax_name, 'otros') !== false) {
|
|
||||||
return '05';
|
return '05';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '01';
|
return '07';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateTaxType(string $tax_name): string
|
||||||
|
{
|
||||||
|
$client_country_code = $this->invoice->client->country->iso_3166_2;
|
||||||
|
|
||||||
|
if($client_country_code == 'ES') {
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'iva') !== false) {
|
||||||
|
return '01';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'igic') !== false) {
|
||||||
|
return '03';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'ipsi') !== false) {
|
||||||
|
return '02';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(stripos($tax_name, 'otros') !== false) {
|
||||||
|
return '05';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '01';
|
||||||
|
}
|
||||||
|
|
||||||
|
$br = new \App\DataMapper\Tax\BaseRule();
|
||||||
|
if (in_array($client_country_code, $br->eu_country_codes) && $this->invoice->client->classification != 'individual') {
|
||||||
|
return '08';
|
||||||
|
}
|
||||||
|
elseif (in_array($client_country_code, $br->eu_country_codes) && $this->invoice->client->classification == 'individual') {
|
||||||
|
return '05';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '07';
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateOperationClassification(string $tax_name): string
|
||||||
|
{
|
||||||
|
if($this->invoice->client->country_id == 724 || stripos($tax_name, 'iva') !== false) {
|
||||||
|
return 'S1';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'N2';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +127,7 @@ class SendToAeat implements ShouldQueue
|
||||||
$verifactu = new Verifactu($invoice);
|
$verifactu = new Verifactu($invoice);
|
||||||
|
|
||||||
$document = (new RegistroAlta($invoice))->run()->getInvoice();
|
$document = (new RegistroAlta($invoice))->run()->getInvoice();
|
||||||
|
$document->setNumSerieFactura($invoice->backup->parent_invoice_number);
|
||||||
$last_hash = $invoice->company->verifactu_logs()->first();
|
$last_hash = $invoice->company->verifactu_logs()->first();
|
||||||
|
|
||||||
$huella = $this->cancellationHash($document, $last_hash->hash);
|
$huella = $this->cancellationHash($document, $last_hash->hash);
|
||||||
|
|
|
||||||
|
|
@ -714,6 +714,7 @@ class InvoiceService
|
||||||
if($new_model && $this->invoice->amount >= 0) {
|
if($new_model && $this->invoice->amount >= 0) {
|
||||||
$this->invoice->backup->document_type = 'F1';
|
$this->invoice->backup->document_type = 'F1';
|
||||||
$this->invoice->backup->adjustable_amount = $this->invoice->amount;
|
$this->invoice->backup->adjustable_amount = $this->invoice->amount;
|
||||||
|
$this->invoice->backup->parent_invoice_number = $this->invoice->number;
|
||||||
$this->invoice->saveQuietly();
|
$this->invoice->saveQuietly();
|
||||||
}
|
}
|
||||||
elseif(isset($invoice_array['modified_invoice_id'])) {
|
elseif(isset($invoice_array['modified_invoice_id'])) {
|
||||||
|
|
@ -726,6 +727,7 @@ class InvoiceService
|
||||||
//Update the client balance by the delta amount from the previous invoice to this one.
|
//Update the client balance by the delta amount from the previous invoice to this one.
|
||||||
$this->invoice->backup->parent_invoice_id = $modified_invoice->hashed_id;
|
$this->invoice->backup->parent_invoice_id = $modified_invoice->hashed_id;
|
||||||
$this->invoice->backup->document_type = 'R2';
|
$this->invoice->backup->document_type = 'R2';
|
||||||
|
$this->invoice->backup->parent_invoice_number = $modified_invoice->number;
|
||||||
$this->invoice->saveQuietly();
|
$this->invoice->saveQuietly();
|
||||||
|
|
||||||
$this->invoice->client->service()->updateBalance(round(($this->invoice->amount - $modified_invoice->amount), 2));
|
$this->invoice->client->service()->updateBalance(round(($this->invoice->amount - $modified_invoice->amount), 2));
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@
|
||||||
"friendsofphp/php-cs-fixer": "^3.14",
|
"friendsofphp/php-cs-fixer": "^3.14",
|
||||||
"laracasts/cypress": "^3.0",
|
"laracasts/cypress": "^3.0",
|
||||||
"larastan/larastan": "^2",
|
"larastan/larastan": "^2",
|
||||||
|
"laravel/boost": "^1.0",
|
||||||
"mockery/mockery": "^1.4.4",
|
"mockery/mockery": "^1.4.4",
|
||||||
"nunomaduro/collision": "^8.1",
|
"nunomaduro/collision": "^8.1",
|
||||||
"phpstan/phpstan": "^1.9",
|
"phpstan/phpstan": "^1.9",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "df5805c56ea07b9fe22be83885c67387",
|
"content-hash": "a6ef0e9ae03d968020a5c8a976835ad9",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "adrienrn/php-mimetyper",
|
"name": "adrienrn/php-mimetyper",
|
||||||
|
|
@ -18381,6 +18381,196 @@
|
||||||
],
|
],
|
||||||
"time": "2025-06-10T22:06:33+00:00"
|
"time": "2025-06-10T22:06:33+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel/boost",
|
||||||
|
"version": "v1.0.9",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/laravel/boost.git",
|
||||||
|
"reference": "ad025a2f2325ccdc5f52e926dab4e0c1d2c6def9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/laravel/boost/zipball/ad025a2f2325ccdc5f52e926dab4e0c1d2c6def9",
|
||||||
|
"reference": "ad025a2f2325ccdc5f52e926dab4e0c1d2c6def9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/guzzle": "^7.9",
|
||||||
|
"illuminate/console": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/contracts": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/routing": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/support": "^10.0|^11.0|^12.0",
|
||||||
|
"laravel/mcp": "^0.1.0",
|
||||||
|
"laravel/prompts": "^0.1.9|^0.3",
|
||||||
|
"laravel/roster": "^0.2",
|
||||||
|
"php": "^8.1|^8.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel/pint": "^1.14|^1.23",
|
||||||
|
"mockery/mockery": "^1.6",
|
||||||
|
"orchestra/testbench": "^8.22.0|^9.0|^10.0",
|
||||||
|
"pestphp/pest": "^2.0|^3.0",
|
||||||
|
"phpstan/phpstan": "^2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Laravel\\Boost\\BoostServiceProvider"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Laravel\\Boost\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Laravel Boost accelerates AI-assisted development to generate high-quality, Laravel-specific code.",
|
||||||
|
"homepage": "https://github.com/laravel/boost",
|
||||||
|
"keywords": [
|
||||||
|
"ai",
|
||||||
|
"dev",
|
||||||
|
"laravel"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/laravel/boost/issues",
|
||||||
|
"source": "https://github.com/laravel/boost"
|
||||||
|
},
|
||||||
|
"time": "2025-08-13T19:51:44+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel/mcp",
|
||||||
|
"version": "v0.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/laravel/mcp.git",
|
||||||
|
"reference": "417890c0d8032af9a46a86d16651bbe13946cddf"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/laravel/mcp/zipball/417890c0d8032af9a46a86d16651bbe13946cddf",
|
||||||
|
"reference": "417890c0d8032af9a46a86d16651bbe13946cddf",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/console": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/contracts": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/http": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/routing": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/support": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/validation": "^10.0|^11.0|^12.0",
|
||||||
|
"php": "^8.1|^8.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel/pint": "^1.14",
|
||||||
|
"orchestra/testbench": "^8.22.0|^9.0|^10.0",
|
||||||
|
"phpstan/phpstan": "^2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"Mcp": "Laravel\\Mcp\\Server\\Facades\\Mcp"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"Laravel\\Mcp\\Server\\McpServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Laravel\\Mcp\\": "src/",
|
||||||
|
"Workbench\\App\\": "workbench/app/",
|
||||||
|
"Laravel\\Mcp\\Tests\\": "tests/",
|
||||||
|
"Laravel\\Mcp\\Server\\": "src/Server/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "The easiest way to add MCP servers to your Laravel app.",
|
||||||
|
"homepage": "https://github.com/laravel/mcp",
|
||||||
|
"keywords": [
|
||||||
|
"dev",
|
||||||
|
"laravel",
|
||||||
|
"mcp"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/laravel/mcp/issues",
|
||||||
|
"source": "https://github.com/laravel/mcp"
|
||||||
|
},
|
||||||
|
"time": "2025-08-12T07:09:39+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel/roster",
|
||||||
|
"version": "v0.2.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/laravel/roster.git",
|
||||||
|
"reference": "caeed7609b02c00c3f1efec52812d8d87c5d4096"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/laravel/roster/zipball/caeed7609b02c00c3f1efec52812d8d87c5d4096",
|
||||||
|
"reference": "caeed7609b02c00c3f1efec52812d8d87c5d4096",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/console": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/contracts": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/routing": "^10.0|^11.0|^12.0",
|
||||||
|
"illuminate/support": "^10.0|^11.0|^12.0",
|
||||||
|
"php": "^8.1|^8.2",
|
||||||
|
"symfony/yaml": "^6.4|^7.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel/pint": "^1.14",
|
||||||
|
"mockery/mockery": "^1.6",
|
||||||
|
"orchestra/testbench": "^8.22.0|^9.0|^10.0",
|
||||||
|
"pestphp/pest": "^2.0|^3.0",
|
||||||
|
"phpstan/phpstan": "^2.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Laravel\\Roster\\RosterServiceProvider"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "1.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Laravel\\Roster\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Detect packages & approaches in use within a Laravel project",
|
||||||
|
"homepage": "https://github.com/laravel/roster",
|
||||||
|
"keywords": [
|
||||||
|
"dev",
|
||||||
|
"laravel"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/laravel/roster/issues",
|
||||||
|
"source": "https://github.com/laravel/roster"
|
||||||
|
},
|
||||||
|
"time": "2025-08-13T15:00:25+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "mockery/mockery",
|
"name": "mockery/mockery",
|
||||||
"version": "1.6.12",
|
"version": "1.6.12",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue