diff --git a/Lib/Modelo303.php b/Lib/Modelo303.php index 9983f21..394a23e 100644 --- a/Lib/Modelo303.php +++ b/Lib/Modelo303.php @@ -21,6 +21,7 @@ use FacturaScripts\Core\Base\DataBase; use FacturaScripts\Core\Tools; +use FacturaScripts\Dinamic\Lib\InvoiceOperation; use FacturaScripts\Dinamic\Model\Ejercicio; use FacturaScripts\Dinamic\Model\Join\PartidaImpuestoResumen; @@ -61,8 +62,6 @@ class Modelo303 // Adquisiciones intracomunitarias 'IVARUE' => ['21' => ['base' => '10', 'cuota' => '11']], - // Operaciones con inversión del sujeto pasivo - // TODO: 'xxxxx' => ['21' => ['base' => '12', 'cuota' => '13']], // Recargo de equivalencia 'IVARRE' => [ @@ -164,6 +163,7 @@ public function loadFromResumen(array $resumen): void foreach ($resumen as $item) { $this->addMovimiento( $item->codcuentaesp ?? '', + $item->operacion ?? '', (float) $item->iva, (float) $item->recargo, (float) $item->baseimponible, @@ -192,20 +192,23 @@ public static function treasury(string $codejercicio, string $period): array ]; } - /** - * Add a tax movement to the model (base + quota by type and rate) - * - Determine the correct square based on the type and tax rate. - * - Update the base and quota squares accordingly. - * - * @param string $tipo - * @param float $iva - * @param float $recargo - * @param float $base - * @param float $cuota - * @return void - */ - private function addMovimiento(string $tipo, float $iva, float $recargo, float $base, float $cuota): void + private function addMovimiento(string $tipo, string $operacion, float $iva, float $recargo, float $base, float $cuota): void { + // ISP: inversión del sujeto pasivo (no-UE, servicios intracomunitarios B2B, doméstico art. 84) + // Devengado → casillas 12-13 / deducible → casillas 28-29 + if (in_array($operacion, [InvoiceOperation::REVERSE_CHARGE, InvoiceOperation::INTRA_COMMUNITY_SERVICES])) { + if (in_array($tipo, ['IVAREP', 'IVARUE'])) { + $this->square['12'] += $base; + $this->square['13'] += $cuota; + return; + } + if (in_array($tipo, ['IVASOP', 'IVASUE'])) { + $this->square['28'] += $base; + $this->square['29'] += $cuota; + return; + } + } + if (false === isset($this->casillaMap[$tipo])) { return; } diff --git a/Model/Join/PartidaImpuestoResumen.php b/Model/Join/PartidaImpuestoResumen.php index d63c850..f62d46a 100644 --- a/Model/Join/PartidaImpuestoResumen.php +++ b/Model/Join/PartidaImpuestoResumen.php @@ -44,6 +44,7 @@ protected function getFields(): array 'codcuentaesp' => 'COALESCE(subcuentas.codcuentaesp, cuentas.codcuentaesp)', 'tipo_desc' => 'cuentasesp.descripcion', + 'operacion' => 'COALESCE(facturasprov.operacion, facturascli.operacion)', 'baseimponible' => $this->sqlForRoundedSum('partidas.baseimponible'), 'debe' => $this->sqlForRoundedSum('partidas.debe'), @@ -65,7 +66,8 @@ protected function getGroupFields(): string . ', partidas.recargo' . ', subcuentas.descripcion' . ', COALESCE(subcuentas.codcuentaesp, cuentas.codcuentaesp)' - . ', cuentasesp.descripcion'; + . ', cuentasesp.descripcion' + . ', COALESCE(facturasprov.operacion, facturascli.operacion)'; } /** @@ -80,7 +82,9 @@ protected function getSQLFrom(): string . ' INNER JOIN subcuentas on subcuentas.idsubcuenta = partidas.idsubcuenta' . ' INNER JOIN cuentas on cuentas.idcuenta = subcuentas.idcuenta' . ' LEFT JOIN cuentasesp on cuentasesp.codcuentaesp = coalesce(subcuentas.codcuentaesp, cuentas.codcuentaesp)' - . ' LEFT JOIN series on series.codserie = partidas.codserie'; + . ' LEFT JOIN series on series.codserie = partidas.codserie' + . ' LEFT JOIN (SELECT codigo, operacion FROM facturasprov) facturasprov on facturasprov.codigo = asientos.documento' + . ' LEFT JOIN (SELECT codigo, operacion FROM facturascli) facturascli on facturascli.codigo = asientos.documento'; } /** @@ -97,6 +101,8 @@ protected function getTables(): array 'cuentas', 'cuentasesp', 'series', + 'facturasprov', + 'facturascli', ]; }