Miglioramenti importazione FE

This commit is contained in:
Thomas Zilio 2018-09-25 11:55:52 +02:00
parent e91064eb38
commit 8cd6ce98a2
15 changed files with 319 additions and 67 deletions

View File

@ -43,7 +43,16 @@ function sum($first, $second = null, $decimals = 4)
return floatval($result);
}
function aggiorna_sconto($tables, $fields, $id_record, $options = [])
/**
* Calcola lo sconto globale per i documenti e lo aggiorna di conseguenza.
* Attenzione: eseguire la funzione dopo l'inserimento e la modifica di tutte le righe del documento.
*
* @param array $tables
* @param array $fields
* @param int $id_record
* @param array $options
*/
function aggiorna_sconto(array $tables, array $fields, $id_record, array $options = [])
{
$dbo = database();
@ -60,6 +69,8 @@ function aggiorna_sconto($tables, $fields, $id_record, $options = [])
$iva = 0;
if (!empty($sconto[0]['sconto_globale'])) {
// Commit: 2c7f69867accb4f12a0c7cfd320714bb98e31a67
// L'aliquota IVA viene calcolata in percentuale sull'imponibile e l'iva effettiva delle righe del documento.
if ($sconto[0]['tipo_sconto_globale'] == 'PRC') {
$rs = $dbo->fetchArray('SELECT SUM(subtotale - sconto) AS imponibile, SUM(iva) AS iva FROM (SELECT '.$tables['row'].'.subtotale, '.$tables['row'].'.sconto, '.$tables['row'].'.iva FROM '.$tables['row'].' WHERE '.$fields['row'].'='.prepare($id_record).') AS t');
$subtotale = $rs[0]['imponibile'];
@ -85,7 +96,7 @@ function aggiorna_sconto($tables, $fields, $id_record, $options = [])
'subtotale' => $subtotale,
'qta' => 1,
'idiva' => $idiva,
'desc_iva' => $rsi[0]['descrizione'],
//'desc_iva' => $rsi[0]['descrizione'],
'iva' => -$iva,
'sconto_globale' => 1,
'order' => orderValue($tables['row'], $fields['row'], $id_record),

View File

@ -0,0 +1,38 @@
<?php
namespace Modules\Fatture;
use Illuminate\Database\Eloquent\Model;
use Modules\Articoli\Articolo as Original;
use Traits\ArticleTrait;
class Articolo extends Model
{
use ArticleTrait;
protected $table = 'co_righe_documenti';
public function __construct(Fattura $fattura, Original $articolo, array $attributes = array())
{
parent::__construct($attributes);
$this->fattura()->associate($fattura);
$this->articolo()->associate($articolo);
// Salvataggio delle informazioni
$this->descrizione = isset($attributes['descrizione']) ? $attributes['descrizione'] : $articolo->descrizione;
$this->abilita_serial = $articolo->abilita_serial;
$this->save();
}
public function articolo()
{
return $this->belongsTo(Original::class, 'idarticolo');
}
public function fattura()
{
return $this->belongsTo(Fattura::class, 'iddocumento');
}
}

View File

@ -329,4 +329,16 @@ class Fattura extends Model
{
return $this->hasMany(Riga::class, 'iddocumento');
}
public function updateSconto()
{
// Aggiornamento sconto
aggiorna_sconto([
'parent' => 'co_documenti',
'row' => 'co_righe_documenti',
], [
'parent' => 'id',
'row' => 'iddocumento',
], $this->id);
}
}

View File

@ -3,18 +3,24 @@
namespace Modules\Fatture;
use Illuminate\Database\Eloquent\Model;
use Traits\RowTrait;
class Riga extends Model
{
use RowTrait;
protected $table = 'co_righe_documenti';
public function __construct(Fattura $fattura, array $attributes = array())
{
parent::__construct($attributes);
$this->fattura()->associate($fattura);
$this->save();
}
public function fattura()
{
return $this->belongsTo(Fattura::class, 'iddocumento');
}
public function getImponibile()
{
return $this->subtotale - $this->sconto;
}
}

View File

@ -531,6 +531,8 @@ switch (post('op')) {
$articolo->setSconto(post('sconto'), post('tipo_sconto'));
$articolo->setIVA(post('idiva'));
$articolo->save();
// Aggiorno l'automezzo dell'intervento
$dbo->query('UPDATE in_interventi SET idautomezzo='.prepare(post('idautomezzo')).' WHERE id='.prepare($id_record).' '.Modules::getAdditionalsQuery($id_module));

View File

@ -118,7 +118,7 @@ class Articolo extends Model
database()->sync('mg_prodotti', [
'id_riga_intervento' => $this->id,
'dir' => 'entrata',
'id_articolo' => $this->idintervento,
'id_articolo' => $this->idarticolo,
], [
'serial' => $serials,
]);

View File

@ -308,15 +308,16 @@ class FatturaElettronica
];
// Sconto globale
$documento['sconto_globale'] = floatval($documento['sconto_globale']);
if (!empty($documento['sconto_globale'])) {
$sconto = [
'Tipo' => $documento['sconto_globale'] > 0 ? 'SC' : 'MG',
];
if ($riga['tipo_sconto_globale'] == 'PRC') {
$sconto['Percentuale'] = $riga['sconto_globale'];
if ($documento['tipo_sconto_globale'] == 'PRC') {
$sconto['Percentuale'] = $documento['sconto_globale'];
} else {
$sconto['Importo'] = $riga['sconto_globale'];
$sconto['Importo'] = $documento['sconto_globale'];
}
$result['ScontoMaggiorazione'] = $sconto;
@ -386,7 +387,7 @@ class FatturaElettronica
$result = [];
// Righe del documento
$righe_documento = $database->fetchArray('SELECT * FROM `co_righe_documenti` WHERE `iddocumento` = '.prepare($documento['id']));
$righe_documento = $database->fetchArray('SELECT * FROM `co_righe_documenti` WHERE `sconto_globale` = 0 AND `iddocumento` = '.prepare($documento['id']));
foreach ($righe_documento as $numero => $riga) {
$prezzo_unitario = $riga['subtotale'] / $riga['qta'];
$prezzo_totale = $riga['subtotale'] - $riga['sconto'];
@ -402,15 +403,16 @@ class FatturaElettronica
];
// Sconto
if (!empty($riga['sconto'])) {
$riga['sconto_unitario'] = floatval($riga['sconto_unitario']);
if (!empty($riga['sconto_unitario'])) {
$sconto = [
'Tipo' => $riga['sconto'] > 0 ? 'SC' : 'MG',
'Tipo' => $riga['sconto_unitario'] > 0 ? 'SC' : 'MG',
];
if ($riga['tipo_sconto'] == 'PRC') {
$sconto['Percentuale'] = $riga['sconto'];
$sconto['Percentuale'] = $riga['sconto_unitario'];
} else {
$sconto['Importo'] = $riga['sconto'];
$sconto['Importo'] = $riga['sconto_unitario'];
}
$dettaglio['ScontoMaggiorazione'] = $sconto;

View File

@ -2,6 +2,8 @@
include_once __DIR__.'/../../core.php';
$directory = Uploads::getDirectory($id_module);
switch (filter('op')) {
case 'save':
$id = Uploads::getFakeID();
@ -12,11 +14,20 @@ switch (filter('op')) {
'id_record' => $id,
]);
try {
$xml = file_get_contents(DOCROOT.'/'.$directory.'/'.$filename);
$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment'));
echo json_encode([
'id' => $id,
'filename' => $filename,
'id_segment' => post('id_segment'),
]);
} catch (UnexpectedValueException $e) {
echo json_encode([
'already' => 1
]);
}
break;
@ -24,14 +35,13 @@ switch (filter('op')) {
$id = post('id');
$filename = post('filename');
$directory = Uploads::getDirectory($id_module);
$xml = file_get_contents(DOCROOT.'/'.$directory.'/'.$filename);
$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml);
$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment'));
$id_record = $fattura_pa->saveFattura(post('id_segment'), post('articoli'));
$id_record = $fattura_pa->saveFattura();
$fattura_pa->saveRighe(post('articoli'));
$fattura_pa->saveRighe(post('articoli'), post('iva'));
$fattura_pa->getFattura()->updateSconto();
$fattura_pa->saveAllegati($directory);

View File

@ -23,7 +23,15 @@ echo '
success: function(data){
data = JSON.parse(data);
launch_modal("'.tr('Righe fattura').'", globals.rootdir + "/plugins/importPA/rows.php?id_module=" + globals.id_module + "&id_plugin=" + '.$id_plugin.' + "&id=" + data.id + "&filename=" + data.filename + "&id_segment" + data.id_segment)
if (!data.already) {
launch_modal("'.tr('Righe fattura').'", globals.rootdir + "/plugins/importPA/rows.php?id_module=" + globals.id_module + "&id_plugin=" + '.$id_plugin.' + "&id=" + data.id + "&filename=" + data.filename + "&id_segment=" + data.id_segment)
} else {
swal({
title: "'.tr('Fattura già importata!').'",
type: "info",
})
}
},
error: function(data) {
alert("'.tr('Errore').': " + data);

View File

@ -5,7 +5,7 @@ include_once __DIR__.'/../../core.php';
$directory = Uploads::getDirectory($id_module);
$xml = file_get_contents(DOCROOT.'/'.$directory.'/'.get('filename'));
$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml);
$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment'));
$righe = $fattura_pa->getRighe();
@ -25,18 +25,30 @@ if (!empty($righe)) {
<tr>
<th width="10%">'.tr('Riga').'</th>
<th width="40%">'.tr('Descrizione').'</th>
<th width="15%">'.tr('Quantità').'</th>
<th width="15%">'.tr('Prezzo unitario').'</th>
<th width="10%">'.tr('Quantità').'</th>
<th width="10%">'.tr('Prezzo unitario').'</th>
<th width="10%">'.tr('Iva associata').'*</th>
<th width="20%">'.tr('Articolo associato').'</th>
</tr>';
foreach ($righe as $key => $riga) {
$query = 'SELECT id, IF(codice IS NULL, descrizione, CONCAT(codice, " - ", descrizione)) AS descrizione FROM co_iva WHERE percentuale = '.prepare($riga['AliquotaIVA']);
if (!empty($riga['Natura'])) {
$query .= ' AND codice_natura_fe = '.prepare($riga['Natura']);
}
$query .= ' ORDER BY descrizione ASC';
echo '
<tr>
<td>'.$key.'</td>
<td>'.$riga['Descrizione'].'</td>
<td>'.$riga['Quantita'].' '.$riga['UnitaMisura'].'</td>
<td>'.$riga['PrezzoUnitario'].'</td>
<td>
{[ "type": "select", "name": "iva['.$key.']", "values": "query='.str_replace('"', '\"', $query).'", "required": 1 ]}
</td>
<td>
{[ "type": "select", "name": "articoli['.$key.']", "ajax-source": "articoli" ]}
</td>

View File

@ -3,6 +3,9 @@
namespace Plugins\ImportPA;
use Modules\Fatture\Fattura;
use Modules\Fatture\Riga;
use Modules\Fatture\Articolo;
use Modules\Articoli\Articolo as ArticoloOriginale;
use Modules\Fatture\Stato as StatoFattura;
use Modules\Fatture\Tipo as TipoFattura;
use Modules\Anagrafiche\Anagrafica;
@ -23,19 +26,31 @@ class FatturaElettronica
/** @var Fattura Fattura collegata */
protected $fattura = null;
protected $id_sezionale = null;
public function __construct($content)
public function __construct($content, $id_sezionale)
{
$xml = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$json = json_encode($xml);
$array = json_decode($json, true);
$this->xml = $array;
}
$this->id_sezionale = $id_sezionale;
public function getFattura()
{
return $this->fattura;
// Individuazione fattura pre-esistente
$dati_generali = $this->getBody()['DatiGenerali']['DatiGeneraliDocumento'];
$data = $dati_generali['Data'];
$numero = $dati_generali['Numero'];
$fattura = Fattura::where([
'id_segment' => $id_sezionale,
'data' => $data,
'numero' => $numero,
])->first();
if (!empty($fattura)) {
throw new \UnexpectedValueException();
}
}
public function getHeader()
@ -132,28 +147,70 @@ class FatturaElettronica
return $anagrafica->id;
}
public function saveRighe($articoli)
{
$righe = $this->getRighe();
}
public function getRighe()
{
return $this->getBody()['DatiBeniServizi']['DettaglioLinee'];
$result = $this->getBody()['DatiBeniServizi']['DettaglioLinee'];
if (!isset($result[0])) {
$result = [$result];
}
public static function existsFattura($id_anagrafica, $data, $numero, $id_tipo)
return $result;
}
public function saveRighe($articoli, $iva)
{
return database()->fetchOne('SELECT `id` FROM `co_documenti` WHERE idanagrafica = '.prepare($id_anagrafica) .' AND idtipodocumento = '.prepare($id_tipo).' AND data = '.prepare($data).' AND numero = '.prepare($numero));
$righe = $this->getRighe();
foreach ($righe as $key => $riga) {
$articolo = ArticoloOriginale::find($articoli[$key]);
if (!empty($articolo)) {
$obj = new Articolo($this->getFattura(), $articolo);
} else {
$obj = new Riga($this->getFattura());
}
$obj->descrizione = $riga['Descrizione'];
$obj->setSubtotale($riga['PrezzoUnitario'], $riga['Quantita']);
/*
$obj->qta = $riga['Quantita'];
$obj->prezzo = $riga['PrezzoUnitario'];
*/
$obj->um = $riga['UnitaMisura'];
$sconto =$riga['ScontoMaggiorazione'];
if (!empty($sconto)) {
$tipo = !empty($sconto['Percentuale']) ? 'PRC' : 'EUR';
$unitario = $sconto['Percentuale'] ?: $sconto['Importo'];
$unitario = ($sconto['Tipo'] == 'SC') ? $unitario : -$unitario;
$obj->sconto_unitario = $unitario;
$obj->tipo_sconto = $tipo;
$obj->sconto = $obj->sconto;
}
$obj->setIVA($iva[$key]);
$obj->save();
}
}
public function getAllegati()
{
$result = $this->getBody()['Allegati'];
if (!isset($result[0])) {
$result = [$result];
}
return $result;
}
public function saveAllegati($directory)
{
$allegati = $this->getBody()['Allegati'];
if (!isset($allegati[0])) {
$allegati = [$allegati];
}
$allegati = $this->getAllegati();
foreach ($allegati as $allegato) {
$content = base64_decode($allegato['Attachment']);
@ -170,13 +227,17 @@ class FatturaElettronica
}
}
public function getFattura()
{
return $this->fattura;
}
/**
* Registra la fattura elettronica come fattura del gestionale.
*
* @param int $id_segment
* @return int
*/
public function saveFattura($id_segment)
public function saveFattura()
{
$id_anagrafica = static::createAnagrafica($this->getHeader()['CedentePrestatore']);
@ -184,31 +245,35 @@ class FatturaElettronica
$data = $dati_generali['Data'];
$numero = $dati_generali['Numero'];
$tipo = empty($this->getBody()['DatiGenerali']['DatiTrasporto']) ? TipoFattura::where('descrizione', 'Fattura immediata di acquisto') : TipoFattura::where('descrizione', 'Fattura accompagnatoria di acquisto');
$id_tipo = $tipo->first()->id;
$result = self::existsFattura($id_anagrafica, $data, $numero, $id_tipo);
// Fattura già inserita
if (!empty($result)) {
$this->fattura = Fattura::find($result['id']);
return $result['id'];
}
$tipo = empty($this->getBody()['DatiGenerali']['DatiTrasporto']) ? 'Fattura immediata di acquisto' : 'Fattura accompagnatoria di acquisto';
$id_tipo = TipoFattura::where('descrizione', $tipo)->first()->id;
$fattura = Fattura::create([
'idanagrafica' => $id_anagrafica,
'data' => $data,
'id_segment' => $id_segment,
'id_segment' => $this->id_sezionale,
'tipo' => $id_tipo,
]);
$this->fattura = $fattura;
$fattura->numero = $numero;
$stato_documento = StatoFattura::where('descrizione', 'Emessa')->first();
$fattura->stato()->associate($stato_documento);
$fattura->save();
$this->fattura = $fattura;
// Sconto globale
$sconto = $dati_generali['ScontoMaggiorazione'];
if (!empty($sconto)) {
$tipo = !empty($sconto['Percentuale']) ? 'PRC' : 'EUR';
$unitario = $sconto['Percentuale'] ?: $sconto['Importo'];
$unitario = ($sconto['Tipo'] == 'SC') ? $unitario : -$unitario;
$fattura->sconto_globale = $unitario;
$fattura->tipo_sconto_globale = $tipo;
}
$fattura->save();
return $fattura->id;
}

View File

@ -377,12 +377,10 @@ class App
$id_parent = filter('id_parent');
$id_module = Modules::getCurrent()['id'];
$id_plugin = Plugins::getCurrent()['id'];
$segment = $_SESSION['module_'.$id_module]['id_segment'];
$user = Auth::user();
$segment = !empty($_SESSION['module_'.$id_module]['id_segment']);
// Elenco delle sostituzioni
$replace = [
// Identificatori

View File

@ -0,0 +1,23 @@
<?php
namespace Traits;
use App;
trait ArticleTrait
{
use RowTrait;
protected $serialID = 'documento';
public function setSerials($serials)
{
database()->sync('mg_prodotti', [
'id_riga_'.$this->serialID => $this->id,
'dir' => 'entrata',
'id_articolo' => $this->idarticolo,
], [
'serial' => $serials,
]);
}
}

65
src/Traits/RowTrait.php Normal file
View File

@ -0,0 +1,65 @@
<?php
namespace Traits;
use App;
trait RowTrait
{
protected $variabilePrezzo = 'prezzo';
public function setIVA($id_iva)
{
$iva = database()->fetchOne('SELECT * FROM co_iva WHERE id = :id_iva', [
':id_iva' => $id_iva,
]);
$descrizione = $iva['descrizione'];
$valore = ($this->subtotale - $this->sconto) * $iva['percentuale'] / 100;
$this->idiva = $iva['id'];
$this->desc_iva = $descrizione;
$this->iva = $valore;
$this->iva_indetraibile = $valore / 100 * $iva['indetraibile'];
}
public function getPrezzoAttribute()
{
return $this->subtotale / $this->qta;
}
public function setSubtotale($prezzo, $qta)
{
$this->qta = $qta;
$this->subtotale = $prezzo * $qta;
}
/*
public function getPrezzoAttribute()
{
return $this->{$this->variabilePrezzo};
}
public function getSubtotaleAttribute()
{
return $this->prezzo * $this->qta;
}
*/
public function getTotaleAttribute()
{
return $this->subtotale + $this->iva;
}
public function getScontoAttribute()
{
return calcola_sconto([
'sconto' => $this->sconto_unitario,
'prezzo' => $this->prezzo,
'tipo' => $this->tipo_sconto,
'qta' => $this->qta,
]);
}
}

View File

@ -187,7 +187,7 @@ foreach ($righe as $r) {
// Iva
echo '
<td class="text-center">';
if (empty($r['is_descrizione'])) {
if (empty($r['is_descrizione']) && empty($r['sconto_globale'])) {
echo '
'.Translator::numberToLocale($r['perc_iva']);
}