diff --git a/config/namespaces.php b/config/namespaces.php index 67ff943b6..28808a2de 100644 --- a/config/namespaces.php +++ b/config/namespaces.php @@ -6,6 +6,7 @@ return [ 'modules/articoli' => 'Modules\Articoli', 'modules/ddt' => 'Modules\DDT', 'modules/fatture' => 'Modules\Fatture', + 'modules/ordini' => 'Modules\Ordini', 'modules/interventi' => 'Modules\Interventi', 'plugins/exportFE' => 'Plugins\ExportFE', 'plugins/importFE' => 'Plugins\ImportFE', diff --git a/modules/ddt/src/DDT.php b/modules/ddt/src/DDT.php index 7ce3e8f0b..ece06d255 100644 --- a/modules/ddt/src/DDT.php +++ b/modules/ddt/src/DDT.php @@ -142,7 +142,7 @@ class DDT extends Document { $database = database(); - $rs = $database->fetchOne("SELECT IFNULL(MAX(numero), '0') AS max_numero FROM dt_ddt WHERE YEAR(data) = :year AND idtipoddt IN(SELECT id FROM dt_tipiddt WHERE dir = :direction) ORDER BY numero DESC", [ + $rs = $database->fetchOne("SELECT IFNULL(MAX(numero), '0') AS max_numero FROM dt_ddt WHERE YEAR(data) = :year AND idtipoddt IN(SELECT id FROM dt_tipiddt WHERE dir = :direction) ORDER BY CAST(numero AS UNSIGNED) DESC", [ ':year' => date('Y', strtotime($data)), ':direction' => $direzione, ]); diff --git a/modules/ordini/actions.php b/modules/ordini/actions.php index d0e016ca9..7e377599e 100644 --- a/modules/ordini/actions.php +++ b/modules/ordini/actions.php @@ -2,6 +2,14 @@ include_once __DIR__.'/../../core.php'; +use Modules\Anagrafiche\Anagrafica; +use Modules\Articoli\Articolo as ArticoloOriginale; +use Modules\Ordini\Components\Articolo; +use Modules\Ordini\Components\Descrizione; +use Modules\Ordini\Components\Riga; +use Modules\Ordini\Ordine; +use Modules\Ordini\Tipo; + $module = Modules::get($id_module); if ($module['name'] == 'Ordini cliente') { @@ -13,41 +21,21 @@ if ($module['name'] == 'Ordini cliente') { switch (post('op')) { case 'add': $idanagrafica = post('idanagrafica'); - $data = post('data'); // Leggo se l'ordine è cliente o fornitore - $rs = $dbo->fetchArray('SELECT id FROM or_tipiordine WHERE dir='.prepare($dir)); - $idtipoordine = $rs[0]['id']; + $tipo = $dbo->fetchOne('SELECT id FROM or_tipiordine WHERE dir='.prepare($dir)); - if (post('idanagrafica') !== null) { - $numero = get_new_numeroordine($data); - if ($dir == 'entrata') { - $numero_esterno = get_new_numerosecondarioordine($data); - } else { - $numero_esterno = ''; - } + $anagrafica = Anagrafica::find($idanagrafica); + $tipo = Tipo::find($tipo['id']); - $campo = ($dir == 'entrata') ? 'idpagamento_vendite' : 'idpagamento_acquisti'; + $ordine = Ordine::make($anagrafica, $tipo, $data); + $id_record = $ordine->id; - // Tipo di pagamento predefinito dall'anagrafica - $rs = $dbo->fetchArray('SELECT id FROM co_pagamenti WHERE id=(SELECT '.$campo.' AS pagamento FROM an_anagrafiche WHERE idanagrafica='.prepare($idanagrafica).')'); - $idpagamento = isset($rs[0]) ? $rs[0]['id'] : null; + flash()->info(tr('Aggiunto ordine numero _NUM_!', [ + '_NUM_' => $numero, + ])); - // Se l'ordine è un ordine cliente e non è stato associato un pagamento predefinito al cliente leggo il pagamento dalle impostazioni - if ($dir == 'entrata' && empty($idpagamento)) { - $idpagamento = setting('Tipo di pagamento predefinito'); - } - - $query = 'INSERT INTO or_ordini( numero, numero_esterno, idanagrafica, idtipoordine, idpagamento, data, idstatoordine ) VALUES ( '.prepare($numero).', '.prepare($numero_esterno).', '.prepare($idanagrafica).', '.prepare($idtipoordine).', '.prepare($idpagamento).', '.prepare($data).", (SELECT `id` FROM `or_statiordine` WHERE `descrizione`='Bozza') )"; - $dbo->query($query); - - $id_record = $dbo->lastInsertedID(); - - flash()->info(tr('Aggiunto ordine numero _NUM_!', [ - '_NUM_' => $numero, - ])); - } break; case 'update': diff --git a/modules/ordini/src/Components/Articolo.php b/modules/ordini/src/Components/Articolo.php new file mode 100644 index 000000000..84cc192a8 --- /dev/null +++ b/modules/ordini/src/Components/Articolo.php @@ -0,0 +1,58 @@ +ordine; + $tipo = $ordine->tipo; + + $numero = $ordine->numero_esterno ?: $ordine->numero; + $data = $ordine->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' => $ordine->id, + ]); + } + + public function getDirection() + { + return $this->ordine->tipo->dir; + } +} diff --git a/modules/ordini/src/Components/Descrizione.php b/modules/ordini/src/Components/Descrizione.php new file mode 100644 index 000000000..97c87ad9b --- /dev/null +++ b/modules/ordini/src/Components/Descrizione.php @@ -0,0 +1,27 @@ +belongsTo(Ordine::class, $this->getParentID()); + } + + public function ordine() + { + return $this->parent(); + } + + public function getNettoAttribute() + { + $result = parent::getNettoAttribute(); + + if ($this->parent->split_payment) { + $result = $result - $this->iva; + } + + return $result; + } +} diff --git a/modules/ordini/src/Components/Riga.php b/modules/ordini/src/Components/Riga.php new file mode 100644 index 000000000..3f27b8e02 --- /dev/null +++ b/modules/ordini/src/Components/Riga.php @@ -0,0 +1,27 @@ +scontoGlobale; + + if ($model == null) { + $model = parent::make(); + + $model->setOrdine($ordine); + } + + return $model; + } +} diff --git a/modules/ordini/src/Ordine.php b/modules/ordini/src/Ordine.php new file mode 100644 index 000000000..f5e0975cc --- /dev/null +++ b/modules/ordini/src/Ordine.php @@ -0,0 +1,180 @@ +first(); + + $id_anagrafica = $anagrafica->id; + $direzione = $tipo_documento->dir; + + $database = database(); + + if ($direzione == 'entrata') { + $conto = 'vendite'; + } else { + $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['id_pagamento'.$conto], + ])['id']; + + // Se il ordine è un ordine cliente 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'); + } + + $model->anagrafica()->associate($anagrafica); + $model->tipo()->associate($tipo_documento); + $model->stato()->associate($stato_documento); + + $model->save(); + + // Salvataggio delle informazioni + $model->data = $data; + + if (!empty($id_pagamento)) { + $model->idpagamento = $id_pagamento; + } + + $model->numero = static::getNextNumero($data, $direzione); + $model->numero_esterno = static::getNextNumeroSecondario($data, $direzione); + + $model->save(); + + return $model; + } + + /** + * Restituisce il nome del modulo a cui l'oggetto è collegato. + * + * @return string + */ + public function getModuleAttribute() + { + return $this->tipo->dir == 'entrata' ? 'Ordini cliente' : 'Ordini fornitore'; + } + + public function updateSconto() + { + // Aggiornamento sconto + aggiorna_sconto([ + 'parent' => 'or_ordini', + 'row' => 'or_righe_ordine', + ], [ + 'parent' => 'id', + 'row' => 'idordine', + ], $this->id); + } + + public function anagrafica() + { + return $this->belongsTo(Anagrafica::class, 'idanagrafica'); + } + + public function tipo() + { + return $this->belongsTo(Tipo::class, 'idtipoordine'); + } + + public function stato() + { + return $this->belongsTo(Stato::class, 'idstatoordine'); + } + + public function articoli() + { + return $this->hasMany(Components\Articolo::class, 'idordine'); + } + + public function righe() + { + return $this->hasMany(Components\Riga::class, 'idordine'); + } + + public function descrizioni() + { + return $this->hasMany(Components\Descrizione::class, 'idordine'); + } + + public function scontoGlobale() + { + return $this->hasOne(Components\Sconto::class, 'idordine'); + } + + // Metodi statici + + /** + * Calcola il nuovo numero di ordine. + * + * @param string $data + * @param string $direzione + * @param int $id_segment + * + * @return string + */ + public static function getNextNumero($data, $direzione) + { + $database = database(); + + $rs = $database->fetchOne("SELECT IFNULL(MAX(numero), '0') AS max_numero FROM or_ordini WHERE YEAR(data) = :year AND idtipoordine IN(SELECT id FROM or_tipiordine WHERE dir = :direction) ORDER BY CAST(numero AS UNSIGNED) DESC", [ + ':year' => date('Y', strtotime($data)), + ':direction' => $direzione, + ]); + + return intval($rs['max_numero']) + 1; + } + + /** + * Calcola il nuovo numero secondario di ordine. + * + * @param string $data + * @param string $direzione + * + * @return string + */ + public static function getNextNumeroSecondario($data, $direzione) + { + if ($direzione == 'uscita') { + return ''; + } + + $database = database(); + + $maschera = setting('Formato numero secondario ordine'); + + $ultimo_ordine = $database->fetchOne('SELECT numero_esterno FROM or_ordini WHERE YEAR(data) = :year AND idtipoordine IN (SELECT id FROM or_tipiordine WHERE dir = :direction) '.Generator::getMascheraOrder($maschera, 'numero_esterno'), [ + ':year' => date('Y', strtotime($data)), + ':direction' => $direzione, + ]); + + $numero_esterno = Generator::generate($maschera, $ultimo_ordine['numero_esterno'], 1, Generator::dateToPattern($data)); + + return $numero_esterno; + } +} diff --git a/modules/ordini/src/Stato.php b/modules/ordini/src/Stato.php new file mode 100644 index 000000000..92413195a --- /dev/null +++ b/modules/ordini/src/Stato.php @@ -0,0 +1,15 @@ +hasMany(Ordine::class, 'idstatoordine'); + } +} diff --git a/modules/ordini/src/Tipo.php b/modules/ordini/src/Tipo.php new file mode 100644 index 000000000..77d8a7e51 --- /dev/null +++ b/modules/ordini/src/Tipo.php @@ -0,0 +1,15 @@ +hasMany(Ordine::class, 'idtipoordine'); + } +}