Introduzione script per correzione movimenti contabili per Sconti
This commit is contained in:
parent
69b715fbd4
commit
aa8725899b
|
@ -69,7 +69,7 @@ class Fattura extends Document
|
||||||
/** @var GestoreMovimenti */
|
/** @var GestoreMovimenti */
|
||||||
protected $gestoreMovimenti;
|
protected $gestoreMovimenti;
|
||||||
/** @var GestoreBollo */
|
/** @var GestoreBollo */
|
||||||
private $gestoreBollo;
|
protected $gestoreBollo;
|
||||||
|
|
||||||
public function __construct(array $attributes = [])
|
public function __construct(array $attributes = [])
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Modules\Fatture\Fattura;
|
||||||
|
use Modules\Fatture\Gestori\Movimenti as GestoreMovimenti;
|
||||||
|
|
||||||
|
// Correzione movimenti contabili automatici per Fatture dalla versione 2.4.17 in poi
|
||||||
|
$fatture = Fattura::where('created_at', '>', '2020-08-01')
|
||||||
|
->whereHas('stato', function ($query) {
|
||||||
|
return $query->whereNotIn('descrizione', ['Bozza', 'Annullata']);
|
||||||
|
})
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($fatture as $fattura) {
|
||||||
|
$gestore = new GestoreMovimenti($fattura);
|
||||||
|
$gestore->registra();
|
||||||
|
}
|
|
@ -1,294 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10;
|
|
||||||
|
|
||||||
use Common\Model;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
||||||
use Modules\TipiIntervento\Tipo as TipoSessione;
|
|
||||||
use Settings;
|
|
||||||
use Traits\RecordTrait;
|
|
||||||
use Util\Generator;
|
|
||||||
|
|
||||||
class Anagrafica extends Model
|
|
||||||
{
|
|
||||||
use RecordTrait;
|
|
||||||
use SoftDeletes;
|
|
||||||
|
|
||||||
protected $table = 'an_anagrafiche';
|
|
||||||
protected $primaryKey = 'idanagrafica';
|
|
||||||
protected $module = 'Anagrafiche';
|
|
||||||
|
|
||||||
protected $guarded = [];
|
|
||||||
|
|
||||||
protected $appends = [
|
|
||||||
'id',
|
|
||||||
'partita_iva',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $hidden = [
|
|
||||||
'idanagrafica',
|
|
||||||
'piva',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea una nuova anagrafica.
|
|
||||||
*
|
|
||||||
* @param string $ragione_sociale
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function build($ragione_sociale, $nome = '', $cognome = '', array $tipologie = [])
|
|
||||||
{
|
|
||||||
$model = parent::build();
|
|
||||||
|
|
||||||
$model->ragione_sociale = $ragione_sociale;
|
|
||||||
|
|
||||||
$model->nome = $nome;
|
|
||||||
$model->cognome = $cognome;
|
|
||||||
|
|
||||||
$model->codice = static::getNextCodice();
|
|
||||||
$model->id_ritenuta_acconto_vendite = setting("Percentuale ritenuta d'acconto");
|
|
||||||
$model->save();
|
|
||||||
|
|
||||||
$model->tipologie = $tipologie;
|
|
||||||
$model->save();
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fromTipo($type)
|
|
||||||
{
|
|
||||||
$tipologia = TipoAnagrafica::where('descrizione', 'Tecnico')->first();
|
|
||||||
|
|
||||||
$anagrafiche = self::whereHas('tipi', function ($query) use ($tipologia) {
|
|
||||||
$query->where('an_tipianagrafiche.idtipoanagrafica', '=', $tipologia->id);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $anagrafiche;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fixAzienda(Anagrafica $anagrafica)
|
|
||||||
{
|
|
||||||
Settings::setValue('Azienda predefinita', $anagrafica->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fixCliente(Anagrafica $anagrafica)
|
|
||||||
{
|
|
||||||
$database = database();
|
|
||||||
|
|
||||||
// Creo il relativo conto nel partitario se non esiste
|
|
||||||
if (empty($anagrafica->idconto_cliente)) {
|
|
||||||
// Calcolo prossimo numero cliente
|
|
||||||
$rs = $database->fetchArray("SELECT MAX(CAST(co_pianodeiconti3.numero AS UNSIGNED)) AS max_numero FROM co_pianodeiconti3 INNER JOIN co_pianodeiconti2 ON co_pianodeiconti3.idpianodeiconti2=co_pianodeiconti2.id WHERE co_pianodeiconti2.descrizione='Crediti clienti e crediti diversi'");
|
|
||||||
$new_numero = $rs[0]['max_numero'] + 1;
|
|
||||||
$new_numero = str_pad($new_numero, 6, '0', STR_PAD_LEFT);
|
|
||||||
|
|
||||||
$database->query('INSERT INTO co_pianodeiconti3(numero, descrizione, idpianodeiconti2, can_delete, can_edit) VALUES('.prepare($new_numero).', '.prepare($anagrafica->ragione_sociale).", (SELECT id FROM co_pianodeiconti2 WHERE descrizione='Crediti clienti e crediti diversi'), 1, 1)");
|
|
||||||
$idconto = $database->lastInsertedID();
|
|
||||||
|
|
||||||
// Collegamento conto
|
|
||||||
$anagrafica->idconto_cliente = $idconto;
|
|
||||||
$anagrafica->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fixFornitore(Anagrafica $anagrafica)
|
|
||||||
{
|
|
||||||
$database = database();
|
|
||||||
|
|
||||||
// Creo il relativo conto nel partitario se non esiste
|
|
||||||
if (empty($anagrafica->idconto_fornitore)) {
|
|
||||||
// Calcolo prossimo numero cliente
|
|
||||||
$rs = $database->fetchArray("SELECT MAX(CAST(co_pianodeiconti3.numero AS UNSIGNED)) AS max_numero FROM co_pianodeiconti3 INNER JOIN co_pianodeiconti2 ON co_pianodeiconti3.idpianodeiconti2=co_pianodeiconti2.id WHERE co_pianodeiconti2.descrizione='Debiti fornitori e debiti diversi'");
|
|
||||||
$new_numero = $rs[0]['max_numero'] + 1;
|
|
||||||
$new_numero = str_pad($new_numero, 6, '0', STR_PAD_LEFT);
|
|
||||||
|
|
||||||
$database->query('INSERT INTO co_pianodeiconti3(numero, descrizione, idpianodeiconti2, can_delete, can_edit) VALUES('.prepare($new_numero).', '.prepare($anagrafica->ragione_sociale).", (SELECT id FROM co_pianodeiconti2 WHERE descrizione='Debiti fornitori e debiti diversi'), 1, 1)");
|
|
||||||
$idconto = $database->lastInsertedID();
|
|
||||||
|
|
||||||
// Collegamento conto
|
|
||||||
$anagrafica->idconto_fornitore = $idconto;
|
|
||||||
$anagrafica->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function fixTecnico(Anagrafica $anagrafica)
|
|
||||||
{
|
|
||||||
$database = database();
|
|
||||||
|
|
||||||
$presenti = $database->fetchArray('SELECT idtipointervento AS id FROM in_tariffe WHERE idtecnico = '.prepare($anagrafica->id));
|
|
||||||
|
|
||||||
// Aggiunta associazioni costi unitari al contratto
|
|
||||||
$tipi = TipoSessione::whereNotIn('idtipointervento', array_column($presenti, 'id'))->get();
|
|
||||||
|
|
||||||
foreach ($tipi as $tipo) {
|
|
||||||
$database->insert('in_tariffe', [
|
|
||||||
'idtecnico' => $anagrafica->id,
|
|
||||||
'idtipointervento' => $tipo->id,
|
|
||||||
'costo_ore' => $tipo->costo_orario,
|
|
||||||
'costo_km' => $tipo->costo_km,
|
|
||||||
'costo_dirittochiamata' => $tipo->costo_diritto_chiamata,
|
|
||||||
'costo_ore_tecnico' => $tipo->costo_orario_tecnico,
|
|
||||||
'costo_km_tecnico' => $tipo->costo_km_tecnico,
|
|
||||||
'costo_dirittochiamata_tecnico' => $tipo->costo_diritto_chiamata_tecnico,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Aggiorna la tipologia dell'anagrafica.
|
|
||||||
*/
|
|
||||||
public function setTipologieAttribute(array $tipologie)
|
|
||||||
{
|
|
||||||
if ($this->isAzienda()) {
|
|
||||||
$tipologie[] = TipoAnagrafica::where('descrizione', 'Azienda')->first()->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
$tipologie = array_clean($tipologie);
|
|
||||||
|
|
||||||
$previous = $this->tipi()->get();
|
|
||||||
$this->tipi()->sync($tipologie);
|
|
||||||
$actual = $this->tipi()->get();
|
|
||||||
|
|
||||||
$diff = $actual->diff($previous);
|
|
||||||
|
|
||||||
foreach ($diff as $tipo) {
|
|
||||||
$method = 'fix'.$tipo->descrizione;
|
|
||||||
if (method_exists($this, $method)) {
|
|
||||||
self::$method($this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controlla se l'anagrafica è di tipo 'Azienda'.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isAzienda()
|
|
||||||
{
|
|
||||||
return $this->isTipo('Azienda');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controlla se l'anagrafica è di tipo 'Azienda'.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isTipo($type)
|
|
||||||
{
|
|
||||||
return $this->tipi()->get()->search(function ($item, $key) use ($type) {
|
|
||||||
return $item->descrizione == $type;
|
|
||||||
}) !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce l'identificativo.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getIdAttribute()
|
|
||||||
{
|
|
||||||
return $this->idanagrafica;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPartitaIvaAttribute()
|
|
||||||
{
|
|
||||||
return $this->piva;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setPartitaIvaAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['piva'] = trim(strtoupper($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setNomeAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['nome'] = trim($value);
|
|
||||||
|
|
||||||
$this->fixRagioneSociale();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCognomeAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['cognome'] = trim($value);
|
|
||||||
|
|
||||||
$this->fixRagioneSociale();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCodiceFiscaleAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['codice_fiscale'] = trim(strtoupper($value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCodiceDestinatarioAttribute($value)
|
|
||||||
{
|
|
||||||
if ($this->tipo == 'Privato' || in_array($value, ['999999', '0000000']) || $this->sedeLegale->nazione->iso2 != 'IT') {
|
|
||||||
$codice_destinatario = '';
|
|
||||||
} else {
|
|
||||||
$codice_destinatario = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->attributes['codice_destinatario'] = trim(strtoupper($codice_destinatario));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tipi()
|
|
||||||
{
|
|
||||||
return $this->belongsToMany(TipoAnagrafica::class, 'an_tipianagrafiche_anagrafiche', 'idanagrafica', 'idtipoanagrafica');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function fatture()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Fattura::class, 'idanagrafica');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function nazione()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Nazione::class, 'id_nazione');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce la sede legale collegata.
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public function getSedeLegaleAttribute()
|
|
||||||
{
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metodi statici
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola il nuovo codice di anagrafica.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function getNextCodice()
|
|
||||||
{
|
|
||||||
// Recupero maschera per le anagrafiche
|
|
||||||
$maschera = setting('Formato codice anagrafica');
|
|
||||||
|
|
||||||
$ultimo = Generator::getPreviousFrom($maschera, 'an_anagrafiche', 'codice', [
|
|
||||||
"codice != ''",
|
|
||||||
'deleted_at IS NULL',
|
|
||||||
]);
|
|
||||||
$codice = Generator::generate($maschera, $ultimo);
|
|
||||||
|
|
||||||
return $codice;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attributi Eloquent
|
|
||||||
|
|
||||||
public function getModuleAttribute()
|
|
||||||
{
|
|
||||||
return 'Anagrafiche';
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function fixRagioneSociale()
|
|
||||||
{
|
|
||||||
if (!empty($this->cognome) || !empty($this->nome)) {
|
|
||||||
$this->ragione_sociale = $this->cognome.' '.$this->nome;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,213 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10;
|
|
||||||
|
|
||||||
use Common\Components\Row;
|
|
||||||
use Common\Document;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Modules\Articoli\Articolo as Original;
|
|
||||||
use UnexpectedValueException;
|
|
||||||
|
|
||||||
abstract class Article extends Row
|
|
||||||
{
|
|
||||||
protected $serialRowID = null;
|
|
||||||
protected $abilita_movimentazione = true;
|
|
||||||
protected $serialsList = null;
|
|
||||||
|
|
||||||
protected $qta_movimentazione = 0;
|
|
||||||
|
|
||||||
public static function build(Document $document, Original $articolo)
|
|
||||||
{
|
|
||||||
$model = parent::build($document, true);
|
|
||||||
|
|
||||||
$model->articolo()->associate($articolo);
|
|
||||||
|
|
||||||
$model->descrizione = $articolo->descrizione;
|
|
||||||
$model->abilita_serial = $articolo->abilita_serial;
|
|
||||||
$model->um = $articolo->um;
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract public function movimenta($qta);
|
|
||||||
|
|
||||||
abstract public function getDirection();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imposta i seriali collegati all'articolo.
|
|
||||||
*
|
|
||||||
* @param array $serials
|
|
||||||
*/
|
|
||||||
public function setSerialsAttribute($serials)
|
|
||||||
{
|
|
||||||
$serials = array_clean($serials);
|
|
||||||
|
|
||||||
database()->sync('mg_prodotti', [
|
|
||||||
'id_riga_'.$this->serialRowID => $this->id,
|
|
||||||
'dir' => $this->getDirection(),
|
|
||||||
'id_articolo' => $this->idarticolo,
|
|
||||||
], [
|
|
||||||
'serial' => $serials,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->serialsList = $serials;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rimuove i seriali collegati all'articolo.
|
|
||||||
*
|
|
||||||
* @param array $serials
|
|
||||||
*/
|
|
||||||
public function removeSerials($serials)
|
|
||||||
{
|
|
||||||
database()->detach('mg_prodotti', [
|
|
||||||
'id_riga_'.$this->serialRowID => $this->id,
|
|
||||||
'dir' => $this->getDirection(),
|
|
||||||
'id_articolo' => $this->idarticolo,
|
|
||||||
], [
|
|
||||||
'serial' => array_clean($serials),
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->serialsList = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce l'elenco dei seriali collegati all'articolo del documento.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getSerialsAttribute()
|
|
||||||
{
|
|
||||||
if (empty($this->abilita_serial)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($this->serialsList)) {
|
|
||||||
// Individuazione dei seriali
|
|
||||||
$results = database()->fetchArray('SELECT serial FROM mg_prodotti WHERE serial IS NOT NULL AND id_riga_'.$this->serialRowID.' = '.prepare($this->id));
|
|
||||||
|
|
||||||
$this->serialsList = array_column($results, 'serial');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->serialsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce il numero di seriali mancanti per il completamento dell'articolo.
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getMissingSerialsAttribute()
|
|
||||||
{
|
|
||||||
return $this->qta - count($this->serials);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modifica la quantità dell'articolo e movimenta automaticamente il magazzino.
|
|
||||||
*
|
|
||||||
* @param float $value
|
|
||||||
*/
|
|
||||||
public function setQtaAttribute($value)
|
|
||||||
{
|
|
||||||
if (!$this->cleanupSerials($value)) {
|
|
||||||
throw new UnexpectedValueException();
|
|
||||||
}
|
|
||||||
|
|
||||||
$diff = parent::setQtaAttribute($value);
|
|
||||||
|
|
||||||
if ($this->abilita_movimentazione) {
|
|
||||||
$this->qta_movimentazione += $diff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function articolo()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Original::class, 'idarticolo');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function movimentazione($value = true)
|
|
||||||
{
|
|
||||||
$this->abilita_movimentazione = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Salva l'articolo, eventualmente movimentandone il magazzino.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function save(array $options = [])
|
|
||||||
{
|
|
||||||
if (!empty($this->qta_movimentazione)) {
|
|
||||||
$this->movimenta($this->qta_movimentazione);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::save($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function boot()
|
|
||||||
{
|
|
||||||
parent::boot(true);
|
|
||||||
|
|
||||||
static::addGlobalScope('articles', function (Builder $builder) {
|
|
||||||
$builder->whereNotNull('idarticolo')->where('idarticolo', '<>', 0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function usedSerials()
|
|
||||||
{
|
|
||||||
if ($this->getDirection() == 'uscita') {
|
|
||||||
$results = database()->fetchArray("SELECT serial FROM mg_prodotti WHERE serial IN (SELECT DISTINCT serial FROM mg_prodotti WHERE dir = 'entrata') AND serial IS NOT NULL AND id_riga_".$this->serialRowID.' = '.prepare($this->id));
|
|
||||||
|
|
||||||
return array_column($results, 'serial');
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function cleanupSerials($new_qta)
|
|
||||||
{
|
|
||||||
// Se la nuova quantità è minore della precedente
|
|
||||||
if ($this->qta > $new_qta) {
|
|
||||||
$seriali_usati = $this->usedSerials();
|
|
||||||
$count_seriali_usati = count($seriali_usati);
|
|
||||||
|
|
||||||
// Controllo sulla possibilità di rimuovere i seriali (se non utilizzati da documenti di vendita)
|
|
||||||
if ($this->getDirection() == 'uscita' && $new_qta < $count_seriali_usati) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// Controllo sul numero di seriali effettivi da rimuovere
|
|
||||||
$seriali = $this->serials;
|
|
||||||
|
|
||||||
if ($new_qta < count($seriali)) {
|
|
||||||
$rimovibili = array_diff($seriali, $seriali_usati);
|
|
||||||
|
|
||||||
// Rimozione dei seriali aggiuntivi
|
|
||||||
$serials = array_slice($rimovibili, 0, $new_qta - $count_seriali_usati);
|
|
||||||
|
|
||||||
$this->serials = array_merge($seriali_usati, $serials);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function customInitCopiaIn($original)
|
|
||||||
{
|
|
||||||
$this->articolo()->associate($original->articolo);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function customBeforeDataCopiaIn($original)
|
|
||||||
{
|
|
||||||
$this->movimentazione(false);
|
|
||||||
|
|
||||||
parent::customBeforeDataCopiaIn($original);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function customAfterDataCopiaIn($original)
|
|
||||||
{
|
|
||||||
$this->movimentazione(true);
|
|
||||||
|
|
||||||
parent::customAfterDataCopiaIn($original);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10\Components;
|
|
||||||
|
|
||||||
use Modules\Articoli\Articolo as Original;
|
|
||||||
use Update\v2_4_10\Article;
|
|
||||||
use Update\v2_4_10\Fattura;
|
|
||||||
|
|
||||||
class Articolo extends Article
|
|
||||||
{
|
|
||||||
use RelationTrait;
|
|
||||||
|
|
||||||
protected $table = 'co_righe_documenti';
|
|
||||||
protected $serialRowID = 'documento';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea un nuovo articolo collegato ad una fattura.
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function build(Fattura $fattura, Original $articolo)
|
|
||||||
{
|
|
||||||
$model = parent::build($fattura, $articolo);
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function movimenta($qta)
|
|
||||||
{
|
|
||||||
// Se il documento è generato da un ddt o intervento allora **non** movimento il magazzino
|
|
||||||
if (!empty($this->idddt) || !empty($this->idintervento)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fattura = $this->fattura;
|
|
||||||
$tipo = $fattura->tipo;
|
|
||||||
|
|
||||||
$numero = $fattura->numero_esterno ?: $fattura->numero;
|
|
||||||
$data = $fattura->data;
|
|
||||||
|
|
||||||
$carico = ($tipo->dir == 'entrata') ? tr('Ripristino articolo da _TYPE_ _NUM_') : tr('Carico magazzino da _TYPE_ numero _NUM_');
|
|
||||||
$scarico = ($tipo->dir == 'entrata') ? tr('Scarico magazzino per _TYPE_ numero _NUM_') : tr('Rimozione articolo da _TYPE_ _NUM_');
|
|
||||||
|
|
||||||
$qta = ($tipo->dir == 'uscita') ? -$qta : $qta;
|
|
||||||
$movimento = ($qta < 0) ? $carico : $scarico;
|
|
||||||
|
|
||||||
$movimento = replace($movimento, [
|
|
||||||
'_TYPE_' => $tipo->descrizione,
|
|
||||||
'_NUM_' => $numero,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->articolo->movimenta(-$qta, $movimento, $data, false, [
|
|
||||||
'iddocumento' => $fattura->id,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDirection()
|
|
||||||
{
|
|
||||||
return $this->fattura->tipo->dir;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10\Components;
|
|
||||||
|
|
||||||
use Common\Components\Description;
|
|
||||||
use Update\v2_4_10\Fattura;
|
|
||||||
|
|
||||||
class Descrizione extends Description
|
|
||||||
{
|
|
||||||
use RelationTrait;
|
|
||||||
|
|
||||||
protected $table = 'co_righe_documenti';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea una nuova riga collegata ad una fattura.
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function build(Fattura $fattura)
|
|
||||||
{
|
|
||||||
$model = parent::build($fattura);
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,182 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10\Components;
|
|
||||||
|
|
||||||
use Modules\Ritenute\RitenutaAcconto;
|
|
||||||
use Modules\Rivalse\RivalsaINPS;
|
|
||||||
use Update\v2_4_10\Fattura;
|
|
||||||
|
|
||||||
trait RelationTrait
|
|
||||||
{
|
|
||||||
public function getParentID()
|
|
||||||
{
|
|
||||||
return 'iddocumento';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function parent()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Fattura::class, $this->getParentID());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function fattura()
|
|
||||||
{
|
|
||||||
return $this->parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getNettoAttribute()
|
|
||||||
{
|
|
||||||
$result = $this->totale - $this->ritenuta_acconto - $this->ritenuta_contributi;
|
|
||||||
|
|
||||||
if ($this->parent->split_payment) {
|
|
||||||
$result = $result - $this->iva;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce il totale (imponibile + iva + rivalsa_inps + iva_rivalsainps) dell'elemento.
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getTotaleAttribute()
|
|
||||||
{
|
|
||||||
return $this->imponibile_scontato + $this->iva + $this->rivalsa_inps + $this->iva_rivalsa_inps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRivalsaINPSAttribute()
|
|
||||||
{
|
|
||||||
return $this->imponibile_scontato / 100 * $this->rivalsa->percentuale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIvaRivalsaINPSAttribute()
|
|
||||||
{
|
|
||||||
return $this->rivalsa_inps / 100 * $this->aliquota->percentuale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRitenutaAccontoAttribute()
|
|
||||||
{
|
|
||||||
$result = $this->imponibile_scontato;
|
|
||||||
|
|
||||||
if ($this->calcolo_ritenuta_acconto == 'IMP+RIV') {
|
|
||||||
$result += $this->rivalsainps;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ritenuta = $this->ritenuta;
|
|
||||||
$result = $result * $ritenuta->percentuale_imponibile / 100;
|
|
||||||
|
|
||||||
return $result / 100 * $ritenuta->percentuale;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getRitenutaContributiAttribute()
|
|
||||||
{
|
|
||||||
if ($this->attributes['ritenuta_contributi']) {
|
|
||||||
$result = $this->imponibile_scontato;
|
|
||||||
$ritenuta = $this->parent->ritenutaContributi;
|
|
||||||
|
|
||||||
$result = $result * $ritenuta->percentuale_imponibile / 100;
|
|
||||||
|
|
||||||
return $result / 100 * $ritenuta->percentuale;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imposta l'identificatore della Rivalsa INPS.
|
|
||||||
*
|
|
||||||
* @param int $value
|
|
||||||
*/
|
|
||||||
public function setIdRivalsaINPSAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['idrivalsainps'] = $value;
|
|
||||||
$this->load('rivalsa');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imposta l'identificatore della Ritenuta d'Acconto.
|
|
||||||
*
|
|
||||||
* @param int $value
|
|
||||||
*/
|
|
||||||
public function setIdRitenutaAccontoAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['idritenutaacconto'] = $value;
|
|
||||||
$this->load('ritenuta');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIdContoAttribute()
|
|
||||||
{
|
|
||||||
return $this->idconto;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setIdContoAttribute($value)
|
|
||||||
{
|
|
||||||
$this->attributes['idconto'] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rivalsa()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(RivalsaINPS::class, 'idrivalsainps');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ritenuta()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(RitenutaAcconto::class, 'idritenutaacconto');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Salva la riga, impostando i campi dipendenti dai parametri singoli.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function save(array $options = [])
|
|
||||||
{
|
|
||||||
$this->fixRitenutaAcconto();
|
|
||||||
$this->fixRivalsaINPS();
|
|
||||||
|
|
||||||
return parent::save($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Effettua i conti per la Rivalsa INPS.
|
|
||||||
*/
|
|
||||||
protected function fixRivalsaINPS()
|
|
||||||
{
|
|
||||||
$this->attributes['rivalsainps'] = $this->rivalsa_inps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Effettua i conti per la Ritenuta d'Acconto, basandosi sul valore del campo calcolo_ritenuta_acconto.
|
|
||||||
*/
|
|
||||||
protected function fixRitenutaAcconto()
|
|
||||||
{
|
|
||||||
$this->attributes['ritenutaacconto'] = $this->ritenuta_acconto;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function evasione($diff)
|
|
||||||
{
|
|
||||||
parent::evasione($diff);
|
|
||||||
|
|
||||||
$database = database();
|
|
||||||
|
|
||||||
// Se c'è un collegamento ad un ddt, aggiorno la quantità evasa
|
|
||||||
if (!empty($this->idddt)) {
|
|
||||||
$database->query('UPDATE dt_righe_ddt SET qta_evasa = qta_evasa + '.$diff.' WHERE descrizione = '.prepare($this->descrizione).' AND idarticolo = '.prepare($this->idarticolo).' AND idddt = '.prepare($this->idddt).' AND idiva = '.prepare($this->idiva).' AND qta_evasa < qta LIMIT 1');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se c'è un collegamento ad un ordine, aggiorno la quantità evasa
|
|
||||||
elseif (!empty($this->idordine)) {
|
|
||||||
$database->query('UPDATE or_righe_ordini SET qta_evasa = qta_evasa + '.$diff.' WHERE descrizione = '.prepare($this->descrizione).' AND idarticolo = '.prepare($this->idarticolo).' AND idordine = '.prepare($this->idordine).' AND idiva = '.prepare($this->idiva).' AND qta_evasa < qta LIMIT 1');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se c'è un collegamento ad un preventivo, aggiorno la quantità evasa
|
|
||||||
elseif (!empty($this->idpreventivo)) {
|
|
||||||
$database->query('UPDATE co_righe_preventivi SET qta_evasa = qta_evasa + '.$diff.' WHERE descrizione = '.prepare($this->descrizione).' AND idarticolo = '.prepare($this->idarticolo).' AND idpreventivo = '.prepare($this->idpreventivo).' AND idiva = '.prepare($this->idiva).' AND qta_evasa < qta LIMIT 1');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se c'è un collegamento ad un contratto, aggiorno la quantità evasa
|
|
||||||
elseif (!empty($this->idcontratto)) {
|
|
||||||
$database->query('UPDATE co_righe_contratti SET qta_evasa = qta_evasa + '.$diff.' WHERE descrizione = '.prepare($this->descrizione).' AND idarticolo = '.prepare($this->idarticolo).' AND idcontratto = '.prepare($this->idcontratto).' AND idiva = '.prepare($this->idiva).' AND qta_evasa < qta LIMIT 1');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10\Components;
|
|
||||||
|
|
||||||
use Common\Components\Row;
|
|
||||||
use Update\v2_4_10\Fattura;
|
|
||||||
|
|
||||||
class Riga extends Row
|
|
||||||
{
|
|
||||||
use RelationTrait;
|
|
||||||
|
|
||||||
protected $table = 'co_righe_documenti';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea una nuova riga collegata ad una fattura.
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function build(Fattura $fattura)
|
|
||||||
{
|
|
||||||
$model = parent::build($fattura);
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10\Components;
|
|
||||||
|
|
||||||
use Common\Components\Discount;
|
|
||||||
use Update\v2_4_10\Fattura;
|
|
||||||
|
|
||||||
class Sconto extends Discount
|
|
||||||
{
|
|
||||||
use RelationTrait;
|
|
||||||
|
|
||||||
protected $table = 'co_righe_documenti';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea un nuovo sconto collegato ad una fattura.
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function build(Fattura $fattura)
|
|
||||||
{
|
|
||||||
$model = parent::build($fattura);
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,600 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10;
|
|
||||||
|
|
||||||
use Auth;
|
|
||||||
use Common\Document;
|
|
||||||
use Modules\Pagamenti\Pagamento;
|
|
||||||
use Modules\RitenuteContributi\RitenutaContributi;
|
|
||||||
use Plugins\ExportFE\FatturaElettronica;
|
|
||||||
use Traits\RecordTrait;
|
|
||||||
use Util\Generator;
|
|
||||||
|
|
||||||
class Fattura extends Document
|
|
||||||
{
|
|
||||||
use RecordTrait;
|
|
||||||
|
|
||||||
protected $table = 'co_documenti';
|
|
||||||
|
|
||||||
protected $casts = [
|
|
||||||
'bollo' => 'float',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea una nuova fattura.
|
|
||||||
*
|
|
||||||
* @param string $data
|
|
||||||
* @param int $id_segment
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public static function build(Anagrafica $anagrafica, TipoFattura $tipo_documento, $data, $id_segment)
|
|
||||||
{
|
|
||||||
$model = parent::build();
|
|
||||||
|
|
||||||
$user = Auth::user();
|
|
||||||
|
|
||||||
$stato_documento = Stato::where('descrizione', 'Bozza')->first();
|
|
||||||
|
|
||||||
$id_anagrafica = $anagrafica->id;
|
|
||||||
$direzione = $tipo_documento->dir;
|
|
||||||
|
|
||||||
$database = database();
|
|
||||||
|
|
||||||
if ($direzione == 'entrata') {
|
|
||||||
$id_conto = setting('Conto predefinito fatture di vendita');
|
|
||||||
$conto = 'vendite';
|
|
||||||
} else {
|
|
||||||
$id_conto = setting('Conto predefinito fatture di acquisto');
|
|
||||||
$conto = 'acquisti';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tipo di pagamento e banca predefinite dall'anagrafica
|
|
||||||
$id_pagamento = $database->fetchOne('SELECT id FROM co_pagamenti WHERE id = :id_pagamento', [
|
|
||||||
':id_pagamento' => $anagrafica['idpagamento_'.$conto],
|
|
||||||
])['id'];
|
|
||||||
$id_banca = $anagrafica['idbanca_'.$conto];
|
|
||||||
|
|
||||||
$split_payment = $anagrafica->split_payment;
|
|
||||||
|
|
||||||
// Se la fattura è di vendita e non è stato associato un pagamento predefinito al cliente leggo il pagamento dalle impostazioni
|
|
||||||
if ($direzione == 'entrata' && empty($id_pagamento)) {
|
|
||||||
$id_pagamento = setting('Tipo di pagamento predefinito');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se non è impostata la banca dell'anagrafica, uso quella del pagamento.
|
|
||||||
if (empty($id_banca)) {
|
|
||||||
$id_banca = $database->fetchOne('SELECT id FROM co_banche WHERE id_pianodeiconti3 = (SELECT idconto_'.$conto.' FROM co_pagamenti WHERE id = :id_pagamento)', [
|
|
||||||
':id_pagamento' => $id_pagamento,
|
|
||||||
])['id'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$id_sede = $anagrafica->idsede_fatturazione;
|
|
||||||
|
|
||||||
$model->anagrafica()->associate($anagrafica);
|
|
||||||
$model->tipo()->associate($tipo_documento);
|
|
||||||
$model->stato()->associate($stato_documento);
|
|
||||||
|
|
||||||
$model->save();
|
|
||||||
|
|
||||||
// Salvataggio delle informazioni
|
|
||||||
$model->data = $data;
|
|
||||||
$model->data_registrazione = $data;
|
|
||||||
$model->data_competenza = $data;
|
|
||||||
$model->id_segment = $id_segment;
|
|
||||||
|
|
||||||
$model->idconto = $id_conto;
|
|
||||||
|
|
||||||
// Imposto, come sede aziendale, la prima sede disponibile come utente
|
|
||||||
if ($direzione == 'entrata') {
|
|
||||||
$model->idsede_destinazione = $user->sedi[0];
|
|
||||||
} else {
|
|
||||||
$model->idsede_partenza = $user->sedi[0];
|
|
||||||
}
|
|
||||||
$model->addebita_bollo = setting('Addebita marca da bollo al cliente');
|
|
||||||
|
|
||||||
$id_ritenuta_contributi = ($tipo_documento->dir == 'entrata') ? setting('Ritenuta contributi') : null;
|
|
||||||
$model->id_ritenuta_contributi = $id_ritenuta_contributi ?: null;
|
|
||||||
|
|
||||||
if (!empty($id_pagamento)) {
|
|
||||||
$model->idpagamento = $id_pagamento;
|
|
||||||
}
|
|
||||||
if (!empty($id_banca)) {
|
|
||||||
$model->idbanca = $id_banca;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($split_payment)) {
|
|
||||||
$model->split_payment = $split_payment;
|
|
||||||
}
|
|
||||||
|
|
||||||
$model->save();
|
|
||||||
|
|
||||||
return $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imposta il sezionale relativo alla fattura e calcola il relativo numero.
|
|
||||||
* **Attenzione**: la data deve inserita prima!
|
|
||||||
*
|
|
||||||
* @param int $value
|
|
||||||
*/
|
|
||||||
public function setIdSegmentAttribute($value)
|
|
||||||
{
|
|
||||||
$previous = $this->id_segment;
|
|
||||||
|
|
||||||
$this->attributes['id_segment'] = $value;
|
|
||||||
|
|
||||||
// Calcolo dei numeri fattura
|
|
||||||
if ($value != $previous) {
|
|
||||||
$direzione = $this->tipo->dir;
|
|
||||||
$data = $this->data;
|
|
||||||
|
|
||||||
$this->numero = static::getNextNumero($data, $direzione, $value);
|
|
||||||
$this->numero_esterno = static::getNextNumeroSecondario($data, $direzione, $value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce il nome del modulo a cui l'oggetto è collegato.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getModuleAttribute()
|
|
||||||
{
|
|
||||||
return $this->direzione == 'entrata' ? 'Fatture di vendita' : 'Fatture di acquisto';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDirezioneAttribute()
|
|
||||||
{
|
|
||||||
return $this->tipo->dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcoli
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola il netto a pagare della fattura.
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getNettoAttribute()
|
|
||||||
{
|
|
||||||
return $this->calcola('netto');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola la rivalsa INPS totale della fattura.
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getRivalsaINPSAttribute()
|
|
||||||
{
|
|
||||||
return $this->calcola('rivalsa_inps');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola l'IVA totale della fattura.
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getIvaAttribute()
|
|
||||||
{
|
|
||||||
return $this->calcola('iva', 'iva_rivalsa_inps');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola l'iva della rivalsa INPS totale della fattura.
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getIvaRivalsaINPSAttribute()
|
|
||||||
{
|
|
||||||
return $this->calcola('iva_rivalsa_inps');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola la ritenuta d'acconto totale della fattura.
|
|
||||||
*
|
|
||||||
* @return float
|
|
||||||
*/
|
|
||||||
public function getRitenutaAccontoAttribute()
|
|
||||||
{
|
|
||||||
return $this->calcola('ritenuta_acconto');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotaleRitenutaContributiAttribute()
|
|
||||||
{
|
|
||||||
return $this->calcola('ritenuta_contributi');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Relazioni Eloquent
|
|
||||||
|
|
||||||
public function anagrafica()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Anagrafica::class, 'idanagrafica');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tipo()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TipoFattura::class, 'idtipodocumento');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pagamento()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Pagamento::class, 'idpagamento');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function stato()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Stato::class, 'idstatodocumento');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function statoFE()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(StatoFE::class, 'codice_stato_fe');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function articoli()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Components\Articolo::class, 'iddocumento');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function righe()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Components\Riga::class, 'iddocumento');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sconti()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Components\Sconto::class, 'iddocumento');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function descrizioni()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Components\Descrizione::class, 'iddocumento');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ritenutaContributi()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(RitenutaContributi::class, 'id_ritenuta_contributi');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function rigaBollo()
|
|
||||||
{
|
|
||||||
return $this->hasOne(Components\Riga::class, 'iddocumento')->where('id', $this->id_riga_bollo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metodi generali
|
|
||||||
|
|
||||||
public function getXML()
|
|
||||||
{
|
|
||||||
if (empty($this->progressivo_invio) && $this->module == 'Fatture di acquisto') {
|
|
||||||
$fe = new FatturaElettronica($this->id);
|
|
||||||
|
|
||||||
return $fe->toXML();
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = $this->uploads()->where('name', 'Fattura Elettronica')->first();
|
|
||||||
|
|
||||||
return file_get_contents($file->filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isFE()
|
|
||||||
{
|
|
||||||
$file = $this->uploads()->where('name', 'Fattura Elettronica')->first();
|
|
||||||
|
|
||||||
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 = -$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 $scadenza
|
|
||||||
* @param bool $is_pagato
|
|
||||||
* @param string $type
|
|
||||||
*/
|
|
||||||
public static function registraScadenza(Fattura $fattura, $importo, $scadenza, $is_pagato, $type = 'fattura')
|
|
||||||
{
|
|
||||||
//Calcolo la descrizione
|
|
||||||
$descrizione = database()->fetchOne("SELECT CONCAT(co_tipidocumento.descrizione, CONCAT(' numero ', IF(numero_esterno!='', numero_esterno, numero))) AS descrizione FROM co_documenti INNER JOIN co_tipidocumento ON co_documenti.idtipodocumento=co_tipidocumento.id WHERE co_documenti.id='".$fattura->id."'")['descrizione'];
|
|
||||||
|
|
||||||
database()->insert('co_scadenziario', [
|
|
||||||
'iddocumento' => $fattura->id,
|
|
||||||
'data_emissione' => $fattura->data,
|
|
||||||
'scadenza' => $scadenza,
|
|
||||||
'da_pagare' => $importo,
|
|
||||||
'tipo' => $type,
|
|
||||||
'pagato' => $is_pagato ? $importo : 0,
|
|
||||||
'data_pagamento' => $is_pagato ? $scadenza : null,
|
|
||||||
'descrizione' => $descrizione,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registra le scadenze della fattura.
|
|
||||||
*
|
|
||||||
* @param bool $is_pagato
|
|
||||||
* @param bool $ignora_fe
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
if ($direzione == 'uscita' && $ritenuta_acconto > 0) {
|
|
||||||
$data = $this->data;
|
|
||||||
$scadenza = date('Y-m', strtotime($data.' +1 month')).'-15';
|
|
||||||
$importo = -$ritenuta_acconto;
|
|
||||||
|
|
||||||
self::registraScadenza($this, $importo, $scadenza, $is_pagato, 'ritenutaacconto');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Elimina le scadenze della fattura.
|
|
||||||
*/
|
|
||||||
public function rimuoviScadenze()
|
|
||||||
{
|
|
||||||
database()->delete('co_scadenziario', ['iddocumento' => $this->id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Salva la fattura, impostando i campi dipendenti dai singoli parametri.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function save(array $options = [])
|
|
||||||
{
|
|
||||||
// Fix dei campi statici
|
|
||||||
$this->manageRigaMarcaDaBollo();
|
|
||||||
|
|
||||||
$this->attributes['ritenutaacconto'] = $this->ritenuta_acconto;
|
|
||||||
$this->attributes['iva_rivalsainps'] = $this->iva_rivalsa_inps;
|
|
||||||
$this->attributes['rivalsainps'] = $this->rivalsa_inps;
|
|
||||||
$this->attributes['ritenutaacconto'] = $this->ritenuta_acconto;
|
|
||||||
|
|
||||||
return parent::save($options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce l'elenco delle note di credito collegate.
|
|
||||||
*
|
|
||||||
* @return iterable
|
|
||||||
*/
|
|
||||||
public function getNoteDiAccredito()
|
|
||||||
{
|
|
||||||
return self::where('ref_documento', $this->id)->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce l'elenco delle note di credito collegate.
|
|
||||||
*
|
|
||||||
* @return self
|
|
||||||
*/
|
|
||||||
public function getFatturaOriginale()
|
|
||||||
{
|
|
||||||
return self::find($this->ref_documento);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controlla se la fattura è una nota di credito.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isNota()
|
|
||||||
{
|
|
||||||
return $this->tipo->reversed == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Metodi statici
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola il nuovo numero di fattura.
|
|
||||||
*
|
|
||||||
* @param string $data
|
|
||||||
* @param string $direzione
|
|
||||||
* @param int $id_segment
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function getNextNumero($data, $direzione, $id_segment)
|
|
||||||
{
|
|
||||||
if ($direzione == 'entrata') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recupero maschera per questo segmento
|
|
||||||
$maschera = Generator::getMaschera($id_segment);
|
|
||||||
|
|
||||||
$ultimo = Generator::getPreviousFrom($maschera, 'co_documenti', 'numero', [
|
|
||||||
'YEAR(data) = '.prepare(date('Y', strtotime($data))),
|
|
||||||
'id_segment = '.prepare($id_segment),
|
|
||||||
]);
|
|
||||||
$numero = Generator::generate($maschera, $ultimo, 1, Generator::dateToPattern($data));
|
|
||||||
|
|
||||||
return $numero;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcola il nuovo numero secondario di fattura.
|
|
||||||
*
|
|
||||||
* @param string $data
|
|
||||||
* @param string $direzione
|
|
||||||
* @param int $id_segment
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function getNextNumeroSecondario($data, $direzione, $id_segment)
|
|
||||||
{
|
|
||||||
if ($direzione == 'uscita') {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recupero maschera per questo segmento
|
|
||||||
$maschera = Generator::getMaschera($id_segment);
|
|
||||||
|
|
||||||
$ultimo = Generator::getPreviousFrom($maschera, 'co_documenti', 'numero_esterno', [
|
|
||||||
'YEAR(data) = '.prepare(date('Y', strtotime($data))),
|
|
||||||
'id_segment = '.prepare($id_segment),
|
|
||||||
]);
|
|
||||||
$numero = Generator::generate($maschera, $ultimo, 1, Generator::dateToPattern($data));
|
|
||||||
|
|
||||||
return $numero;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce i dati bancari in base al pagamento.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function getBanca()
|
|
||||||
{
|
|
||||||
$result = [];
|
|
||||||
$riba = database()->fetchOne('SELECT riba FROM co_pagamenti WHERE id ='.prepare($this->idpagamento));
|
|
||||||
|
|
||||||
if ($riba['riba'] == 1) {
|
|
||||||
$result = database()->fetchOne('SELECT codiceiban, appoggiobancario, bic FROM an_anagrafiche WHERE idanagrafica ='.prepare($this->idanagrafica));
|
|
||||||
} else {
|
|
||||||
$result = database()->fetchOne('SELECT iban AS codiceiban, nome AS appoggiobancario, bic FROM co_banche WHERE id='.prepare($this->idbanca));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_vendita = $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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opzioni di riferimento
|
|
||||||
|
|
||||||
public function getReferenceName()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getReferenceNumber()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getReferenceDate()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getReferenceRagioneSociale()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getReference()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10;
|
|
||||||
|
|
||||||
use Common\Model;
|
|
||||||
|
|
||||||
class TipoAnagrafica extends Model
|
|
||||||
{
|
|
||||||
protected $table = 'an_tipianagrafiche';
|
|
||||||
protected $primaryKey = 'idtipoanagrafica';
|
|
||||||
|
|
||||||
protected $appends = [
|
|
||||||
'id',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $hidden = [
|
|
||||||
'idtipoanagrafica',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restituisce l'identificativo.
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function getIdAttribute()
|
|
||||||
{
|
|
||||||
return $this->idtipoanagrafica;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function anagrafiche()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Anagrafica::class, 'an_tipianagrafiche_anagrafiche', 'idtipoanagrafica', 'idanagrafica');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Update\v2_4_10;
|
|
||||||
|
|
||||||
use Common\Model;
|
|
||||||
|
|
||||||
class TipoFattura extends Model
|
|
||||||
{
|
|
||||||
protected $table = 'co_tipidocumento';
|
|
||||||
|
|
||||||
public function fatture()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Fattura::class, 'idtipodocumento');
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue