From 8e4e6951cfd54311be2b3f8b10d2c808f41d9b4c Mon Sep 17 00:00:00 2001 From: Thomas Zilio Date: Wed, 5 Aug 2020 17:58:54 +0200 Subject: [PATCH] Introduzione Totale reddito per i Movimenti --- modules/fatture/modutil.php | 12 ++ modules/fatture/src/Fattura.php | 218 +++++----------------- modules/fatture/src/Gestori/Bollo.php | 82 ++++++++ modules/fatture/src/Gestori/Movimenti.php | 209 +++++++++++++++++++++ modules/fatture/src/Gestori/Scadenze.php | 123 ++++++++++++ modules/iva/edit.php | 2 +- modules/partitario/actions.php | 2 +- modules/partitario/edit_conto.php | 11 +- modules/primanota/src/Mastrino.php | 57 +++--- modules/primanota/src/Movimento.php | 17 +- update/2_4_17.sql | 4 + 11 files changed, 538 insertions(+), 199 deletions(-) create mode 100644 modules/fatture/src/Gestori/Bollo.php create mode 100644 modules/fatture/src/Gestori/Movimenti.php create mode 100644 modules/fatture/src/Gestori/Scadenze.php diff --git a/modules/fatture/modutil.php b/modules/fatture/modutil.php index d4427abee..d75c14729 100755 --- a/modules/fatture/modutil.php +++ b/modules/fatture/modutil.php @@ -91,6 +91,8 @@ function get_ivaindetraibile_fattura($iddocumento) /** * Elimina una scadenza in base al codice documento. + * + * @deprecated 2.4.17 */ function elimina_scadenze($iddocumento) { @@ -104,6 +106,8 @@ function elimina_scadenze($iddocumento) * $iddocumento string E' l'id del documento di cui ricalcolare lo scadenzario * $pagamento string Nome del tipo di pagamento. Se è vuoto lo leggo da co_pagamenti_documenti, perché significa che devo solo aggiornare gli importi. * $pagato boolean Indica se devo segnare l'importo come pagato. + * + * @deprecated 2.4.17 */ function aggiungi_scadenza($iddocumento, $pagamento = '', $pagato = false) { @@ -118,6 +122,8 @@ function aggiungi_scadenza($iddocumento, $pagamento = '', $pagato = false) * * @param $iddocumento * @param int $prima_nota + * + * @deprecated 2.4.17 */ function elimina_movimenti($id_documento, $prima_nota = 0) { @@ -134,6 +140,8 @@ function elimina_movimenti($id_documento, $prima_nota = 0) * $iddocumento string E' l'id del documento da collegare alla prima nota * $dir string Direzione dell'importo (entrata, uscita) * $primanota boolean Indica se il movimento è un movimento di prima nota o un movimento normale (di default movimento normale). + * + * @deprecated 2.4.17 */ function aggiungi_movimento($iddocumento, $dir, $primanota = 0) { @@ -331,6 +339,8 @@ function aggiungi_movimento($iddocumento, $dir, $primanota = 0) /** * Funzione per generare un nuovo codice per il mastrino. + * + * @deprecated 2.4.17 */ function get_new_idmastrino($table = 'co_movimenti') { @@ -346,6 +356,8 @@ function get_new_idmastrino($table = 'co_movimenti') * Ricalcola i costi aggiuntivi in fattura (rivalsa inps, ritenuta d'acconto, marca da bollo) * Deve essere eseguito ogni volta che si aggiunge o toglie una riga * $iddocumento int ID della fattura. + * + * @deprecated 2.4.17 */ function ricalcola_costiagg_fattura($iddocumento) { diff --git a/modules/fatture/src/Fattura.php b/modules/fatture/src/Fattura.php index 4a1da5203..0aa9dfecb 100755 --- a/modules/fatture/src/Fattura.php +++ b/modules/fatture/src/Fattura.php @@ -8,7 +8,9 @@ use Common\Components\Description; use Common\Document; use Illuminate\Database\Eloquent\Builder; use Modules\Anagrafiche\Anagrafica; -use Modules\Fatture\Components\Riga; +use Modules\Fatture\Gestori\Bollo as GestoreBollo; +use Modules\Fatture\Gestori\Movimenti as GestoreMovimenti; +use Modules\Fatture\Gestori\Scadenze as GestoreScadenze; use Modules\Pagamenti\Pagamento; use Modules\PrimaNota\Movimento; use Modules\RitenuteContributi\RitenutaContributi; @@ -40,6 +42,23 @@ class Fattura extends Document 'data', ]; + /** @var GestoreScadenze */ + protected $gestoreScadenze; + /** @var GestoreMovimenti */ + protected $gestoreMovimenti; + /** @var GestoreBollo */ + private $gestoreBollo; + + public function __construct(array $attributes = []) + { + parent::__construct($attributes); + + // Inizializzazione gestori relativi + $this->gestoreScadenze = new GestoreScadenze($this); + $this->gestoreMovimenti = new GestoreMovimenti($this); + $this->gestoreBollo = new GestoreBollo($this); + } + /** * Crea una nuova fattura. * @@ -137,12 +156,12 @@ class Fattura extends Document $model->dichiarazione()->associate($dichiarazione); $model->note = tr("Operazione non imponibile come da vostra dichiarazione d'intento nr _PROT_ del _PROT_DATE_ emessa in data _RELEASE_DATE_, da noi registrata al nr _ID_ del _DATE_", [ - '_PROT_' => $dichiarazione->numero_protocollo, - '_PROT_DATE_' => $dichiarazione->data_protocollo, - '_RELEASE_DATE_' => $dichiarazione->data_emissione, - '_ID_' => $dichiarazione->id, - '_DATE_' => $dichiarazione->data, - ]).'.'; + '_PROT_' => $dichiarazione->numero_protocollo, + '_PROT_DATE_' => $dichiarazione->data_protocollo, + '_RELEASE_DATE_' => $dichiarazione->data_emissione, + '_ID_' => $dichiarazione->id, + '_DATE_' => $dichiarazione->data, + ]).'.'; } $model->save(); @@ -436,71 +455,6 @@ class Fattura extends Document return !empty($this->progressivo_invio) and file_exists($file->filepath); } - /** - * Registra le scadenze della fattura elettronica collegata al documento. - * - * @param bool $is_pagato - * - * @return bool - */ - public function registraScadenzeFE($is_pagato = false) - { - $xml = \Util\XML::read($this->getXML()); - - $pagamenti = $xml['FatturaElettronicaBody']['DatiPagamento']['DettaglioPagamento']; - if (!empty($pagamenti)) { - $rate = isset($pagamenti[0]) ? $pagamenti : [$pagamenti]; - - foreach ($rate as $rata) { - $scadenza = $rata['DataScadenzaPagamento'] ?: $this->data; - $importo = ($this->isNota()) ? $rata['ImportoPagamento'] : -$rata['ImportoPagamento']; - - self::registraScadenza($this, $importo, $scadenza, $is_pagato); - } - } - - return !empty($pagamenti); - } - - /** - * Registra le scadenze tradizionali del gestionale. - * - * @param bool $is_pagato - */ - public function registraScadenzeTradizionali($is_pagato = false) - { - $rate = $this->pagamento->calcola($this->netto, $this->data); - $direzione = $this->tipo->dir; - - foreach ($rate as $rata) { - $scadenza = $rata['scadenza']; - $importo = $direzione == 'uscita' ? -$rata['importo'] : $rata['importo']; - - self::registraScadenza($this, $importo, $scadenza, $is_pagato); - } - } - - /** - * Registra una specifica scadenza nel database. - * - * @param float $importo - * @param string $data_scadenza - * @param bool $is_pagato - * @param string $type - */ - public static function registraScadenza(Fattura $fattura, $importo, $data_scadenza, $is_pagato, $type = 'fattura') - { - $numero = $fattura->numero_esterno ?: $fattura->numero; - $descrizione = $fattura->tipo->descrizione.' numero '.$numero; - - $scadenza = Scadenza::build($descrizione, $importo, $data_scadenza, $type, $is_pagato); - - $scadenza->documento()->associate($fattura); - $scadenza->data_emissione = $fattura->data; - - $scadenza->save(); - } - /** * Registra le scadenze della fattura. * @@ -509,29 +463,7 @@ class Fattura extends Document */ public function registraScadenze($is_pagato = false, $ignora_fe = false) { - $this->rimuoviScadenze(); - - if (!$ignora_fe && $this->module == 'Fatture di acquisto' && $this->isFE()) { - $scadenze_fe = $this->registraScadenzeFE($is_pagato); - } - - if (empty($scadenze_fe)) { - $this->registraScadenzeTradizionali($is_pagato); - } - - $direzione = $this->tipo->dir; - $ritenuta_acconto = $this->ritenuta_acconto; - - // Se c'è una ritenuta d'acconto, la aggiungo allo scadenzario al 15 del mese dopo l'ultima scadenza di pagamento - if ($direzione == 'uscita' && $ritenuta_acconto > 0) { - $ultima_scadenza = $this->scadenze->last(); - $scadenza = $ultima_scadenza->scadenza->copy()->startOfMonth()->addMonth(); - $scadenza->setDate($scadenza->year, $scadenza->month, 15); - - $importo = -$ritenuta_acconto; - - self::registraScadenza($this, $importo, $scadenza, $is_pagato, 'ritenutaacconto'); - } + $this->gestoreScadenze->registra($is_pagato, $ignora_fe); } /** @@ -539,7 +471,7 @@ class Fattura extends Document */ public function rimuoviScadenze() { - database()->delete('co_scadenziario', ['iddocumento' => $this->id]); + $this->gestoreScadenze->rimuovi(); } /** @@ -550,7 +482,7 @@ class Fattura extends Document public function save(array $options = []) { // Fix dei campi statici - $this->manageRigaMarcaDaBollo(); + $this->id_riga_bollo = $this->gestoreBollo->manageRigaMarcaDaBollo(); $this->attributes['ritenutaacconto'] = $this->ritenuta_acconto; $this->attributes['iva_rivalsainps'] = $this->iva_rivalsa_inps; @@ -562,7 +494,7 @@ class Fattura extends Document $dichiarazione_precedente = Dichiarazione::find($this->original['id_dichiarazione_intento']); $is_fiscale = $this->isFiscale(); - // Generazione numero fattura se non presente + // Generazione numero fattura se non presente (Bozza -> Emessa) if ((($stato_precedente->descrizione == 'Bozza' && $this->stato['descrizione'] == 'Emessa') or (!$is_fiscale)) && empty($this->numero_esterno)) { $this->numero_esterno = self::getNextNumeroSecondario($this->data, $this->direzione, $this->id_segment); } @@ -571,6 +503,7 @@ class Fattura extends Document $result = parent::save($options); // Operazioni al cambiamento di stato + // Bozza o Annullato -> Stato diverso da Bozza o Annullato if ( in_array($stato_precedente->descrizione, ['Bozza', 'Annullata']) && !in_array($this->stato['descrizione'], ['Bozza', 'Annullata']) @@ -579,12 +512,17 @@ class Fattura extends Document $this->registraScadenze($this->stato['descrizione'] == 'Pagato'); // Registrazione movimenti - aggiungi_movimento($this->id, $this->direzione); - } elseif (in_array($this->stato['descrizione'], ['Bozza', 'Annullata'])) { + $this->gestoreMovimenti->registra(); + } // Stato qualunque -> Bozza o Annullato + elseif (in_array($this->stato['descrizione'], ['Bozza', 'Annullata'])) { + // Rimozione delle scadenza $this->rimuoviScadenze(); - elimina_movimenti($this->id, 1); - elimina_movimenti($this->id); + // Rimozione dei movimenti + $this->gestoreMovimenti->rimuovi(); + + // Rimozione dei movimenti contabili (Prima nota) + $this->movimentiContabili()->delete(); } // Operazioni sulla dichiarazione d'intento @@ -608,8 +546,14 @@ class Fattura extends Document { $result = parent::delete(); + // Rimozione delle scadenza $this->rimuoviScadenze(); - elimina_movimenti($this->id); + + // Rimozione dei movimenti + $this->gestoreMovimenti->rimuovi(); + + // Rimozione dei movimenti contabili (Prima nota) + $this->movimentiContabili()->delete(); return $result; } @@ -688,74 +632,6 @@ class Fattura extends Document return $result; } - /** - * Metodo per calcolare automaticamente il bollo da applicare al documento. - * - * @return float - */ - public function getBollo() - { - if (isset($this->bollo)) { - return $this->bollo; - } - - $righe_bollo = $this->getRighe()->filter(function ($item, $key) { - return $item->aliquota != null && in_array($item->aliquota->codice_natura_fe, ['N1', 'N2', 'N3', 'N4']); - }); - $importo_righe_bollo = $righe_bollo->sum('netto'); - - // Leggo la marca da bollo se c'è e se il netto a pagare supera la soglia - $bollo = ($this->direzione == 'uscita') ? $this->bollo : setting('Importo marca da bollo'); - - $marca_da_bollo = 0; - if (abs($bollo) > 0 && abs($importo_righe_bollo) > setting("Soglia minima per l'applicazione della marca da bollo")) { - $marca_da_bollo = $bollo; - } - - // Se l'importo è negativo può essere una nota di credito, quindi cambio segno alla marca da bollo - $marca_da_bollo = abs($marca_da_bollo); - - return $marca_da_bollo; - } - - /** - * Metodo per aggiornare ed eventualemente aggiungere la marca da bollo al documento. - */ - public function manageRigaMarcaDaBollo() - { - $riga = $this->rigaBollo; - - $addebita_bollo = $this->addebita_bollo; - $marca_da_bollo = $this->getBollo(); - - // Rimozione riga bollo se nullo - if (empty($addebita_bollo) || empty($marca_da_bollo)) { - if (!empty($riga)) { - $this->id_riga_bollo = null; - - $riga->delete(); - } - - return; - } - - // Creazione riga bollo se non presente - if (empty($riga)) { - $riga = Components\Riga::build($this); - $riga->save(); - - $this->id_riga_bollo = $riga->id; - } - - $riga->prezzo_unitario = $marca_da_bollo; - $riga->qta = 1; - $riga->descrizione = setting('Descrizione addebito bollo'); - $riga->id_iva = setting('Iva da applicare su marca da bollo'); - $riga->idconto = setting('Conto predefinito per la marca da bollo'); - - $riga->save(); - } - // Metodi statici /** diff --git a/modules/fatture/src/Gestori/Bollo.php b/modules/fatture/src/Gestori/Bollo.php new file mode 100644 index 000000000..01f608a4e --- /dev/null +++ b/modules/fatture/src/Gestori/Bollo.php @@ -0,0 +1,82 @@ +fattura = $fattura; + } + + /** + * Metodo per calcolare automaticamente il bollo da applicare al documento. + * + * @return float + */ + public function getBollo() + { + if (isset($this->fattura->bollo)) { + return $this->fattura->bollo; + } + + $righe_bollo = $this->fattura->getRighe()->filter(function ($item, $key) { + return $item->aliquota != null && in_array($item->aliquota->codice_natura_fe, ['N1', 'N2', 'N3', 'N4']); + }); + $importo_righe_bollo = $righe_bollo->sum('netto'); + + // Leggo la marca da bollo se c'è e se il netto a pagare supera la soglia + $bollo = ($this->fattura->direzione == 'uscita') ? $this->fattura->bollo : setting('Importo marca da bollo'); + + $marca_da_bollo = 0; + if (abs($bollo) > 0 && abs($importo_righe_bollo) > setting("Soglia minima per l'applicazione della marca da bollo")) { + $marca_da_bollo = $bollo; + } + + // Se l'importo è negativo può essere una nota di credito, quindi cambio segno alla marca da bollo + $marca_da_bollo = abs($marca_da_bollo); + + return $marca_da_bollo; + } + + /** + * Metodo per aggiornare ed eventualmente aggiungere la marca da bollo al documento. + */ + public function manageRigaMarcaDaBollo() + { + $riga = $this->fattura->rigaBollo; + + $addebita_bollo = $this->fattura->addebita_bollo; + $marca_da_bollo = $this->getBollo(); + + // Rimozione riga bollo se nullo + if (empty($addebita_bollo) || empty($marca_da_bollo)) { + if (!empty($riga)) { + $riga->delete(); + } + + return null; + } + + // Creazione riga bollo se non presente + if (empty($riga)) { + $riga = Components\Riga::build($this->fattura); + $riga->save(); + } + + $riga->prezzo_unitario = $marca_da_bollo; + $riga->qta = 1; + $riga->descrizione = setting('Descrizione addebito bollo'); + $riga->id_iva = setting('Iva da applicare su marca da bollo'); + $riga->idconto = setting('Conto predefinito per la marca da bollo'); + + $riga->save(); + + return $riga->id; + } +} diff --git a/modules/fatture/src/Gestori/Movimenti.php b/modules/fatture/src/Gestori/Movimenti.php new file mode 100644 index 000000000..2530650da --- /dev/null +++ b/modules/fatture/src/Gestori/Movimenti.php @@ -0,0 +1,209 @@ +fattura = $fattura; + } + + public function getMastrino() + { + if (!isset($this->mastrino)) { + $this->mastrino = Mastrino::where('iddocumento', $this->fattura->id) + ->where('primanota', false) + ->first(); + } + + return $this->mastrino; + } + + public function generateMastrino() + { + $descrizione = $this->fattura->getReference(); + $data = $this->fattura->data_competenza; + + $mastrino = Mastrino::build($descrizione, $data, false, false); + $mastrino->iddocumento = $this->fattura->id; + + $this->mastrino = $mastrino; + + return $this->mastrino; + } + + /** + * Registra i movimenti relativi alla fattura. + */ + public function registra() + { + // Rimozione degli elementi pre-esistenti + $this->rimuovi(); + + $movimenti = []; + + // Informazioni generali sul documento + $direzione = $this->fattura->direzione; + $is_acquisto = $direzione == 'uscita'; + $split_payment = $this->fattura->split_payment; + + // Totali utili per i movimenti + $totale = $this->fattura->totale; + $iva = $this->fattura->iva; + $iva_indetraibile = $this->fattura->iva_indetraibile; + $iva_detraibile = $iva - $iva_indetraibile; + + /* + * 1) Movimento relativo al conto dell'anagrafica del documento + * + * Totale (Split Payment disabilitato), oppure Totale - IVA detraibile (Split Payment abilitato) -> DARE per Vendita, AVERE per Acquisto + */ + $anagrafica = $this->fattura->anagrafica; + + $id_conto = $is_acquisto ? $anagrafica->idconto_fornitore : $anagrafica->idconto_cliente; + if (empty($id_conto)) { + $id_conto = $is_acquisto ? setting('Conto per Riepilogativo fornitori') : setting('Conto per Riepilogativo clienti'); + } + $id_conto_controparte = $id_conto; // Salvataggio del conto dell'anagrafica per usi successivi + + $importo_anagrafica = $totale; + if ($split_payment) { + $importo_anagrafica = sum($importo_anagrafica, -$iva_detraibile, 2); + } + + $movimenti[] = [ + 'id_conto' => $id_conto, + 'dare' => $importo_anagrafica, + ]; + + /* + * 2) Movimento per ogni riga del documento + * Imponibile -> AVERE per Vendita, DARE per Acquisto + */ + $righe = $this->fattura->getRighe(); + foreach ($righe as $riga) { + // Retro-compatibilità per versioni <= 2.4 + $id_conto = $riga->id_conto ?: $this->fattura->idconto; + + $imponibile = $riga->imponibile; + if (!empty($imponibile)) { + $movimenti[] = [ + 'id_conto' => $id_conto, + 'avere' => $riga->imponibile, + ]; + } + } + + /* + * 3) IVA detraibile sul relativo conto (Split Payment disabilitato) + * IVA detraibile -> AVERE per Vendita, DARE per Acquisto + */ + if (!empty($iva_detraibile) && empty($split_payment)) { + $id_conto = $is_acquisto ? setting('Conto per Iva su acquisti') : setting('Conto per Iva su vendite'); + $movimenti[] = [ + 'id_conto' => $id_conto, + 'avere' => $iva_detraibile, + ]; + } + + /* + * 4) IVA indetraibile sul relativo conto (Split Payment disabilitato) + * IVA indetraibile -> AVERE per Vendita, DARE per Acquisto + */ + if (!empty($iva_indetraibile) && empty($split_payment)) { + $id_conto = setting('Conto per Iva indetraibile'); + $movimenti[] = [ + 'id_conto' => $id_conto, + 'avere' => $iva_indetraibile, + ]; + } + + /* + * 5) Rivalsa INPS sul relativo conto + * Rivalsa INPS (senza IVA) -> AVERE per Vendita, DARE per Acquisto + */ + $rivalsa_inps = $this->fattura->rivalsa_inps; + if (!empty($rivalsa_inps)) { + $id_conto = setting('Conto per Erario c/INPS'); + $movimenti[] = [ + 'id_conto' => $id_conto, + 'avere' => $rivalsa_inps, + ]; + } + + /* + * 6) Ritenuta d'acconto + * Conto "Conto per Erario c/ritenute d'acconto": DARE per Vendita, AVERE per Acquisto + * Conto della controparte: AVERE per Vendita, DARE per Acquisto + */ + $ritenuta_acconto = $this->fattura->ritenuta_acconto; + if (!empty($ritenuta_acconto)) { + $id_conto = setting("Conto per Erario c/ritenute d'acconto"); + $movimenti[] = [ + 'id_conto' => $id_conto, + 'dare' => $ritenuta_acconto, + ]; + + $movimenti[] = [ + 'id_conto' => $id_conto_controparte, + 'avere' => $ritenuta_acconto, + ]; + } + + /* + * 7) Ritenuta contributi + * Conto "Conto per Erario c/enasarco": DARE per Vendita, AVERE per Acquisto + * Conto della controparte: AVERE per Vendita, DARE per Acquisto + */ + $ritenuta_contributi = $this->fattura->totale_ritenuta_contributi; + if (!empty($ritenuta_contributi)) { + $id_conto = setting('Conto per Erario c/enasarco'); + $movimenti[] = [ + 'id_conto' => $id_conto, + 'dare' => $ritenuta_contributi, + ]; + + $movimenti[] = [ + 'id_conto' => $id_conto_controparte, + 'avere' => $ritenuta_contributi, + ]; + } + + // Inversione contabile per i documenti di acquisto + if ($is_acquisto) { + foreach ($movimenti as $movimento) { + $temp = $movimento['avere']; + $movimento['avere'] = $movimento['dare']; + $movimento['dare'] = $temp; + } + } + + // Registrazione dei singoli Movimenti nel relativo Mastrino + $mastrino = $this->generateMastrino(); + foreach ($movimenti as $element) { + $movimento = Movimento::build($mastrino, $element['id_conto']); + $movimento->setTotale($element['avere'] ?: 0, $element['dare'] ?: 0); + $movimento->save(); + } + } + + /** + * Elimina i movimenti del mastrino relativo alla fattura. + */ + public function rimuovi() + { + $mastrino = $this->getMastrino(); + + if (!empty($mastrino)) { + $mastrino->delete(); + } + } +} diff --git a/modules/fatture/src/Gestori/Scadenze.php b/modules/fatture/src/Gestori/Scadenze.php new file mode 100644 index 000000000..1f96738f8 --- /dev/null +++ b/modules/fatture/src/Gestori/Scadenze.php @@ -0,0 +1,123 @@ +fattura = $fattura; + } + + /** + * Registra le scadenze della fattura. + * + * @param bool $is_pagato + * @param bool $ignora_fe + */ + public function registra($is_pagato = false, $ignora_fe = false) + { + // Rimozione degli elementi pre-esistenti + $this->rimuovi(); + + if (!$ignora_fe && $this->fattura->module == 'Fatture di acquisto' && $this->fattura->isFE()) { + $scadenze_fe = $this->registraScadenzeFE($is_pagato); + } + + if (empty($scadenze_fe)) { + $this->registraScadenzeTradizionali($is_pagato); + } + + $direzione = $this->fattura->tipo->dir; + $ritenuta_acconto = $this->fattura->ritenuta_acconto; + + // Se c'è una ritenuta d'acconto, la aggiungo allo scadenzario al 15 del mese dopo l'ultima scadenza di pagamento + if ($direzione == 'uscita' && $ritenuta_acconto > 0) { + $ultima_scadenza = $this->fattura->scadenze->last(); + $scadenza = $ultima_scadenza->scadenza->copy()->startOfMonth()->addMonth(); + $scadenza->setDate($scadenza->year, $scadenza->month, 15); + + $importo = -$ritenuta_acconto; + + self::registraScadenza($this->fattura, $importo, $scadenza, $is_pagato, 'ritenutaacconto'); + } + } + + /** + * Elimina le scadenze della fattura. + */ + public function rimuovi() + { + database()->delete('co_scadenziario', ['iddocumento' => $this->fattura->id]); + } + + /** + * Registra una specifica scadenza nel database. + * + * @param float $importo + * @param string $data_scadenza + * @param bool $is_pagato + * @param string $type + */ + protected function registraScadenza(Fattura $fattura, $importo, $data_scadenza, $is_pagato, $type = 'fattura') + { + $numero = $fattura->numero_esterno ?: $fattura->numero; + $descrizione = $fattura->tipo->descrizione.' numero '.$numero; + + $scadenza = Scadenza::build($descrizione, $importo, $data_scadenza, $type, $is_pagato); + + $scadenza->documento()->associate($fattura); + $scadenza->data_emissione = $fattura->data; + + $scadenza->save(); + } + + /** + * Registra le scadenze della fattura elettronica collegata al documento. + * + * @param bool $is_pagato + * + * @return bool + */ + protected function registraScadenzeFE($is_pagato = false) + { + $xml = \Util\XML::read($this->fattura->getXML()); + + $pagamenti = $xml['FatturaElettronicaBody']['DatiPagamento']['DettaglioPagamento']; + if (!empty($pagamenti)) { + $rate = isset($pagamenti[0]) ? $pagamenti : [$pagamenti]; + + foreach ($rate as $rata) { + $scadenza = $rata['DataScadenzaPagamento'] ?: $this->fattura->data; + $importo = ($this->fattura->isNota()) ? $rata['ImportoPagamento'] : -$rata['ImportoPagamento']; + + self::registraScadenza($this->fattura, $importo, $scadenza, $is_pagato); + } + } + + return !empty($pagamenti); + } + + /** + * Registra le scadenze tradizionali del gestionale. + * + * @param bool $is_pagato + */ + protected function registraScadenzeTradizionali($is_pagato = false) + { + $rate = $this->fattura->pagamento->calcola($this->fattura->netto, $this->fattura->data); + $direzione = $this->fattura->tipo->dir; + + foreach ($rate as $rata) { + $scadenza = $rata['scadenza']; + $importo = $direzione == 'uscita' ? -$rata['importo'] : $rata['importo']; + + self::registraScadenza($this->fattura, $importo, $scadenza, $is_pagato); + } + } +} diff --git a/modules/iva/edit.php b/modules/iva/edit.php index 896ec0a4a..82eeee0e7 100755 --- a/modules/iva/edit.php +++ b/modules/iva/edit.php @@ -56,7 +56,7 @@ if ($res) {
- {[ "type": "number", "label": "", "name": "indetraibile", "value": "$indetraibile$", "icon-after": "", "readonly": "", "extra": "", "max-value": "100" ]} + {[ "type": "number", "label": "", "name": "indetraibile", "value": "$indetraibile$", "icon-after": "", "readonly": "", "extra": "", "max-value": "100" ]}
diff --git a/modules/partitario/actions.php b/modules/partitario/actions.php index d49d46942..8b7b6a5d6 100755 --- a/modules/partitario/actions.php +++ b/modules/partitario/actions.php @@ -45,7 +45,7 @@ switch (post('op')) { } else { $duplicate_query = 'SELECT idpianodeiconti2, numero FROM co_pianodeiconti3 WHERE numero='.prepare($numero).' AND NOT id='.prepare($idconto).' AND idpianodeiconti2='.prepare($idpianodeiconti); - $update_query = 'UPDATE co_pianodeiconti3 SET numero='.prepare($numero).', descrizione='.prepare($descrizione).' WHERE id='.prepare($idconto); + $update_query = 'UPDATE co_pianodeiconti3 SET numero='.prepare($numero).', descrizione='.prepare($descrizione).', percentuale_deducibile='.prepare(post('percentuale_deducibile')).' WHERE id='.prepare($idconto); } // Controllo che non sia stato usato un numero non valido del conto diff --git a/modules/partitario/edit_conto.php b/modules/partitario/edit_conto.php index 4c1a36fc1..6517b9cbd 100755 --- a/modules/partitario/edit_conto.php +++ b/modules/partitario/edit_conto.php @@ -23,11 +23,16 @@ $info = $dbo->fetchOne($query);
-
+
{[ "type": "text", "label": "", "name": "numero", "required": 1, "class": "text-center", "value": "", "extra": "maxlength=\"6\"" ]}
-
+
+ {[ "type": "number", "label": "", "name": "percentuale_deducibile", "value": "", "disabled": , "icon-after": "", "max-value": "100", "min-value": "0" ]} +
+
+
+
{[ "type": "text", "label": "", "name": "descrizione", "required": 1, "value": ]}
@@ -41,3 +46,5 @@ $info = $dbo->fetchOne($query);
+ + diff --git a/modules/primanota/src/Mastrino.php b/modules/primanota/src/Mastrino.php index 6500fd16f..3f9986d97 100755 --- a/modules/primanota/src/Mastrino.php +++ b/modules/primanota/src/Mastrino.php @@ -32,6 +32,11 @@ class Mastrino extends Model return $model; } + /** + * Rimuove tutti i movimenti collegati al mastrino. + * + * @return mixed + */ public function cleanup() { $movimenti = $this->movimenti; @@ -44,6 +49,7 @@ class Mastrino extends Model public function save(array $options = []) { + return true; } public function delete() @@ -51,7 +57,7 @@ class Mastrino extends Model $movimenti = $this->cleanup(); $this->aggiornaScadenzario($movimenti); - return parent::delete(); // TODO: Change the autogenerated stub + return parent::delete(); } // Attributi @@ -74,8 +80,13 @@ class Mastrino extends Model public function aggiornaScadenzario($movimenti = null) { + // Aggiornamento dello scadenzario disponibile solo da Mastrino di PrimaNota + if (empty($this->primanota)) { + return; + } $movimenti = $movimenti ?: $this->movimenti; + // Aggiornamento delle scadenze per i singoli documenti $documenti = []; $scadenze = []; foreach ($movimenti as $movimento) { @@ -123,7 +134,28 @@ class Mastrino extends Model } } - public function correggiScadenza(Movimento $movimento, Scadenza $scadenza = null, Fattura $documento = null) + // Relazioni Eloquent + + public function fattura() + { + return $this->belongsTo(Fattura::class, 'iddocumento'); + } + + public function movimenti() + { + return $this->hasMany(Movimento::class, 'idmastrino'); + } + + // Metodi statici + + public static function getNextMastrino() + { + $ultimo = database()->fetchOne('SELECT MAX(idmastrino) AS max FROM co_movimenti'); + + return intval($ultimo['max']) + 1; + } + + protected function correggiScadenza(Movimento $movimento, Scadenza $scadenza = null, Fattura $documento = null) { $documento = $documento ?: $scadenza->documento; if ($documento) { @@ -184,25 +216,4 @@ class Mastrino extends Model $scadenza->save(); } } - - // Relazioni Eloquent - - public function fattura() - { - return $this->belongsTo(Fattura::class, 'iddocumento'); - } - - public function movimenti() - { - return $this->hasMany(Movimento::class, 'idmastrino'); - } - - // Metodi statici - - public static function getNextMastrino() - { - $ultimo = database()->fetchOne('SELECT MAX(idmastrino) AS max FROM co_movimenti'); - - return intval($ultimo['max']) + 1; - } } diff --git a/modules/primanota/src/Movimento.php b/modules/primanota/src/Movimento.php index 3919960cd..b981ba669 100755 --- a/modules/primanota/src/Movimento.php +++ b/modules/primanota/src/Movimento.php @@ -26,8 +26,13 @@ class Movimento extends Model $model->primanota = $mastrino->primanota; $model->is_insoluto = $mastrino->is_insoluto; - $model->id_scadenza = $scadenza ? $scadenza->id : null; + // Associazione al documento del mastrino + if (!empty($mastrino->iddocumento)) { + $model->iddocumento = $mastrino->iddocumento; + } + // Associazione alla scadenza indicata + $model->id_scadenza = $scadenza ? $scadenza->id : null; $documento = $scadenza ? $scadenza->documento : null; if (!empty($documento)) { $model->iddocumento = $documento->id; @@ -52,6 +57,16 @@ class Movimento extends Model $this->totale = $totale; } + public function save(array $options = []) + { + // Aggiornamento automatico di totale_reddito + $conto = database()->fetchOne('SELECT * FROM co_pianodeiconti3 WHERE id = '.prepare($this->id_conto)); + $percentuale = floatval($conto['percentuale_deducibile']); + $this->totale_reddito = $this->totale * $percentuale / 100; + + return parent::save($options); + } + // Attributi public function getIdContoAttribute() diff --git a/update/2_4_17.sql b/update/2_4_17.sql index 414e3eac2..25b7804a0 100644 --- a/update/2_4_17.sql +++ b/update/2_4_17.sql @@ -227,3 +227,7 @@ UPDATE `my_impianto_componenti` SET `data_sostituzione` = NULL WHERE `data_sosti INSERT INTO `zz_settings` (`id`, `nome`, `valore`, `tipo`, `editable`, `sezione`, `order`) VALUES (NULL, 'Mostra promemoria attività ai soli Tecnici assegnati', '1', 'boolean', '1', 'Attività', 14), (NULL, 'Espandi automaticamente la sezione "Dettagli aggiuntivi"', '0', 'boolean', '1', 'Attività', 15); + +-- Modifica per introdurre il totale reddito per i Movimenti, sulla base del Conto relativo +ALTER TABLE `co_movimenti` ADD `totale_reddito` decimal(12, 6) NOT NULL DEFAULT 0; +ALTER TABLE `co_pianodeiconti3` ADD `percentuale_deducibile` decimal(5,2) NOT NULL DEFAULT 0;