Introduzione Totale reddito per i Movimenti

This commit is contained in:
Thomas Zilio 2020-08-05 17:58:54 +02:00
parent a1009c52a2
commit 8e4e6951cf
11 changed files with 538 additions and 199 deletions

View File

@ -91,6 +91,8 @@ function get_ivaindetraibile_fattura($iddocumento)
/** /**
* Elimina una scadenza in base al codice documento. * Elimina una scadenza in base al codice documento.
*
* @deprecated 2.4.17
*/ */
function elimina_scadenze($iddocumento) function elimina_scadenze($iddocumento)
{ {
@ -104,6 +106,8 @@ function elimina_scadenze($iddocumento)
* $iddocumento string E' l'id del documento di cui ricalcolare lo scadenzario * $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. * $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. * $pagato boolean Indica se devo segnare l'importo come pagato.
*
* @deprecated 2.4.17
*/ */
function aggiungi_scadenza($iddocumento, $pagamento = '', $pagato = false) function aggiungi_scadenza($iddocumento, $pagamento = '', $pagato = false)
{ {
@ -118,6 +122,8 @@ function aggiungi_scadenza($iddocumento, $pagamento = '', $pagato = false)
* *
* @param $iddocumento * @param $iddocumento
* @param int $prima_nota * @param int $prima_nota
*
* @deprecated 2.4.17
*/ */
function elimina_movimenti($id_documento, $prima_nota = 0) 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 * $iddocumento string E' l'id del documento da collegare alla prima nota
* $dir string Direzione dell'importo (entrata, uscita) * $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). * $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) 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. * Funzione per generare un nuovo codice per il mastrino.
*
* @deprecated 2.4.17
*/ */
function get_new_idmastrino($table = 'co_movimenti') 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) * 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 * Deve essere eseguito ogni volta che si aggiunge o toglie una riga
* $iddocumento int ID della fattura. * $iddocumento int ID della fattura.
*
* @deprecated 2.4.17
*/ */
function ricalcola_costiagg_fattura($iddocumento) function ricalcola_costiagg_fattura($iddocumento)
{ {

View File

@ -8,7 +8,9 @@ use Common\Components\Description;
use Common\Document; use Common\Document;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Modules\Anagrafiche\Anagrafica; 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\Pagamenti\Pagamento;
use Modules\PrimaNota\Movimento; use Modules\PrimaNota\Movimento;
use Modules\RitenuteContributi\RitenutaContributi; use Modules\RitenuteContributi\RitenutaContributi;
@ -40,6 +42,23 @@ class Fattura extends Document
'data', '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. * Crea una nuova fattura.
* *
@ -137,12 +156,12 @@ class Fattura extends Document
$model->dichiarazione()->associate($dichiarazione); $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_", [ $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_' => $dichiarazione->numero_protocollo,
'_PROT_DATE_' => $dichiarazione->data_protocollo, '_PROT_DATE_' => $dichiarazione->data_protocollo,
'_RELEASE_DATE_' => $dichiarazione->data_emissione, '_RELEASE_DATE_' => $dichiarazione->data_emissione,
'_ID_' => $dichiarazione->id, '_ID_' => $dichiarazione->id,
'_DATE_' => $dichiarazione->data, '_DATE_' => $dichiarazione->data,
]).'.'; ]).'.';
} }
$model->save(); $model->save();
@ -436,71 +455,6 @@ class Fattura extends Document
return !empty($this->progressivo_invio) and file_exists($file->filepath); 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. * Registra le scadenze della fattura.
* *
@ -509,29 +463,7 @@ class Fattura extends Document
*/ */
public function registraScadenze($is_pagato = false, $ignora_fe = false) public function registraScadenze($is_pagato = false, $ignora_fe = false)
{ {
$this->rimuoviScadenze(); $this->gestoreScadenze->registra($is_pagato, $ignora_fe);
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');
}
} }
/** /**
@ -539,7 +471,7 @@ class Fattura extends Document
*/ */
public function rimuoviScadenze() 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 = []) public function save(array $options = [])
{ {
// Fix dei campi statici // Fix dei campi statici
$this->manageRigaMarcaDaBollo(); $this->id_riga_bollo = $this->gestoreBollo->manageRigaMarcaDaBollo();
$this->attributes['ritenutaacconto'] = $this->ritenuta_acconto; $this->attributes['ritenutaacconto'] = $this->ritenuta_acconto;
$this->attributes['iva_rivalsainps'] = $this->iva_rivalsa_inps; $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']); $dichiarazione_precedente = Dichiarazione::find($this->original['id_dichiarazione_intento']);
$is_fiscale = $this->isFiscale(); $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)) { 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); $this->numero_esterno = self::getNextNumeroSecondario($this->data, $this->direzione, $this->id_segment);
} }
@ -571,6 +503,7 @@ class Fattura extends Document
$result = parent::save($options); $result = parent::save($options);
// Operazioni al cambiamento di stato // Operazioni al cambiamento di stato
// Bozza o Annullato -> Stato diverso da Bozza o Annullato
if ( if (
in_array($stato_precedente->descrizione, ['Bozza', 'Annullata']) in_array($stato_precedente->descrizione, ['Bozza', 'Annullata'])
&& !in_array($this->stato['descrizione'], ['Bozza', 'Annullata']) && !in_array($this->stato['descrizione'], ['Bozza', 'Annullata'])
@ -579,12 +512,17 @@ class Fattura extends Document
$this->registraScadenze($this->stato['descrizione'] == 'Pagato'); $this->registraScadenze($this->stato['descrizione'] == 'Pagato');
// Registrazione movimenti // Registrazione movimenti
aggiungi_movimento($this->id, $this->direzione); $this->gestoreMovimenti->registra();
} elseif (in_array($this->stato['descrizione'], ['Bozza', 'Annullata'])) { } // Stato qualunque -> Bozza o Annullato
elseif (in_array($this->stato['descrizione'], ['Bozza', 'Annullata'])) {
// Rimozione delle scadenza
$this->rimuoviScadenze(); $this->rimuoviScadenze();
elimina_movimenti($this->id, 1); // Rimozione dei movimenti
elimina_movimenti($this->id); $this->gestoreMovimenti->rimuovi();
// Rimozione dei movimenti contabili (Prima nota)
$this->movimentiContabili()->delete();
} }
// Operazioni sulla dichiarazione d'intento // Operazioni sulla dichiarazione d'intento
@ -608,8 +546,14 @@ class Fattura extends Document
{ {
$result = parent::delete(); $result = parent::delete();
// Rimozione delle scadenza
$this->rimuoviScadenze(); $this->rimuoviScadenze();
elimina_movimenti($this->id);
// Rimozione dei movimenti
$this->gestoreMovimenti->rimuovi();
// Rimozione dei movimenti contabili (Prima nota)
$this->movimentiContabili()->delete();
return $result; return $result;
} }
@ -688,74 +632,6 @@ class Fattura extends Document
return $result; 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 // Metodi statici
/** /**

View File

@ -0,0 +1,82 @@
<?php
namespace Modules\Fatture\Gestori;
use Modules\Fatture\Components;
use Modules\Fatture\Fattura;
class Bollo
{
private $fattura;
public function __construct(Fattura $fattura)
{
$this->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;
}
}

View File

@ -0,0 +1,209 @@
<?php
namespace Modules\Fatture\Gestori;
use Modules\Fatture\Fattura;
use Modules\PrimaNota\Mastrino;
use Modules\PrimaNota\Movimento;
class Movimenti
{
protected $fattura;
protected $mastrino = null;
public function __construct(Fattura $fattura)
{
$this->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();
}
}
}

View File

@ -0,0 +1,123 @@
<?php
namespace Modules\Fatture\Gestori;
use Modules\Fatture\Fattura;
use Modules\Scadenzario\Scadenza;
class Scadenze
{
private $fattura;
public function __construct(Fattura $fattura)
{
$this->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);
}
}
}

View File

@ -56,7 +56,7 @@ if ($res) {
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
{[ "type": "number", "label": "<?php echo tr('Indetraibile'); ?>", "name": "indetraibile", "value": "$indetraibile$", "icon-after": "<i class=\"fa fa-percent\"></i>", "readonly": "<?php echo $is_readonly; ?>", "extra": "<?php echo $attr; ?>", "max-value": "100" ]} {[ "type": "number", "label": "<?php echo tr('Indetraibile'); ?>", "name": "indetraibile", "value": "$indetraibile$", "icon-after": "<i class=\"fa fa-percent\"></i>", "readonly": "<?php echo $is_readonly; ?>", "extra": "<?php echo $attr; ?>", "max-value": "100" ]}
</div> </div>
</div> </div>

View File

@ -45,7 +45,7 @@ switch (post('op')) {
} else { } else {
$duplicate_query = 'SELECT idpianodeiconti2, numero FROM co_pianodeiconti3 WHERE numero='.prepare($numero).' AND NOT id='.prepare($idconto).' AND idpianodeiconti2='.prepare($idpianodeiconti); $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 // Controllo che non sia stato usato un numero non valido del conto

View File

@ -23,11 +23,16 @@ $info = $dbo->fetchOne($query);
<input type="hidden" name="idconto" value="<?php echo $info['id']; ?>"> <input type="hidden" name="idconto" value="<?php echo $info['id']; ?>">
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-6">
{[ "type": "text", "label": "<?php echo tr('Numero'); ?>", "name": "numero", "required": 1, "class": "text-center", "value": "<?php echo $info['numero']; ?>", "extra": "maxlength=\"6\"" ]} {[ "type": "text", "label": "<?php echo tr('Numero'); ?>", "name": "numero", "required": 1, "class": "text-center", "value": "<?php echo $info['numero']; ?>", "extra": "maxlength=\"6\"" ]}
</div> </div>
<div class="col-md-8"> <div class="col-md-6">
{[ "type": "number", "label": "<?php echo tr('Percentuale deducibile'); ?>", "name": "percentuale_deducibile", "value": "<?php echo $info['percentuale_deducibile']; ?>", "disabled": <?php echo intval($lvl == 2); ?>, "icon-after": "<i class=\"fa fa-percent\"></i>", "max-value": "100", "min-value": "0" ]}
</div>
</div>
<div class="row">
<div class="col-md-12">
{[ "type": "text", "label": "<?php echo tr('Descrizione'); ?>", "name": "descrizione", "required": 1, "value": <?php echo json_encode($info['descrizione']); ?> ]} {[ "type": "text", "label": "<?php echo tr('Descrizione'); ?>", "name": "descrizione", "required": 1, "value": <?php echo json_encode($info['descrizione']); ?> ]}
</div> </div>
</div> </div>
@ -41,3 +46,5 @@ $info = $dbo->fetchOne($query);
<div class="clearfix"></div> <div class="clearfix"></div>
</form> </form>
<script>$(document).ready(init)</script>

View File

@ -32,6 +32,11 @@ class Mastrino extends Model
return $model; return $model;
} }
/**
* Rimuove tutti i movimenti collegati al mastrino.
*
* @return mixed
*/
public function cleanup() public function cleanup()
{ {
$movimenti = $this->movimenti; $movimenti = $this->movimenti;
@ -44,6 +49,7 @@ class Mastrino extends Model
public function save(array $options = []) public function save(array $options = [])
{ {
return true;
} }
public function delete() public function delete()
@ -51,7 +57,7 @@ class Mastrino extends Model
$movimenti = $this->cleanup(); $movimenti = $this->cleanup();
$this->aggiornaScadenzario($movimenti); $this->aggiornaScadenzario($movimenti);
return parent::delete(); // TODO: Change the autogenerated stub return parent::delete();
} }
// Attributi // Attributi
@ -74,8 +80,13 @@ class Mastrino extends Model
public function aggiornaScadenzario($movimenti = null) public function aggiornaScadenzario($movimenti = null)
{ {
// Aggiornamento dello scadenzario disponibile solo da Mastrino di PrimaNota
if (empty($this->primanota)) {
return;
}
$movimenti = $movimenti ?: $this->movimenti; $movimenti = $movimenti ?: $this->movimenti;
// Aggiornamento delle scadenze per i singoli documenti
$documenti = []; $documenti = [];
$scadenze = []; $scadenze = [];
foreach ($movimenti as $movimento) { 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; $documento = $documento ?: $scadenza->documento;
if ($documento) { if ($documento) {
@ -184,25 +216,4 @@ class Mastrino extends Model
$scadenza->save(); $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;
}
} }

View File

@ -26,8 +26,13 @@ class Movimento extends Model
$model->primanota = $mastrino->primanota; $model->primanota = $mastrino->primanota;
$model->is_insoluto = $mastrino->is_insoluto; $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; $documento = $scadenza ? $scadenza->documento : null;
if (!empty($documento)) { if (!empty($documento)) {
$model->iddocumento = $documento->id; $model->iddocumento = $documento->id;
@ -52,6 +57,16 @@ class Movimento extends Model
$this->totale = $totale; $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 // Attributi
public function getIdContoAttribute() public function getIdContoAttribute()

View File

@ -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 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, 'Mostra promemoria attività ai soli Tecnici assegnati', '1', 'boolean', '1', 'Attività', 14),
(NULL, 'Espandi automaticamente la sezione "Dettagli aggiuntivi"', '0', 'boolean', '1', 'Attività', 15); (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;