Skip to content

Commit 3ff78fb

Browse files
feat: esportazione xml per la liquidazione iva
1 parent f910af0 commit 3ff78fb

4 files changed

Lines changed: 295 additions & 2 deletions

File tree

modules/stampe_contabili/actions.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,5 +104,37 @@
104104

105105
echo json_encode(['first_page' => $first_page - 1]);
106106

107+
break;
108+
109+
case 'download-xml-lipe':
110+
$date_start = get('date_start');
111+
$date_end = get('date_end');
112+
113+
if (empty($date_start) || empty($date_end)) {
114+
echo json_encode(['error' => 'Date non specificate']);
115+
exit();
116+
}
117+
118+
try {
119+
// Genera il contenuto XML
120+
$xml_content = generaXmlLipe($date_start, $date_end);
121+
122+
// Nome del file
123+
$filename = 'LIPE_'.date('Ymd', strtotime($date_start)).'_'.date('Ymd', strtotime($date_end)).'.xml';
124+
125+
// Imposta gli header per il download
126+
header('Content-Type: application/xml; charset=utf-8');
127+
header('Content-Disposition: attachment; filename="'.$filename.'"');
128+
header('Content-Length: '.strlen($xml_content));
129+
header('Cache-Control: no-cache, must-revalidate');
130+
header('Pragma: no-cache');
131+
132+
echo $xml_content;
133+
exit();
134+
} catch (Exception $e) {
135+
echo json_encode(['error' => $e->getMessage()]);
136+
exit();
137+
}
138+
107139
break;
108140
}

modules/stampe_contabili/modutil.php

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Carbon\Carbon;
2222
use Models\Locale;
2323
use Models\Module;
24+
use Modules\Anagrafiche\Anagrafica;
2425
use Modules\PrimaNota\Mastrino;
2526
use Modules\PrimaNota\Movimento;
2627

@@ -773,3 +774,218 @@ function creaMovimentoLiquidazioneIva($date_start, $date_end)
773774
return null;
774775
}
775776
}
777+
778+
/**
779+
* Genera il file XML per la LIPE (Liquidazione IVA Periodica).
780+
*
781+
* @param string $date_start Data inizio periodo
782+
* @param string $date_end Data fine periodo
783+
*
784+
* @return string Contenuto del file XML
785+
*/
786+
function generaXmlLipe($date_start, $date_end)
787+
{
788+
// Recupera i dati dell'anagrafica azienda
789+
$azienda = Anagrafica::find(setting('Azienda predefinita'));
790+
791+
if (empty($azienda)) {
792+
throw new Exception('Anagrafica azienda non configurata');
793+
}
794+
795+
// Determina i mesi da includere
796+
$data_start = new Carbon($date_start);
797+
$data_end = new Carbon($date_end);
798+
$anno = $data_start->format('Y');
799+
800+
// Calcola i mesi del periodo
801+
$mesi = [];
802+
$current = clone $data_start;
803+
while ($current <= $data_end) {
804+
$mesi[] = (int) $current->format('m');
805+
$current->addMonth();
806+
}
807+
808+
// Recupera dati intermediario (da impostazioni o fallback ai dati azienda)
809+
$cf_dichiarante = setting('Codice fiscale dichiarante') ?: $azienda->codice_fiscale;
810+
$cf_intermediario = setting('Codice fiscale intermediario');
811+
$identificativo_software = setting('Identificativo software');
812+
$piva = $azienda->piva ?: '';
813+
814+
// Crea il documento DOM
815+
$dom = new \DOMDocument('1.0', 'UTF-8');
816+
$dom->preserveWhiteSpace = false;
817+
$dom->formatOutput = true;
818+
819+
// Crea elemento radice Fornitura con namespace
820+
$fornitura = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:Fornitura');
821+
$fornitura->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:ds', 'http://www.w3.org/2000/09/xmldsig#');
822+
$dom->appendChild($fornitura);
823+
824+
// Crea Intestazione
825+
$intestazione = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:Intestazione');
826+
$fornitura->appendChild($intestazione);
827+
828+
// CodiceFornitura
829+
$codiceFornitura = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:CodiceFornitura');
830+
$codiceFornitura->appendChild($dom->createTextNode('IVP18'));
831+
$intestazione->appendChild($codiceFornitura);
832+
833+
// CodiceFiscaleDichiarante
834+
$codiceFiscaleDichiarante = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:CodiceFiscaleDichiarante');
835+
$codiceFiscaleDichiarante->appendChild($dom->createTextNode($cf_dichiarante ?: ''));
836+
$intestazione->appendChild($codiceFiscaleDichiarante);
837+
838+
// CodiceCarica
839+
$codiceCarica = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:CodiceCarica');
840+
$codiceCarica->appendChild($dom->createTextNode('1'));
841+
$intestazione->appendChild($codiceCarica);
842+
843+
// Crea Comunicazione
844+
$comunicazione = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:Comunicazione');
845+
$comunicazione->setAttribute('identificativo', '00001');
846+
$fornitura->appendChild($comunicazione);
847+
848+
// Crea Frontespizio
849+
$frontespizio = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:Frontespizio');
850+
$comunicazione->appendChild($frontespizio);
851+
852+
// CodiceFiscale (Partita IVA)
853+
$codiceFiscale = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:CodiceFiscale');
854+
$codiceFiscale->appendChild($dom->createTextNode($piva ?: ''));
855+
$frontespizio->appendChild($codiceFiscale);
856+
857+
// AnnoImposta
858+
$annoImposta = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:AnnoImposta');
859+
$annoImposta->appendChild($dom->createTextNode($anno));
860+
$frontespizio->appendChild($annoImposta);
861+
862+
// PartitaIVA
863+
$partitaIVA = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:PartitaIVA');
864+
$partitaIVA->appendChild($dom->createTextNode($piva ?: ''));
865+
$frontespizio->appendChild($partitaIVA);
866+
867+
// CFDichiarante
868+
$cfDichiarante = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:CFDichiarante');
869+
$cfDichiarante->appendChild($dom->createTextNode($cf_dichiarante ?: ''));
870+
$frontespizio->appendChild($cfDichiarante);
871+
872+
// CodiceCaricaDichiarante
873+
$codiceCaricaDichiarante = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:CodiceCaricaDichiarante');
874+
$codiceCaricaDichiarante->appendChild($dom->createTextNode('1'));
875+
$frontespizio->appendChild($codiceCaricaDichiarante);
876+
877+
// FirmaDichiarazione
878+
$firmaDichiarazione = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:FirmaDichiarazione');
879+
$firmaDichiarazione->appendChild($dom->createTextNode('1'));
880+
$frontespizio->appendChild($firmaDichiarazione);
881+
882+
// CFIntermediario
883+
if ($cf_intermediario) {
884+
$cfIntermediario = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:CFIntermediario');
885+
$cfIntermediario->appendChild($dom->createTextNode($cf_intermediario ?: ''));
886+
$frontespizio->appendChild($cfIntermediario);
887+
888+
// ImpegnoPresentazione
889+
$impegnoPresentazione = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:ImpegnoPresentazione');
890+
$impegnoPresentazione->appendChild($dom->createTextNode('1'));
891+
$frontespizio->appendChild($impegnoPresentazione);
892+
893+
// DataImpegno
894+
$dataImpegno = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:DataImpegno');
895+
$dataImpegno->appendChild($dom->createTextNode(date('dmY')));
896+
$frontespizio->appendChild($dataImpegno);
897+
898+
// FirmaIntermediario
899+
$firmaIntermediario = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:FirmaIntermediario');
900+
$firmaIntermediario->appendChild($dom->createTextNode('1'));
901+
$frontespizio->appendChild($firmaIntermediario);
902+
}
903+
904+
// IdentificativoProdSoftware
905+
if ($identificativo_software) {
906+
$identificativoProdSoftware = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:IdentificativoProdSoftware');
907+
$identificativoProdSoftware->appendChild($dom->createTextNode($identificativo_software ?: ''));
908+
$frontespizio->appendChild($identificativoProdSoftware);
909+
}
910+
911+
// Crea DatiContabili
912+
$datiContabili = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:DatiContabili');
913+
$comunicazione->appendChild($datiContabili);
914+
915+
// Genera i moduli per ogni mese
916+
$numero_modulo = 1;
917+
918+
foreach ($mesi as $mese) {
919+
// Calcola date per il mese corrente
920+
$mese_start = $anno.'-'.str_pad($mese, 2, '0', STR_PAD_LEFT).'-01';
921+
$mese_end = (new Carbon($mese_start))->endOfMonth()->format('Y-m-d');
922+
923+
// Calcola importi per il mese specifico
924+
$importi_mese = calcolaImportiLiquidazioneIva($mese_start, $mese_end);
925+
926+
// Calcola totali operazioni per il mese
927+
$totale_attive_mese = 0;
928+
$totale_passive_mese = 0;
929+
930+
foreach ($importi_mese['iva_vendite'] as $iva) {
931+
$totale_attive_mese += floatval($iva['subtotale']);
932+
}
933+
934+
foreach ($importi_mese['iva_acquisti'] as $iva) {
935+
$totale_passive_mese += floatval($iva['subtotale']);
936+
}
937+
938+
$iva_esigibile_mese = floatval($importi_mese['totale_iva_esigibile']);
939+
$iva_detraibile_mese = floatval($importi_mese['totale_iva_detraibile']);
940+
$iva_dovuta_mese = $iva_esigibile_mese - $iva_detraibile_mese;
941+
$importo_da_versare_mese = max(0, $iva_dovuta_mese);
942+
943+
// Crea elemento Modulo
944+
$modulo = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:Modulo');
945+
$datiContabili->appendChild($modulo);
946+
947+
// NumeroModulo
948+
$numeroModuloEl = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:NumeroModulo');
949+
$numeroModuloEl->appendChild($dom->createTextNode((string) $numero_modulo));
950+
$modulo->appendChild($numeroModuloEl);
951+
952+
// Mese
953+
$meseEl = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:Mese');
954+
$meseEl->appendChild($dom->createTextNode((string) $mese));
955+
$modulo->appendChild($meseEl);
956+
957+
// TotaleOperazioniAttive
958+
$totaleAttive = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:TotaleOperazioniAttive');
959+
$totaleAttive->appendChild($dom->createTextNode(number_format($totale_attive_mese, 2, ',', '')));
960+
$modulo->appendChild($totaleAttive);
961+
962+
// TotaleOperazioniPassive
963+
$totalePassive = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:TotaleOperazioniPassive');
964+
$totalePassive->appendChild($dom->createTextNode(number_format($totale_passive_mese, 2, ',', '')));
965+
$modulo->appendChild($totalePassive);
966+
967+
// IvaEsigibile
968+
$ivaEsigibile = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:IvaEsigibile');
969+
$ivaEsigibile->appendChild($dom->createTextNode(number_format($iva_esigibile_mese, 2, ',', '')));
970+
$modulo->appendChild($ivaEsigibile);
971+
972+
// IvaDetratta
973+
$ivaDetratta = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:IvaDetratta');
974+
$ivaDetratta->appendChild($dom->createTextNode(number_format($iva_detraibile_mese, 2, ',', '')));
975+
$modulo->appendChild($ivaDetratta);
976+
977+
// IvaDovuta
978+
$ivaDovuta = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:IvaDovuta');
979+
$ivaDovuta->appendChild($dom->createTextNode(number_format($iva_dovuta_mese, 2, ',', '')));
980+
$modulo->appendChild($ivaDovuta);
981+
982+
// ImportoDaVersare
983+
$importoDaVersare = $dom->createElementNS('urn:www.agenziaentrate.gov.it:specificheTecniche:sco:ivp', 'iv:ImportoDaVersare');
984+
$importoDaVersare->appendChild($dom->createTextNode(number_format($importo_da_versare_mese, 2, ',', '')));
985+
$modulo->appendChild($importoDaVersare);
986+
987+
$numero_modulo++;
988+
}
989+
990+
return $dom->saveXML();
991+
}

modules/stampe_contabili/stampe_contabili.php

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,28 @@
191191
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fa fa-plus"></i></button>
192192
</div>
193193
</div>
194-
<div class="card-body">
194+
<div class="card-body">';
195+
196+
// Alert per configurazione impostazioni XML LIPE (solo per Liquidazione IVA)
197+
if ($nome_stampa === 'Liquidazione IVA') {
198+
$impostazioni_lipe = setting('Codice fiscale dichiarante') || setting('Codice fiscale intermediario') || setting('Identificativo software');
199+
if (empty($impostazioni_lipe)) {
200+
echo '
201+
<div class="alert alert-warning">
202+
<div class="row">
203+
<div class="col-md-1 text-center d-flex align-items-center justify-content-center">
204+
<i class="fa fa-info-circle fa-2x"></i>
205+
</div>
206+
<div class="col-md-11">
207+
<strong>'.tr('Configurazione XML LIPE').'</strong><br>
208+
'.tr('Per esportare correttamente il file XML per la LIPE (Liquidazione IVA Periodica) potrebbe essere necessario configurare i campi aggiuntivi in '.Modules::link('Impostazioni', null, 'Strumenti->Impostazioni->LIPE XML')).'
209+
</div>
210+
</div>
211+
</div>';
212+
}
213+
}
214+
215+
echo '
195216
<div class="table-responsive">
196217
<table class="table table-hover table-striped">';
197218

@@ -224,6 +245,15 @@
224245
</a>';
225246
}
226247

248+
// Pulsante per esportazione XML LIPE (solo per Liquidazione IVA)
249+
$xml_button = '';
250+
if ($nome_stampa === 'Liquidazione IVA') {
251+
$xml_button = '
252+
<a class="btn btn-sm btn-info" href="'.base_path_osm().'/actions.php?id_module='.$id_module.'&op=download-xml-lipe&date_start='.$elemento['date_start'].'&date_end='.$elemento['date_end'].'" target="_blank">
253+
<i class="fa fa-file-code-o"></i> '.tr('Esporta XML').'
254+
</a>';
255+
}
256+
227257
echo '
228258
<tr>
229259
<td>'.dateFormat($elemento['date_start']).' - '.dateFormat($elemento['date_end']).'</td>
@@ -233,7 +263,8 @@
233263
<a class="btn btn-sm btn-info" href="'.base_path_osm().'/actions.php?id_module='.$id_module.'&op=download-allegato&id='.$file['id'].'&filename='.$file['filename'].'" target="_blank">
234264
<i class="fa fa-download"></i> '.tr('Scarica').'
235265
</a>
236-
'.$movimento_button.'
266+
'.$xml_button.'
267+
'.$movimento_button.'
237268
</td>
238269
</tr>';
239270
}

update/2_10.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,17 @@ CREATE TABLE IF NOT EXISTS `in_tariffe_sedi` (
471471
);
472472
ALTER TABLE `in_tariffe_sedi` ADD CONSTRAINT `in_tariffe_sedi_ibfk_1` FOREIGN KEY (`idsede`) REFERENCES `an_sedi`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
473473
ALTER TABLE `in_tariffe_sedi` ADD CONSTRAINT `in_tariffe_sedi_ibfk_2` FOREIGN KEY (`idtipointervento`) REFERENCES `in_tipiintervento`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
474+
475+
-- Aggiunta impostazioni per esportazione XML LIPE
476+
INSERT INTO `zz_settings` (`id`, `nome`, `valore`, `tipo`, `editable`, `sezione`, `order`) VALUES
477+
(NULL, 'Codice fiscale dichiarante', '', 'string', '1', 'LIPE XML', NULL),
478+
(NULL, 'Codice fiscale intermediario', '', 'string', '1', 'LIPE XML', NULL),
479+
(NULL, 'Identificativo software', '', 'string', '1', 'LIPE XML', NULL);
480+
481+
INSERT INTO `zz_settings_lang` (`id_lang`, `id_record`, `title`, `help`) VALUES
482+
(1, (SELECT MAX(`id`)-2 FROM `zz_settings`), 'Codice fiscale dichiarante', 'Codice fiscale del dichiarante per la LIPE (Liquidazione IVA Periodica). Se vuoto, viene usato il codice fiscale dell''azienda predefinita.'),
483+
(1, (SELECT MAX(`id`)-1 FROM `zz_settings`), 'Codice fiscale intermediario', 'Codice fiscale dell''intermediario per la LIPE.'),
484+
(1, (SELECT MAX(`id`) FROM `zz_settings`), 'Identificativo software', 'Codice identificativo del software utilizzato per la LIPE (es. codice fiscale del produttore del software). Se vuoto, il campo viene omesso nel file XML.'),
485+
(2, (SELECT MAX(`id`)-2 FROM `zz_settings`), 'Tax ID of declarant', 'Tax ID of declarant for LIPE (Periodic VAT Settlement). If empty, the company''s default tax ID is used.'),
486+
(2, (SELECT MAX(`id`)-1 FROM `zz_settings`), 'Tax ID of intermediary', 'Tax ID of intermediary for LIPE.'),
487+
(2, (SELECT MAX(`id`) FROM `zz_settings`), 'Software identifier', 'Software identifier code for LIPE (e.g., tax ID of software producer). If empty, the field is omitted from the XML file.');

0 commit comments

Comments
 (0)