Miglioramento classi dei moduli

This commit is contained in:
Thomas Zilio 2018-09-25 16:47:44 +02:00
parent 8cd6ce98a2
commit aac50aa2da
44 changed files with 511 additions and 366 deletions

View File

@ -55,19 +55,7 @@
},
"autoload": {
"psr-4": {
"": "src/",
"Modules\\Anagrafiche\\": "modules/anagrafiche/src",
"Modules\\Anagrafiche\\Custom\\": "modules/anagrafiche/custom/src",
"Modules\\Articoli\\": "modules/articoli/src",
"Modules\\Articoli\\Custom\\": "modules/articoli/custom/src",
"Modules\\Fatture\\": "modules/fatture/src",
"Modules\\Fatture\\Custom\\": "modules/fatture/custom/src",
"Modules\\Interventi\\": "modules/interventi/src",
"Modules\\Interventi\\Custom\\": "modules/interventi/custom/src",
"Plugins\\ExportPA\\": "plugins/exportPA/src",
"Plugins\\ExportPA\\Custom\\": "plugins/exportPA/custom/src",
"Plugins\\ImportPA\\": "plugins/importPA/src",
"Plugins\\ImportPA\\Custom\\": "plugins/importPA/custom/src"
"": "src/"
},
"files": [
"lib/functions.php",

10
config/namespaces.php Normal file
View File

@ -0,0 +1,10 @@
<?php
return [
'modules/anagrafiche' => 'Modules\\Anagrafiche\\',
'modules/articoli' => 'Modules\\Articoli\\',
'modules/fatture' => 'Modules\\Fatture\\',
'modules/interventi' => 'Modules\\Interventi\\',
'plugins/exportPA' => 'Modules\\ExportPA\\',
'plugins/importPA' => 'Modules\\ImportPA\\',
];

View File

@ -22,7 +22,13 @@ if (file_exists(__DIR__.'/config.inc.php')) {
}
// Caricamento delle dipendenze e delle librerie del progetto
require_once __DIR__.'/vendor/autoload.php';
$loader = require_once __DIR__.'/vendor/autoload.php';
$namespaces = require_once __DIR__.'/config/namespaces.php';
foreach ($namespaces as $path => $namespace) {
$loader->addPsr4($namespace, $path.'/src');
$loader->addPsr4($namespace, $path.'/custom/src');
}
// Individuazione dei percorsi di base
App::definePaths(__DIR__);

View File

@ -110,10 +110,7 @@ switch (post('op')) {
$idtipoanagrafica = post('idtipoanagrafica');
$ragione_sociale = post('ragione_sociale');
$anagrafica = Anagrafica::create([
'ragione_sociale' => $ragione_sociale,
'tipologie' => $idtipoanagrafica,
]);
$anagrafica = Anagrafica::new($ragione_sociale, $idtipoanagrafica);
$id_record = $anagrafica->id;
// Se ad aggiungere un cliente è un agente, lo imposto come agente di quel cliente

View File

@ -2,7 +2,7 @@
namespace Modules\Anagrafiche;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
use Modules\Fatture\Fattura;
use Util\Generator;
use Settings;
@ -12,11 +12,6 @@ class Anagrafica extends Model
protected $table = 'an_anagrafiche';
protected $primaryKey = 'idanagrafica';
/** @var array Opzioni abilitate per la creazione */
protected $fillable = [
'ragione_sociale',
];
protected $appends = [
'id',
'partita_iva',
@ -28,18 +23,19 @@ class Anagrafica extends Model
];
/**
* Crea una nuova fattura.
* Crea una nuova anagrafica.
*
* @param int $id_anagrafica
* @param string $data
* @param int $id_segment
* @param string $ragione_sociale
* @param array $tipologie
*
* @return self
*/
public static function create(array $attributes = [])
public static function new($ragione_sociale, array $tipologie = [])
{
$model = static::query()->create($attributes);
$model = parent::new();
// Completamento informazioni
$model->updateTipologie((array)$attributes['tipologie']);
$model->ragione_sociale = $ragione_sociale;
$model->updateTipologie($tipologie);
$ultimo = database()->fetchOne('SELECT codice FROM an_anagrafiche ORDER BY CAST(codice AS SIGNED) DESC LIMIT 1');
$codice = Generator::generate(setting('Formato codice anagrafica'), $ultimo['codice']);
@ -111,7 +107,6 @@ class Anagrafica extends Model
* Aggiorna la tipologia dell'anagrafica.
*
* @param array $tipologie
* @return void
*/
public function updateTipologie(array $tipologie)
{
@ -159,7 +154,7 @@ class Anagrafica extends Model
{
if (self::where([
['codice', $value],
[$this->primaryKey, '<>', $this->id]
[$this->primaryKey, '<>', $this->id],
])->count() == 0) {
$this->attributes['codice'] = $value;
}

View File

@ -2,7 +2,7 @@
namespace Modules\Anagrafiche;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
class Nazione extends Model
{

View File

@ -2,7 +2,7 @@
namespace Modules\Anagrafiche;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
class Tipo extends Model
{

View File

@ -7,7 +7,7 @@ switch ($resource) {
$query = 'SELECT mg_articoli.*, (SELECT CONCAT(numero, " ", descrizione) FROM co_pianodeiconti3 WHERE co_pianodeiconti3.id = idconto_vendita) AS idconto_vendita_title, (SELECT CONCAT(numero, " ", descrizione) FROM co_pianodeiconti3 WHERE co_pianodeiconti3.id = idconto_acquisto) AS idconto_acquisto_title, co_iva.descrizione AS iva_vendita FROM mg_articoli LEFT OUTER JOIN co_iva ON mg_articoli.idiva_vendita=co_iva.id |where| ORDER BY mg_articoli.id_categoria ASC, mg_articoli.id_sottocategoria ASC';
$idiva_predefinita = setting('Iva predefinita');
$rs = $dbo->fetchArray("SELECT descrizione FROM co_iva WHERE id=".prepare($idiva_predefinita));
$rs = $dbo->fetchArray('SELECT descrizione FROM co_iva WHERE id='.prepare($idiva_predefinita));
$iva_predefinita = $rs[0]['descrizione'];
foreach ($elements as $element) {

View File

@ -2,7 +2,7 @@
namespace Modules\Articoli;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
use Modules\Articoli\Articolo as ArticoloIntervento;
class Articolo extends Model

View File

@ -285,11 +285,11 @@ if ($total == 0) {
</div>
<br>
<?php
$qp = "SELECT MONTH(data_richiesta) AS mese, YEAR(data_richiesta) AS anno FROM (co_promemoria INNER JOIN co_contratti ON co_promemoria.idcontratto=co_contratti.id) INNER JOIN an_anagrafiche ON co_contratti.idanagrafica=an_anagrafiche.idanagrafica WHERE idcontratto IN( SELECT id FROM co_contratti WHERE idstato IN(SELECT id FROM co_staticontratti WHERE pianificabile = 1) ) AND idintervento IS NULL
$qp = 'SELECT MONTH(data_richiesta) AS mese, YEAR(data_richiesta) AS anno FROM (co_promemoria INNER JOIN co_contratti ON co_promemoria.idcontratto=co_contratti.id) INNER JOIN an_anagrafiche ON co_contratti.idanagrafica=an_anagrafiche.idanagrafica WHERE idcontratto IN( SELECT id FROM co_contratti WHERE idstato IN(SELECT id FROM co_staticontratti WHERE pianificabile = 1) ) AND idintervento IS NULL
UNION SELECT MONTH(data_scadenza) AS mese, YEAR(data_scadenza) AS anno FROM (co_ordiniservizio INNER JOIN co_contratti ON co_ordiniservizio.idcontratto=co_contratti.id) INNER JOIN an_anagrafiche ON co_contratti.idanagrafica=an_anagrafiche.idanagrafica WHERE idcontratto IN( SELECT id FROM co_contratti WHERE idstato IN(SELECT id FROM co_staticontratti WHERE pianificabile = 1) ) AND idintervento IS NULL
UNION SELECT MONTH(data_richiesta) AS mese, YEAR(data_richiesta) AS anno FROM in_interventi INNER JOIN an_anagrafiche ON in_interventi.idanagrafica=an_anagrafiche.idanagrafica WHERE (SELECT COUNT(*) FROM in_interventi_tecnici WHERE in_interventi_tecnici.idintervento = in_interventi.id) = 0";
UNION SELECT MONTH(data_richiesta) AS mese, YEAR(data_richiesta) AS anno FROM in_interventi INNER JOIN an_anagrafiche ON in_interventi.idanagrafica=an_anagrafiche.idanagrafica WHERE (SELECT COUNT(*) FROM in_interventi_tecnici WHERE in_interventi_tecnici.idintervento = in_interventi.id) = 0';
$rsp = $dbo->fetchArray($qp);
if (!empty($rsp)) {

View File

@ -3,6 +3,10 @@
include_once __DIR__.'/../../core.php';
use Modules\Fatture\Fattura;
use Modules\Fatture\Articolo;
use Modules\Articoli\Articolo as ArticoloOriginale;
use Modules\Fatture\Tipo;
use Modules\Anagrafiche\Anagrafica;
// Necessaria per la funzione add_movimento_magazzino
include_once Modules::filepath('Articoli', 'modutil.php');
@ -25,12 +29,10 @@ switch (post('op')) {
$idtipodocumento = post('idtipodocumento');
$id_segment = post('id_segment');
$fattura = Fattura::create([
'idanagrafica' => $idanagrafica,
'data' => $data,
'id_segment' => $id_segment,
'tipo' => $idtipodocumento,
]);
$anagrafica = Anagrafica::find($idanagrafica);
$tipo = Tipo::find($idtipodocumento);
$fattura = Fattura::new($anagrafica, $tipo, $data, $id_segment);
$id_record = $fattura->id;
flash()->info(tr('Aggiunta fattura numero _NUM_!', [
@ -480,34 +482,32 @@ switch (post('op')) {
case 'addarticolo':
if (!empty($id_record) && post('idarticolo') !== null) {
$idarticolo = post('idarticolo');
$descrizione = post('descrizione');
$idiva = post('idiva');
$idconto = post('idconto');
$idum = post('um');
$idrivalsainps = post('idrivalsainps');
$idritenutaacconto = post('idritenutaacconto');
$calcolo_ritenutaacconto = post('calcolo_ritenutaacconto');
$qta = post('qta');
if (!empty($record['is_reversed'])) {
$qta = -$qta;
}
$prezzo = post('prezzo');
$originale = ArticoloOriginale::find(post('idarticolo'));
$articolo = Articolo::new($fattura, $originale);
// Calcolo dello sconto
$sconto_unitario = post('sconto');
$tipo_sconto = post('tipo_sconto');
$sconto = calcola_sconto([
'sconto' => $sconto_unitario,
'prezzo' => $prezzo,
'tipo' => $tipo_sconto,
'qta' => $qta,
]);
$articolo->descrizione = post('descrizione');
$articolo->setSubtotale(post('prezzo'), $qta);
$articolo->sconto_unitario = post('sconto');
$articolo->tipo_sconto = post('tipo_sconto');
add_articolo_infattura($id_record, $idarticolo, $descrizione, $idiva, $qta, $prezzo * $qta, $sconto, $sconto_unitario, $tipo_sconto, '0', $idconto, $idum, $idrivalsainps, $idritenutaacconto, $calcolo_ritenutaacconto);
$um = post('um');
if (!empty($um)) {
$articolo->um = $um;
}
$articolo->id_iva = post('idiva');
$articolo->idconto = post('idconto');
$articolo->calcolo_ritenuta_acconto = post('calcolo_ritenutaacconto');
$articolo->id_ritenuta_acconto = post('idritenutaacconto');
$articolo->save();
//add_articolo_infattura($id_record, $idarticolo, $descrizione, $idiva, $qta, $prezzo * $qta, $sconto, $sconto_unitario, $tipo_sconto, '0', $idconto, $idum, $idrivalsainps, $idritenutaacconto, $calcolo_ritenutaacconto);
ricalcola_costiagg_fattura($id_record);

View File

@ -10,6 +10,7 @@ if ($module['name'] == 'Fatture di vendita') {
if (isset($id_record)) {
$fattura = Modules\Fatture\Fattura::with('tipo', 'stato')->find($id_record);
//$fattura->articoli();
$record = $dbo->fetchOne('SELECT *, co_tipidocumento.reversed AS is_reversed, co_documenti.idagente AS idagente_fattura, co_documenti.note, co_documenti.note_aggiuntive, co_documenti.idpagamento, co_documenti.id AS iddocumento, co_statidocumento.descrizione AS `stato`, co_tipidocumento.descrizione AS `descrizione_tipodoc`, (SELECT descrizione FROM co_ritenutaacconto WHERE id=idritenutaacconto) AS ritenutaacconto_desc, (SELECT descrizione FROM co_rivalsainps WHERE id=idrivalsainps) AS rivalsainps_desc FROM ((co_documenti LEFT OUTER JOIN co_statidocumento ON co_documenti.idstatodocumento=co_statidocumento.id) INNER JOIN an_anagrafiche ON co_documenti.idanagrafica=an_anagrafiche.idanagrafica) INNER JOIN co_tipidocumento ON co_documenti.idtipodocumento=co_tipidocumento.id WHERE co_tipidocumento.dir = '.prepare($dir).' AND co_documenti.id='.prepare($id_record));

View File

@ -2,33 +2,64 @@
namespace Modules\Fatture;
use Illuminate\Database\Eloquent\Model;
use Modules\Articoli\Articolo as Original;
use Traits\ArticleTrait;
use Base\Article;
class Articolo extends Model
class Articolo extends Article
{
use ArticleTrait;
protected $table = 'co_righe_documenti';
public function __construct(Fattura $fattura, Original $articolo, array $attributes = array())
/**
* Crea un nuovo articolo collegato ad una fattura.
*
* @param Fattura $fattura
* @param Original $articolo
*
* @return self
*/
public static function new(Fattura $fattura, Original $articolo)
{
parent::__construct($attributes);
$model = parent::new($articolo);
$this->fattura()->associate($fattura);
$this->articolo()->associate($articolo);
$model->fattura()->associate($fattura);
// Salvataggio delle informazioni
$this->descrizione = isset($attributes['descrizione']) ? $attributes['descrizione'] : $articolo->descrizione;
$this->abilita_serial = $articolo->abilita_serial;
$model->save();
$this->save();
return $model;
}
public function articolo()
public function movimenta($qta)
{
return $this->belongsTo(Original::class, 'idarticolo');
// 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()->first();
$tipo = $fattura->tipo()->first();
$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 == 'uscita') ? tr('Rimozione articolo da _TYPE_ _NUM_') : tr('Scarico magazzino per _TYPE_ numero _NUM_');
$movimento = ($qta > 0) ? $carico : $scarico;
$qta = ($tipo->dir == 'uscita') ? -$qta : $qta;
$movimento = replace($movimento, [
'_TYPE_' => $tipo->descrizione,
'_NUM_' => $numero,
]);
$this->articolo()->first()->movimenta(-$qta, $movimento, $data, false, [
'iddocumento' => $fattura->id,
]);
}
protected function serialID()
{
return 'documento';
}
public function fattura()

View File

@ -2,7 +2,7 @@
namespace Modules\Fatture;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
use Util\Generator;
use Modules\Anagrafiche\Anagrafica;
@ -10,36 +10,28 @@ class Fattura extends Model
{
protected $table = 'co_documenti';
/** @var array Opzioni abilitate per la creazione */
protected $fillable = [
'idanagrafica',
'data',
'id_segment',
];
/** @var array Conti rilevanti della fattura */
protected $conti = [];
/**
* Crea una nuova fattura.
*
* @param int $id_anagrafica
* @param Anagrafica $anagrafica
* @param Tipo $tipo_documento
* @param string $data
* @param int $id_segment
*
* @return self
*/
public static function create(array $attributes = [])
public static function new(Anagrafica $anagrafica, Tipo $tipo_documento, $data, $id_segment)
{
$model = static::query()->create($attributes);
$model = parent::new();
$tipo_documento = Tipo::find($attributes['tipo']);
$stato_documento = Stato::where('descrizione', 'Bozza')->first();
$id_anagrafica = $anagrafica->id;
$direzione = $tipo_documento->dir;
$data = $attributes['data'];
$id_anagrafica = $attributes['idanagrafica'];
$id_segment = $attributes['id_segment'];
$database = database();
// Calcolo dei numeri fattura
@ -79,12 +71,20 @@ class Fattura extends Model
// Salvataggio delle informazioni
$model->numero = $numero;
$model->numero_esterno = $numero_esterno;
$model->data = $data;
$model->id_segment = $id_segment;
$model->idconto = $id_conto;
$model->idpagamento = $id_pagamento;
$model->idbanca = $id_banca;
$model->idsede = $id_sede;
if (!empty($id_pagamento)) {
$model->idpagamento = $id_pagamento;
}
if (!empty($id_banca)) {
$model->idbanca = $id_banca;
}
$model->anagrafica()->associate($anagrafica);
$model->tipo()->associate($tipo_documento);
$model->stato()->associate($stato_documento);
@ -325,6 +325,11 @@ class Fattura extends Model
return $this->belongsTo(Stato::class, 'idstatodocumento');
}
public function articoli()
{
return $this->hasMany(Articolo::class, 'iddocumento');
}
public function righe()
{
return $this->hasMany(Riga::class, 'iddocumento');

View File

@ -2,21 +2,26 @@
namespace Modules\Fatture;
use Illuminate\Database\Eloquent\Model;
use Traits\RowTrait;
use Base\Row;
class Riga extends Model
class Riga extends Row
{
use RowTrait;
protected $table = 'co_righe_documenti';
public function __construct(Fattura $fattura, array $attributes = array())
/**
* Crea una nuova riga collegata ad una fattura.
*
* @param Fattura $fattura
*
* @return self
*/
public static function new(Fattura $fattura)
{
parent::__construct($attributes);
$model = parent::new();
$this->fattura()->associate($fattura);
$this->save();
$model->fattura()->associate($fattura);
return $model;
}
public function fattura()

View File

@ -2,7 +2,7 @@
namespace Modules\Fatture;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
class Stato extends Model
{

View File

@ -2,7 +2,7 @@
namespace Modules\Fatture;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
class Tipo extends Model
{

View File

@ -3,6 +3,8 @@
include_once __DIR__.'/../../core.php';
use Modules\Interventi\Articolo;
use Modules\Interventi\Intervento;
use Modules\Articoli\Articolo as ArticoloOriginale;
include_once Modules::filepath('Interventi', 'modutil.php');
include_once Modules::filepath('Articoli', 'modutil.php');
@ -327,7 +329,7 @@ switch (post('op')) {
$id_record = post('id_intervento');
$idcontratto = $dbo->fetchOne('SELECT idcontratto FROM co_promemoria WHERE idintervento = :id', [
':id' => $id_record
':id' => $id_record,
])['idcontratto'];
}
@ -518,18 +520,19 @@ switch (post('op')) {
// no break
case 'addarticolo':
$articolo = Articolo::create([
'idarticolo' => post('idarticolo'),
'idintervento' => $id_record,
'idautomezzo' => post('idautomezzo'),
'qta' => post('qta'),
'descrizione' => post('descrizione'),
'prezzo' => post('prezzo_vendita'),
'um' => post('um'),
]);
$originale = ArticoloOriginale::find(post('idarticolo'));
$intervento = Intervento::find($id_record);
$articolo = Articolo::new($intervento, $originale, post('idautomezzo'));
$articolo->setSconto(post('sconto'), post('tipo_sconto'));
$articolo->setIVA(post('idiva'));
$articolo->qta = post('qta');
$articolo->descrizione = post('descrizione');
$articolo->prezzo_vendita = post('prezzo_vendita');
$articolo->um = post('um');
$articolo->sconto_unitario = post('sconto');
$articolo->tipo_sconto = post('tipo_sconto');
$articolo->id_iva = post('idiva');
$articolo->save();

View File

@ -3,6 +3,8 @@
include_once Modules::filepath('Articoli', 'modutil.php');
use Modules\Interventi\Articolo;
use Modules\Interventi\Intervento;
use Modules\Articoli\Articolo as ArticoloOriginale;
switch ($resource) {
case 'intervento':
@ -59,13 +61,14 @@ switch ($resource) {
case 'articolo_intervento':
$data = $request['data'];
$articolo = Articolo::create([
'idarticolo' => $data['id_articolo'],
'idintervento' => $data['id_intervento'],
'idautomezzo' => $data['id_automezzo'],
'qta' => $data['qta'],
'um' => $data['um'],
]);
$originale = ArticoloOriginale::find($data['id_articolo']);
$intervento = Intervento::find($data['id_intervento']);
$articolo = Articolo::new($intervento, $originale, $data['id_automezzo']);
$articolo->qta = $data['qta'];
$articolo->um = $data['um'];
$articolo->save();
break;
}

View File

@ -2,35 +2,34 @@
namespace Modules\Interventi;
use Illuminate\Database\Eloquent\Model;
use Modules\Articoli\Articolo as Original;
use Base\Article;
class Articolo extends Model
class Articolo extends Article
{
protected $table = 'mg_articoli_interventi';
/** @var array Opzioni abilitate per la creazione */
protected $fillable = [
'idarticolo',
'idintervento',
'idautomezzo',
];
/**
* Crea un nuovo articolo collegato ad un intervento.
*
* @param array $attributes
*/
public static function create(array $attributes = [])
public static function new(Intervento $intervento, Original $articolo, $id_automezzo = null)
{
$model = static::query()->create($attributes);
$model = parent::new($articolo);
$articolo = $model->articolo()->first();
$qta = $attributes['qta'];
$model->intervento()->associate($intervento);
$model->prezzo_acquisto = $articolo->prezzo_acquisto;
$model->prezzo_vendita = $articolo->prezzo_vendita;
$model->save();
return $model;
}
public function movimenta($qta)
{
$articolo = $this->articolo()->first();
// Movimento l'articolo
if (!empty($model->idautomezzo)) {
$rs = $dbo->fetchArray("SELECT CONCAT_WS(' - ', nome, targa) AS nome FROM dt_automezzi WHERE id=".prepare($model->idautomezzo));
if (!empty($this->idautomezzo)) {
$rs = $dbo->fetchArray("SELECT CONCAT_WS(' - ', nome, targa) AS nome FROM dt_automezzi WHERE id=".prepare($this->idautomezzo));
$nome = $rs[0]['nome'];
$descrizione = ($qta < 0) ? tr("Carico sull'automezzo _NAME_", [
@ -39,15 +38,15 @@ class Articolo extends Model
'_NAME_' => $nome,
]);
$dbo->query('UPDATE mg_articoli_automezzi SET qta = qta + '.$qta.' WHERE idarticolo = '.prepare($articolo->id).' AND idautomezzo = '.prepare($model->idautomezzo));
$dbo->query('UPDATE mg_articoli_automezzi SET qta = qta + '.$qta.' WHERE idarticolo = '.prepare($articolo->id).' AND idautomezzo = '.prepare($this->idautomezzo));
$data = date('Y-m-d');
$articolo->registra(-$qta, $descrizione, $data, false, [
'idautomezzo' => $model->idautomezzo,
'idintervento' => $model->idintervento,
'idautomezzo' => $this->idautomezzo,
'idintervento' => $this->idintervento,
]);
} else {
$intervento = $model->intervento()->first();
$intervento = $this->intervento()->first();
$numero = $intervento->codice;
$data = database()->fetchOne('SELECT MAX(orario_fine) AS data FROM in_interventi_tecnici WHERE idintervento = :id_intervento', [
@ -66,67 +65,16 @@ class Articolo extends Model
'idintervento' => $intervento->id,
]);
}
// Salvataggio delle informazioni
$model->descrizione = isset($attributes['descrizione']) ? $attributes['descrizione'] : $articolo->descrizione;
$model->prezzo_acquisto = $articolo->prezzo_acquisto;
$model->abilita_serial = $articolo->abilita_serial;
$model->um = $attributes['um'];
$model->qta = $attributes['qta'];
$model->prezzo_vendita = isset($attributes['prezzo']) ? $attributes['prezzo'] : $articolo->prezzo_vendita;
$model->save();
return $model;
}
public function setIVA($id_iva)
protected function serialID()
{
$iva = database()->fetchOne('SELECT * FROM co_iva WHERE id = :id_iva', [
':id_iva' => $id_iva,
]);
$descrizione = $iva['descrizione'];
$valore = (($this->prezzo_vendita * $this->qta) - $this->sconto) * $iva['percentuale'] / 100;
$this->idiva = $iva['id'];
$this->desc_iva = $descrizione;
$this->iva = $valore;
$this->save();
return 'intervento';
}
public function setSconto($unitario, $tipo)
public function getSubtotaleAttribute()
{
$sconto = calcola_sconto([
'sconto' => $unitario,
'prezzo' => $this->prezzo_vendita,
'tipo' => $tipo,
'qta' => $this->qta,
]);
$this->sconto_unitario = $unitario;
$this->tipo_sconto = $tipo;
$this->sconto = $sconto;
$this->save();
}
public function setSerials($serials)
{
database()->sync('mg_prodotti', [
'id_riga_intervento' => $this->id,
'dir' => 'entrata',
'id_articolo' => $this->idarticolo,
], [
'serial' => $serials,
]);
}
public function articolo()
{
return $this->belongsTo(Original::class, 'idarticolo');
return $this->prezzo_vendita * $this->qta;
}
public function intervento()

View File

@ -2,7 +2,7 @@
namespace Modules\Interventi;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
use Modules\Anagrafiche\Anagrafica;
class Intervento extends Model

View File

@ -2,7 +2,7 @@
namespace Modules\Interventi;
use Illuminate\Database\Eloquent\Model;
use Base\Model;
class Riga extends Model
{

View File

@ -107,7 +107,7 @@ if ($generated) {
<hr>
<div class="row">
<div class="col-md-12">
<a href="'.ROOTDIR.'/plugins/fatturazione/view.php?id_record='.$id_record.'" class="btn btn-info btn-lg btn-block" target="_blank">
<a href="'.ROOTDIR.'/plugins/exportPA/view.php?id_record='.$id_record.'" class="btn btn-info btn-lg btn-block" target="_blank">
<i class="fa fa-eye"></i> '.tr('Visualizza').'
</a>
</div>

View File

@ -351,7 +351,6 @@ class FatturaElettronica
return $result;
}
/**
* Restituisce l'array responsabile per la generazione del tag DatiDocumento.
*

View File

@ -25,7 +25,7 @@ switch (filter('op')) {
]);
} catch (UnexpectedValueException $e) {
echo json_encode([
'already' => 1
'already' => 1,
]);
}
@ -38,7 +38,7 @@ switch (filter('op')) {
$xml = file_get_contents(DOCROOT.'/'.$directory.'/'.$filename);
$fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment'));
$id_record = $fattura_pa->saveFattura();
$id_record = $fattura_pa->saveFattura(post('pagamento'));
$fattura_pa->saveRighe(post('articoli'), post('iva'));
$fattura_pa->getFattura()->updateSconto();

View File

@ -9,6 +9,13 @@ $fattura_pa = new Plugins\ImportPA\FatturaElettronica($xml, post('id_segment'));
$righe = $fattura_pa->getRighe();
$pagamenti = $fattura_pa->getBody()['DatiPagamento'];
$metodi = $pagamenti['DettaglioPagamento'];
$metodi = isset($metodi[0]) ? $metodi : [$metodi];
$query = 'SELECT id, descrizione FROM co_pagamenti WHERE prc '.($pagamenti['CondizioniPagamento'] == 'TP01' ? '!' : '').'= 100 AND codice_modalita_pagemento_fe = '.prepare($metodi[0]['ModalitaPagamento']).' GROUP BY descrizione ORDER BY descrizione ASC';
echo '
<form action="'.$rootdir.'/actions.php" method="post">
<input type="hidden" name="id_module" value="'.$id_module.'">
@ -17,7 +24,9 @@ echo '
<input type="hidden" name="id_segment" value="'.get('id_segment').'">
<input type="hidden" name="id" value="'.get('id').'">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="op" value="generate">';
<input type="hidden" name="op" value="generate">
{[ "type": "select", "label": "'.tr('Pagamento').'", "name": "pagamento", "required": 1, "values": "query='.$query.'" ]}';
if (!empty($righe)) {
echo '
@ -62,7 +71,6 @@ if (!empty($righe)) {
<p>Non ci sono righe nella fattura.</p>';
}
echo '
<div class="row">
<div class="col-md-12 text-right">

View File

@ -30,7 +30,7 @@ class FatturaElettronica
public function __construct($content, $id_sezionale)
{
$xml = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$xml = simplexml_load_string($content, 'SimpleXMLElement', LIBXML_NOCDATA);
$json = json_encode($xml);
$array = json_decode($json, true);
@ -84,15 +84,12 @@ class FatturaElettronica
INNER JOIN `an_tipianagrafiche` ON `an_tipianagrafiche`.`idtipoanagrafica` = `an_tipianagrafiche_anagrafiche`.`idtipoanagrafica`
WHERE `an_tipianagrafiche`.`descrizione` = '.prepare($type).' AND ('.implode(' OR ', $where).')')['idanagrafica'];
if (!empty($id_anagrafica)) {
return $id_anagrafica;
return Anagrafica::find($id_anagrafica);
}
$ragione_sociale = $xml['DatiAnagrafici']['Anagrafica']['Denominazione'] ?: $xml['DatiAnagrafici']['Anagrafica']['Nome'].' '.$xml['DatiAnagrafici']['Anagrafica']['Cognome'];
$anagrafica = Anagrafica::create([
'ragione_sociale' => $ragione_sociale,
'tipologie' => [
TipoAnagrafica::where('descrizione', 'Fornitore')->first()->id
],
$anagrafica = Anagrafica::new($ragione_sociale, [
TipoAnagrafica::where('descrizione', 'Fornitore')->first()->id,
]);
// Informazioni sull'anagrafica
@ -151,9 +148,7 @@ class FatturaElettronica
{
$result = $this->getBody()['DatiBeniServizi']['DettaglioLinee'];
if (!isset($result[0])) {
$result = [$result];
}
$result = isset($result[0]) ? $result : [$result];
return $result;
}
@ -166,9 +161,9 @@ class FatturaElettronica
$articolo = ArticoloOriginale::find($articoli[$key]);
if (!empty($articolo)) {
$obj = new Articolo($this->getFattura(), $articolo);
$obj = Articolo::new($this->getFattura(), $articolo);
} else {
$obj = new Riga($this->getFattura());
$obj = Riga::new($this->getFattura());
}
$obj->descrizione = $riga['Descrizione'];
@ -177,7 +172,9 @@ class FatturaElettronica
$obj->qta = $riga['Quantita'];
$obj->prezzo = $riga['PrezzoUnitario'];
*/
if (!empty($riga['UnitaMisura'])) {
$obj->um = $riga['UnitaMisura'];
}
$sconto = $riga['ScontoMaggiorazione'];
if (!empty($sconto)) {
@ -188,10 +185,9 @@ class FatturaElettronica
$obj->sconto_unitario = $unitario;
$obj->tipo_sconto = $tipo;
$obj->sconto = $obj->sconto;
}
$obj->setIVA($iva[$key]);
$obj->id_iva = $iva[$key];
$obj->save();
}
@ -201,9 +197,7 @@ class FatturaElettronica
{
$result = $this->getBody()['Allegati'];
if (!isset($result[0])) {
$result = [$result];
}
$result = isset($result[0]) ? $result : [$result];
return $result;
}
@ -212,16 +206,22 @@ class FatturaElettronica
{
$allegati = $this->getAllegati();
$module = Modules::get('Fatture di acquisto');
foreach ($allegati as $allegato) {
$content = base64_decode($allegato['Attachment']);
$filename = $directory.'/'.$allegato['NomeAttachment'].'.'.strtolower($allegato['FormatoAttachment']);
$original = $allegato['NomeAttachment'].'.'.strtolower($allegato['FormatoAttachment']);
$filename = Uploads::getName($original, [
'id_module' => $module['id'],
]);
file_put_contents($filename, $content);
file_put_contents($directory.'/'.$filename, $content);
Uploads::register([
'original' => $allegato['NomeAttachment'],
'filename' => $filename,
'original' => $original,
'category' => tr('Fattura elettronica'),
'id_module' => Modules::get('Fatture di acquisto')['id'],
'id_module' => $module['id'],
'id_record' => $this->fattura->id,
]);
}
@ -237,26 +237,22 @@ class FatturaElettronica
*
* @return int
*/
public function saveFattura()
public function saveFattura($id_pagamento)
{
$id_anagrafica = static::createAnagrafica($this->getHeader()['CedentePrestatore']);
$anagrafica = static::createAnagrafica($this->getHeader()['CedentePrestatore']);
$dati_generali = $this->getBody()['DatiGenerali']['DatiGeneraliDocumento'];
$data = $dati_generali['Data'];
$numero = $dati_generali['Numero'];
$tipo = empty($this->getBody()['DatiGenerali']['DatiTrasporto']) ? 'Fattura immediata di acquisto' : 'Fattura accompagnatoria di acquisto';
$id_tipo = TipoFattura::where('descrizione', $tipo)->first()->id;
$descrizione_tipo = empty($this->getBody()['DatiGenerali']['DatiTrasporto']) ? 'Fattura immediata di acquisto' : 'Fattura accompagnatoria di acquisto';
$tipo = TipoFattura::where('descrizione', $descrizione_tipo)->first();
$fattura = Fattura::create([
'idanagrafica' => $id_anagrafica,
'data' => $data,
'id_segment' => $this->id_sezionale,
'tipo' => $id_tipo,
]);
$fattura = Fattura::new($anagrafica, $tipo, $data, $this->id_sezionale);
$this->fattura = $fattura;
$fattura->numero = $numero;
$fattura->idpagamento = $id_pagamento;
$stato_documento = StatoFattura::where('descrizione', 'Emessa')->first();
$fattura->stato()->associate($stato_documento);

View File

@ -173,7 +173,7 @@ class Backup
if (extension_loaded('zip')) {
$result = Zip::create([
DOCROOT,
self::getDatabaseDirectory()
self::getDatabaseDirectory(),
], $backup_dir.'/'.$backup_name.'.zip', $ignores);
}
@ -181,7 +181,7 @@ class Backup
else {
$result = copyr([
DOCROOT,
self::getDatabaseDirectory()
self::getDatabaseDirectory(),
], $backup_dir.'/'.$backup_name.'.zip', $ignores);
}

15
src/Base/Description.php Normal file
View File

@ -0,0 +1,15 @@
<?php
namespace Base;
abstract class Description extends Model
{
protected static function boot()
{
parent::boot();
static::addGlobalScope('descriptions', function (Builder $builder) {
$builder->where('is_descrizione', '=', 0);
});
}
}

18
src/Base/Model.php Normal file
View File

@ -0,0 +1,18 @@
<?php
namespace Base;
use Illuminate\Database\Eloquent\Model as Original;
abstract class Model extends Original
{
/**
* Crea una nuova istanza del modello.
*
* @return static
*/
public static function new()
{
return new static();
}
}

View File

@ -1,7 +1,6 @@
<?php
use Models\MailAccount;
use Models\MailTemplate;
/**
* Classe per gestire le email in base alle impostazioni, basata sul framework open-source PHPMailer.

View File

@ -87,7 +87,7 @@ class EmailNotification extends Notification
$prints = $dbo->fetchArray('SELECT id_print FROM zz_email_print WHERE id_email = '.prepare($template['id']));
foreach ($prints as $print) {
$this->addPrint($print['id_print'], $id_record);
};
}
}
/**

View File

@ -1,23 +0,0 @@
<?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,
]);
}
}

View File

@ -1,65 +0,0 @@
<?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

@ -4,8 +4,6 @@ namespace Traits;
trait UploadTrait
{
protected $upload_directory = 'files';
/**
* Restituisce il percorso per il salvataggio degli upload.
*
@ -13,6 +11,6 @@ trait UploadTrait
*/
public function getUploadDirectoryAttribute()
{
return $this->upload_directory.'/'.$this->directory;
return 'files/'.$this->directory;
}
}

View File

@ -60,7 +60,7 @@ class Uploads
*
* @return string
*/
protected static function getName($source, $data)
public static function getName($source, $data)
{
$extension = strtolower(pathinfo($source)['extension']);
$ok = self::isSupportedType($extension);

View File

@ -26,6 +26,7 @@ class Zip
* Estrae i contenuti di un file ZIP in una cartella temporanea.
*
* @param string $path
*
* @return string
*/
public static function extract($path)

72
src/base/Article.php Normal file
View File

@ -0,0 +1,72 @@
<?php
namespace Base;
use Modules\Articoli\Articolo as Original;
abstract class Article extends Row
{
abstract protected function serialID();
abstract public function movimenta($qta);
protected static function boot()
{
parent::boot();
static::addGlobalScope('articles', function (Builder $builder) {
$builder->whereNotNull('idarticolo')->where('idarticolo', '<>', 0);
});
}
public static function new(Original $articolo)
{
$model = parent::new();
$model->articolo()->associate($articolo);
$model->descrizione = $articolo->descrizione;
$model->abilita_serial = $articolo->abilita_serial;
$model->um = $articolo->um;
return $model;
}
public function setSerials($serials)
{
database()->sync('mg_prodotti', [
'id_riga_'.$this->serialID() => $this->id,
'dir' => 'entrata',
'id_articolo' => $this->idarticolo,
], [
'serial' => $serials,
]);
}
public function setQtaAttribute($value)
{
$previous = $this->qta;
$this->attributes['qta'] = $value;
$diff = $value - $previous;
$this->movimenta($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));
}
// Se c'è un collegamento ad un ordine, aggiorno la quantità evasa
if (!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));
}
}
public function articolo()
{
return $this->belongsTo(Original::class, 'idarticolo');
}
}

130
src/base/Row.php Normal file
View File

@ -0,0 +1,130 @@
<?php
namespace Base;
abstract class Row extends Model
{
protected static function boot()
{
parent::boot();
static::addGlobalScope('rows', function (Builder $builder) {
$builder->whereNull('idarticolo')->where('idarticolo', '=', 0);
});
}
/*
public function getPrezzoAttribute()
{
return $this->prezzo;
}
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 ?: $this->prezzo_vendita, // Compatibilità con gli interventi
'tipo' => $this->tipo_sconto,
'qta' => $this->qta,
]);
}
public function setIdRivalsaINPSAttribute($value)
{
$this->attributes['idrivalsainps'] = $value;
// Calcolo rivalsa inps
$rivalsa = database()->fetchOne('SELECT * FROM co_rivalsainps WHERE id='.prepare($value));
$this->rivalsainps = ($this->subtotale - $this->sconto) / 100 * $rivalsa['percentuale'];
}
public function getCalcoloRitenutaAccontoAttribute()
{
return $this->calcolo_ritenutaacconto ?: 'Imponibile';
}
public function setCalcoloRitenutaAccontoAttribute($value)
{
return $this->attributes['calcolo_ritenutaacconto'] = $value;
}
public function setIdRitenutaAccontoAttribute($value)
{
$this->attributes['idritenutaacconto'] = $value;
// Calcolo ritenuta d'acconto
$ritenuta = database()->fetchOne('SELECT * FROM co_ritenutaacconto WHERE id='.prepare($value));
$conto = ($this->subtotale - $this->sconto);
if ($this->calcolo_ritenutaacconto == 'Imponibile + rivalsa inps') {
$conto += $this->rivalsainps;
}
$this->ritenutaacconto = $conto / 100 * $ritenuta['percentuale'];
}
/* Retrocompatibilità */
public function setScontoUnitarioAttribute($value)
{
$this->attributes['sconto_unitario'] = $value;
$this->fixSconto();
}
public function setTipoScontoAttribute($value)
{
$this->attributes['tipo_sconto'] = $value;
$this->fixSconto();
}
protected function fixSconto()
{
$this->attributes['sconto'] = $this->sconto;
}
public function setIdIvaAttribute($value)
{
$this->attributes['idiva'] = $value;
$iva = database()->fetchOne('SELECT * FROM co_iva WHERE id = :id_iva', [
':id_iva' => $value,
]);
$descrizione = $iva['descrizione'];
$valore = ($this->subtotale - $this->sconto) * $iva['percentuale'] / 100;
$this->idiva = $iva['id'];
$this->desc_iva = $descrizione;
$this->iva = $valore;
// Compatibilità con gli interventi
if (!isset($this->prezzo_vendita)) {
$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;
}
}

View File

@ -1,17 +1,23 @@
<?php
use Modules\Fatture\Fattura;
use Modules\Fatture\Tipo;
use Modules\Anagrafiche\Anagrafica;
class FatturaTest extends \Codeception\Test\Unit
{
public function testCreate()
{
$data = date('Y-m-d H:i:s');
$fattura = Modules\Fatture\Fattura::create([
'idanagrafica' => 1,
'data' => $data,
'id_segment' => 1,
'tipo' => 2,
]);
$id_anagrafica = 1;
$id_tipo = 2;
$id_segment = 1;
$anagrafica = Anagrafica::find($id_anagrafica);
$tipo = Tipo::find($id_tipo);
$fattura = Fattura::new($anagrafica, $tipo, $data, $id_segment);
$this->assertEquals($fattura->idanagrafica, 1);
$this->assertEquals($fattura->idtipodocumento, 2);

View File

@ -653,7 +653,6 @@ foreach ($it as $key => $value) {
$dbo->query("UPDATE `an_anagrafiche` SET `piva` = SUBSTRING(`piva`, 2) WHERE `piva` LIKE '".$key."%'");
}
// File e cartelle deprecate
$files = [
'docs',