From 9fb0d120c3339381c462aaf82177be3b67f85db8 Mon Sep 17 00:00:00 2001 From: Thomas Zilio Date: Mon, 17 Feb 2020 18:43:49 +0100 Subject: [PATCH] Aggiornamento Pianificazione fatturazione di Contratti --- config/namespaces.php | 1 + include/src/Components/Description.php | 16 + include/src/Components/Row.php | 2 +- modules/anagrafiche/add.php | 24 +- modules/contratti/ajax.php | 26 -- modules/contratti/edit.php | 3 +- modules/contratti/js/contratti_helper.js | 44 -- modules/contratti/plugins/addfattura.php | 60 --- .../contratti.fatturaordiniservizio.php | 378 ------------------ modules/contratti/src/Contratto.php | 6 + .../widgets/contratti.ratecontrattuali.php | 8 +- modules/fatture/actions.php | 2 +- .../pianificazione_fatturazione/actions.php | 96 +++++ .../add_pianificazione.php | 94 +++++ .../crea_fattura.php | 68 ++++ plugins/pianificazione_fatturazione/edit.php | 110 +++++ .../src/Pianificazione.php | 104 +++++ plugins/pianificazione_interventi/actions.php | 4 +- plugins/pianificazione_interventi/edit.php | 7 +- update/2_4_14.sql | 7 + 20 files changed, 527 insertions(+), 533 deletions(-) delete mode 100755 modules/contratti/js/contratti_helper.js delete mode 100755 modules/contratti/plugins/addfattura.php delete mode 100755 modules/contratti/plugins/contratti.fatturaordiniservizio.php create mode 100755 plugins/pianificazione_fatturazione/actions.php create mode 100644 plugins/pianificazione_fatturazione/add_pianificazione.php create mode 100755 plugins/pianificazione_fatturazione/crea_fattura.php create mode 100755 plugins/pianificazione_fatturazione/edit.php create mode 100755 plugins/pianificazione_fatturazione/src/Pianificazione.php diff --git a/config/namespaces.php b/config/namespaces.php index e4da1fcae..42ae46b66 100755 --- a/config/namespaces.php +++ b/config/namespaces.php @@ -36,5 +36,6 @@ return [ 'plugins/receiptFE' => 'Plugins\ReceiptFE', 'plugins/dichiarazioni_intento' => 'Plugins\DichiarazioniIntento', 'plugins/pianificazione_interventi' => 'Plugins\PianificazioneInterventi', + 'plugins/pianificazione_fatturazione' => 'Plugins\PianificazioneFatturazione', 'plugins/statistiche_articoli' => 'Plugins\StatisticheArticoli', ]; diff --git a/include/src/Components/Description.php b/include/src/Components/Description.php index e36192563..20774e66e 100755 --- a/include/src/Components/Description.php +++ b/include/src/Components/Description.php @@ -113,6 +113,22 @@ abstract class Description extends Model return $result; } + public function toArray() + { + $array = parent::toArray(); + + $result = array_merge($array, [ + 'spesa' => $this->spesa, + 'imponibile' => $this->imponibile, + 'sconto' => $this->sconto, + 'totale_imponibile' => $this->totale_imponibile, + 'iva' => $this->iva, + 'totale' => $this->totale, + ]); + + return $result; + } + /** * Imposta il proprietario dell'oggetto e l'ordine relativo all'interno delle righe. */ diff --git a/include/src/Components/Row.php b/include/src/Components/Row.php index 6561a5fe1..ad82a526d 100755 --- a/include/src/Components/Row.php +++ b/include/src/Components/Row.php @@ -105,7 +105,7 @@ abstract class Row extends Description public function getIvaAttribute() { - return ($this->totale_imponibile) * $this->aliquota->percentuale / 100; + return $this->iva_unitaria * $this->qta; } public function getIvaDetraibileAttribute() diff --git a/modules/anagrafiche/add.php b/modules/anagrafiche/add.php index 4ac4bf4f8..365d6ac55 100755 --- a/modules/anagrafiche/add.php +++ b/modules/anagrafiche/add.php @@ -23,11 +23,11 @@ echo '
- +
{[ "type": "text", "label": "'.tr('Cognome').'", "name": "cognome", "required": 0 ]}
- +
{[ "type": "text", "label": "'.tr('Nome').'", "name": "nome", "id": "nome_", "required": 0 ]}
@@ -53,12 +53,12 @@ echo '
{[ "type": "text", "label": "'.tr('Codice fiscale').'", "maxlength": 16, "name": "codice_fiscale", "class": "text-center alphanumeric-mask", "validation": "codice_fiscale" ]}
- +
{[ "type": "select", "label": "'.tr('Tipologia').'", "name": "tipo", "values": "list=\"\": \"'.tr('Non specificato').'\", \"Azienda\": \"'.tr('Azienda').'\", \"Privato\": \"'.tr('Privato').'\", \"Ente pubblico\": \"'.tr('Ente pubblico').'\"" ]}
- - + +
@@ -80,11 +80,11 @@ echo '
- +
{[ "type": "select", "label": "'.tr('Nazione').'", "name": "id_nazione", "values": "query=SELECT id AS id, CONCAT_WS(\' - \', iso2, nome) AS descrizione FROM an_nazioni ORDER BY CASE WHEN iso2=\'IT\' THEN -1 ELSE iso2 END" ]}
- +
{[ "type": "text", "label": "'.tr('Telefono').'", "name": "telefono", "class": "text-center", "icon-before": "" ]}
@@ -93,13 +93,13 @@ echo '
- +
- +
{[ "type": "text", "label": "'.tr('Email').'", "name": "email", "class": "email-mask", "placeholder":"casella@dominio.ext", "icon-before": "" ]}
- +
{[ "type": "text", "label": "'.tr('PEC').'", "name": "pec", "class": "email-mask", "placeholder":"pec@dominio.ext", "icon-before": "" ]}
'; @@ -114,8 +114,8 @@ echo '
'; -echo - '
+echo ' +
diff --git a/modules/contratti/ajax.php b/modules/contratti/ajax.php index 15c4f2624..edf62b5d7 100755 --- a/modules/contratti/ajax.php +++ b/modules/contratti/ajax.php @@ -8,29 +8,3 @@ if (get('op') == 'get_costo_orario') { $rs = $dbo->fetchArray('SELECT costo_orario FROM in_tipiintervento WHERE idtipointervento='.prepare($idtipointervento)); echo $rs[0]['costo_orario']; } - -// Copia ordine di servizio da un impianto ad un altro -elseif (get('op') == 'get_pianificazione_os') { - $idcontratto = get('idcontratto'); - $matricola_src = get('matricola_src'); - - $ordiniservizio = []; - - if (!empty($matricola_src)) { - // Leggo tutti gli ordini di servizio creati per matricola_src - $rs = $dbo->fetchArray('SELECT * FROM co_ordiniservizio WHERE idcontratto='.prepare($idcontratto).' AND idimpianto='.prepare($matricola_src)); - - for ($i = 0; $i < sizeof($rs); ++$i) { - // Leggo tutte le voci di servizio - $rs2 = $dbo->fetchArray('SELECT (SELECT id FROM in_vociservizio WHERE descrizione=voce) AS idvoce FROM co_ordiniservizio_vociservizio WHERE idordineservizio='.prepare($rs[$i]['id'])); - - for ($v = 0; $v < sizeof($rs2); ++$v) { - $ordiniservizio[] = date('Ym', strtotime($rs[$i]['data_scadenza'])).':'.$rs2[$v]['idvoce']; - } - } - - // Ritorno l'array con le combinazioni di voce e mese pianificato - echo implode(',', $ordiniservizio); - exit(); - } -} diff --git a/modules/contratti/edit.php b/modules/contratti/edit.php index e3b7323cf..9813db6c2 100755 --- a/modules/contratti/edit.php +++ b/modules/contratti/edit.php @@ -8,8 +8,7 @@ unset($_SESSION['superselect']['idsede_destinazione']); unset($_SESSION['superselect']['idanagrafica']); $_SESSION['superselect']['idanagrafica'] = $record['idanagrafica']; -?> - +?>
diff --git a/modules/contratti/js/contratti_helper.js b/modules/contratti/js/contratti_helper.js deleted file mode 100755 index 27329d80a..000000000 --- a/modules/contratti/js/contratti_helper.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - Legge la matricola data e ricrea le spunte e selezioni della matricola data nella nuova pianificazione, - in modo da poter creare un'altra pianificazione simile (o modificando quella appena copiata) -*/ -function copia_pianificazione_os(idcontratto, matricola_src) { - $.get(globals.rootdir + '/modules/contratti/ajax.php?op=get_pianificazione_os&idcontratto=' + idcontratto + '&matricola_src=' + matricola_src, function (data, response) { - if (response == 'success') { - //Nascondo tutte le voci pianificate - $('div[id*=voce_]').addClass('hide'); - - //Tolgo tutte le spunte - $('div[id*=voce_] input[id*=m_]').removeAttr('checked'); - - //Deseleziono tutte le voci della lista '; - -// Data -echo ' -
-
- {[ "type": "date", "label": "'.tr('Data').'", "name": "data", "required": 1, "class": "text-center", "value": "-now-" ]} -
'; - -// Tipo di documento -echo ' -
- {[ "type": "select", "label": "'.tr('Tipo di fattura').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT * FROM co_tipidocumento WHERE dir=\'entrata\'" ]} -
'; - -// Sezionale -echo ' -
- {[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module='.Modules::get('Fatture di vendita')['id'].' ORDER BY name", "value":"'.$_SESSION['module_'.Modules::get('Fatture di vendita')['id']]['id_segment'].'" ]} -
- -
'; - -// Note -echo ' -
-
- {[ "type": "textarea", "label": "'.tr('Descrizione').'", "name": "note", "value": "Rata '.$n_rata.' del contratto numero '.$numero.', zona '.$zona.'" ]} -
-
'; - -echo ' - -
-
- -
-
-
'; - -echo ' - '; diff --git a/modules/contratti/plugins/contratti.fatturaordiniservizio.php b/modules/contratti/plugins/contratti.fatturaordiniservizio.php deleted file mode 100755 index 55327b58e..000000000 --- a/modules/contratti/plugins/contratti.fatturaordiniservizio.php +++ /dev/null @@ -1,378 +0,0 @@ - $zone) { - foreach ($zone as $n => $idzona) { - $dbo->query('DELETE FROM co_ordiniservizio_pianificazionefatture WHERE idzona='.prepare($idzona).' AND iddocumento=0 AND idcontratto='.prepare($id_record)); - } - } - - // Ciclo fra le voci in arrivo dal form - foreach (post('zona') as $data_scadenza => $zone) { - // Ogni data può avere più zone da pianificare - foreach ($zone as $n => $idzona) { - // Aggiunta pianificazione solo se la zona è spuntata - if (in_array($idzona, post('idzona'))) { - // Creazione pianificazione - $dbo->query('INSERT INTO co_ordiniservizio_pianificazionefatture(idcontratto, data_scadenza, idzona, iddocumento) VALUES('.prepare($id_record).', '.prepare($data_scadenza).', '.prepare($idzona).', 0)'); - } - - $prev_data = $data_scadenza; - } - } - - flash()->info(tr('Pianificazione generata correttamente!')); -} - -// Eliminazione pianificazione specifica -elseif (get('op') == 'del_pianificazione') { - $idpianificazione = get('idpianificazione'); - - $n = $dbo->fetchNum('SELECT id FROM co_ordiniservizio_pianificazionefatture WHERE id='.prepare($idpianificazione)); - - if ($n == 1) { - // Eliminazione ordine di servizio - if ($dbo->query('DELETE FROM co_ordiniservizio_pianificazionefatture WHERE id='.prepare($idpianificazione))) { - flash()->info(tr('Pianificazione eliminata correttamente!')); - } - } -} - -// Creazione fattura pianificata -elseif (get('op') == 'addfattura') { - $idpianificazione = get('idpianificazione'); - $descrizione = post('note'); - $data = post('data'); - $idtipodocumento = post('idtipodocumento'); - $note = post('note'); - - // Lettura idanagrafica - $rs = $dbo->fetchArray('SELECT idanagrafica FROM co_contratti WHERE id='.prepare($id_record)); - $idanagrafica = $rs[0]['idanagrafica']; - - $dir = 'entrata'; - $idconto = setting('Conto predefinito fatture di vendita'); - $numero = get_new_numerofattura($data); - $id_segment = post('id_segment'); - $numero_esterno = get_new_numerosecondariofattura($data); - - // Tipo di pagamento + banca predefinite dall'anagrafica - $query = 'SELECT id, (SELECT idbanca_vendite FROM an_anagrafiche WHERE idanagrafica = '.prepare($idanagrafica).') AS idbanca FROM co_pagamenti WHERE id = (SELECT idpagamento_vendite AS pagamento FROM an_anagrafiche WHERE idanagrafica='.prepare($idanagrafica).')'; - $rs = $dbo->fetchArray($query); - $idpagamento = $rs[0]['id']; - $idbanca = $rs[0]['idbanca']; - - // Se la fattura è di vendita e non è stato associato un pagamento predefinito al cliente leggo il pagamento dalle impostazioni - if ($dir == 'entrata' && $idpagamento == '') { - $idpagamento = setting('Tipo di pagamento predefinito'); - } - - // Se non è impostata la banca dell'anagrafica, uso quella del pagamento. - if (empty($idbanca)) { - // Banca predefinita del pagamento - $query = 'SELECT id FROM co_banche WHERE id_pianodeiconti3 = (SELECT idconto_vendite FROM co_pagamenti WHERE id = '.prepare($idpagamento).')'; - $rs = $dbo->fetchArray($query); - $idbanca = $rs[0]['id']; - } - - $query = 'INSERT INTO co_documenti(numero, numero_esterno, idanagrafica, idtipodocumento, idpagamento, data, idstatodocumento, note, idsede_destinazione, id_segment, idconto, idbanca) VALUES ('.prepare($numero).', '.prepare($numero_esterno).', '.prepare($idanagrafica).', '.prepare($idtipodocumento).', '.prepare($idpagamento).', '.prepare($data).", (SELECT `id` FROM `co_statidocumento` WHERE `descrizione`='Bozza'), ".prepare($note).', (SELECT idsede_fatturazione FROM an_anagrafiche WHERE idanagrafica='.prepare($idanagrafica).'), '.prepare($id_segment).', '.prepare($idconto).', '.prepare($idbanca).' )'; - $dbo->query($query); - $iddocumento = $dbo->lastInsertedID(); - - // Imposto l'iddocumento anche sulla pianificazione, giusto per tener traccia della fattura generata - $dbo->query('UPDATE co_ordiniservizio_pianificazionefatture SET iddocumento='.prepare($iddocumento).' WHERE id='.prepare($idpianificazione)); - - // Leggo quante rate si vogliono pagare per dividerle per mese - $rs = $dbo->fetchArray('SELECT id FROM co_ordiniservizio_pianificazionefatture WHERE idcontratto='.prepare($id_record)); - - // L'importo deve essere diviso per il numero di mesi - $rs2 = $dbo->fetchArray('SELECT SUM(subtotale) AS totale FROM co_righe_contratti WHERE idcontratto='.prepare($id_record)); - $importo = $rs2[0]['totale'] / sizeof($rs); - - // Lettura iva del cliente o predefinita - $rs2 = $dbo->fetchArray('SELECT idiva_vendite AS idiva FROM an_anagrafiche WHERE idanagrafica='.prepare($idanagrafica)); - $idiva = $rs2[0]['idiva']; - - if ($idiva != 0) { - $rs2 = $dbo->fetchArray('SELECT * FROM co_iva WHERE id='.prepare($idiva)); - } else { - $rs2 = $dbo->fetchArray('SELECT * FROM co_iva WHERE id='.prepare(setting('Iva predefinita'))); - } - - $desc_iva = $rs2[0]['descrizione']; - - $iva = $importo / 100 * $rs2[0]['percentuale']; - $iva_indetraibile = $importo / 100 * $rs2[0]['indetraibile']; - - // Inserimento riga in fattura - $dbo->query('INSERT INTO co_righe_documenti(iddocumento, idcontratto, descrizione, desc_iva, iva, iva_indetraibile, subtotale, um, qta, `order`) VALUES('.prepare($iddocumento).', '.prepare($id_record).', '.prepare($descrizione).', '.prepare($desc_iva).', '.prepare($iva).', '.prepare($iva_indetraibile).', '.prepare($importo).", '-', 1, (SELECT IFNULL(MAX(`order`) + 1, 0) FROM co_righe_documenti AS t WHERE iddocumento=".prepare($iddocumento).'))'); - - redirect($rootdir.'/editor.php?id_module='.Modules::get('Fatture di vendita')['id'].'&id_record='.$iddocumento.'&dir=entrata'); - exit(); -} - -echo ' -
-
-

'.tr('Pianificazione fatturazione').'

-
-
'; - -echo ' -

'.tr('Qui puoi programmare la fatturazione del contratto').'.

'; - -/* - Fatture pianificate -*/ -$rs = $dbo->fetchArray('SELECT *, (SELECT SUM(subtotale) FROM co_righe_contratti WHERE idcontratto='.prepare($id_record).') AS budget_contratto, (SELECT descrizione FROM an_zone WHERE id=idzona) AS zona FROM co_ordiniservizio_pianificazionefatture WHERE idcontratto='.prepare($id_record).' ORDER BY data_scadenza ASC'); - -if (empty($rs)) { - echo ' -

'.tr('Non sono ancora state pianificate fatture').'...

'; -} else { - $rs2 = $dbo->fetchArray('SELECT * FROM co_ordiniservizio_pianificazionefatture WHERE idcontratto='.prepare($id_record).' ORDER BY idzona'); - - for ($i = 0; $i < sizeof($rs2); ++$i) { - // Leggo quante rate sono pianificate per dividere l'importo delle sedi in modo corretto - ++$n_rate[$rs2[$i]['idzona']]; - - // Leggo il totale già fatturato per questa zona per toglierlo dalla divisione (totale/n_rate) - $rs3 = $dbo->fetchArray('SELECT SUM(subtotale-sconto) AS totale FROM co_righe_documenti WHERE iddocumento IN (SELECT iddocumento FROM co_ordiniservizio_pianificazionefatture WHERE iddocumento='.prepare($rs2[$i]['iddocumento']).')'); - $gia_fatturato[$rs2[$i]['idzona']] += $rs3[0]['totale']; - } - - echo ' - - - - - - - - - '; - - $prev_mese = ''; - $n_rata = 0; - - for ($i = 0; $i < sizeof($rs); ++$i) { - // Lettura numero di sedi in cui si sono pianificati ordini di servizio per la zona corrente - if (!empty($rs[$i]['idzona'])) { - $n_sedi_pianificate = $dbo->fetchNum('SELECT DISTINCT(idsede) FROM my_impianti WHERE id IN (SELECT idimpianto FROM co_ordiniservizio WHERE idcontratto='.prepare($id_record).') AND idsede IN(SELECT id FROM an_sedi WHERE idzona='.prepare($rs[$i]['idzona']).')'); - - // Verifico se ci sono impianti in questa zona legati alla sede legale - $n_sedi_pianificate += $dbo->fetchNum('SELECT DISTINCT(idsede) FROM my_impianti WHERE id IN (SELECT idimpianto FROM co_ordiniservizio WHERE idcontratto='.prepare($id_record).') AND idsede=(SELECT idsede FROM an_anagrafiche WHERE idanagrafica=(SELECT idanagrafica FROM co_contratti WHERE id='.prepare($id_record).') AND idzona='.prepare($rs[$i]['idzona']).') AND idsede=0'); - } - // Fix nel caso non siano previste sedi pianificate (l'eventuale 0 portava a problemi nel calcolo dell'importo) - $n_sedi_pianificate = ($n_sedi_pianificate < 1) ? 1 : $n_sedi_pianificate; - // else{ - // $n_sedi_pianificate = $dbo->fetchNum("SELECT (idsede) FROM my_impianti WHERE id IN (SELECT idimpianto FROM co_ordiniservizio WHERE idcontratto=\"".$id_record."\") AND idsede=0"); - // } - - echo ' - - '; - } - echo ' - '; - - // Sede - if ($rs[$i]['zona'] == '') { - $zona = 'Altro'; - } else { - $zona = $rs[$i]['zona']; - } - - if ($n_sedi_pianificate == 1) { - $n_sedi = tr('1 sede'); - } else { - $n_sedi = tr('_NUM_ sedi', [ - '_NUM_' => $n_sedi_pianificate, - ]); - } - - echo ' - '; - - /* - Importo - */ - // Se è stata emessa una fattura, bisogna utilizzare il totale della fattura da scalare al totale pianificato - if ($rs[$i]['iddocumento'] != 0) { - $rs2 = $dbo->fetchArray('SELECT SUM(subtotale-sconto) AS totale FROM co_righe_documenti WHERE iddocumento='.prepare($rs[$i]['iddocumento'])); - $importo = $rs2[0]['totale']; - } else { - // $importo = ($rs[$i]['budget_contratto'] * $n_sedi_pianificate / $n_rate[ $rs[$i]['idzona'] ]) - ($gia_fatturato[ $rs[$i]['idzona'] ] * $n_sedi_pianificate / sizeof($gia_fatturato[ $rs[$i]['idzona'] ]) ); - $importo = ($rs[$i]['budget_contratto'] * $n_sedi_pianificate / $n_rate[$rs[$i]['idzona']]); - } - - echo ' - '; - - // Documento collegato (fattura) - if ($rs[$i]['iddocumento'] != 0) { - $rsf = $dbo->fetchArray('SELECT numero, numero_esterno, data, (SELECT SUM(subtotale) FROM co_righe_documenti WHERE iddocumento=co_documenti.id) AS imponibile, (SELECT icona FROM co_statidocumento WHERE id=co_documenti.idstatodocumento) AS icona, (SELECT descrizione FROM co_statidocumento WHERE id=co_documenti.idstatodocumento) AS stato FROM co_documenti WHERE id='.prepare($rs[$i]['iddocumento'])); - - if ($rsf[0]['numero_esterno'] != '') { - $numero_doc = $rsf[0]['numero_esterno']; - } else { - $numero_doc = $rsf[0]['numero']; - } - - $documento = Modules::link('Fatture di vendita', $rs[$i]['iddocumento'], tr('Fattura num. _NUM_ del _DATE_', [ - '_NUM_' => $numero_doc, - '_DATE_' => Translator::dateToLocale($rsf[0]['data']), - ])); - - $stato = ' '.$rsf[0]['stato']; - } else { - $documento = ''; - $stato = ' '.tr('Non ancora fatturato'); - } - - // Link a fattura - echo ' - '; - - // Stato - echo ' - '; - - // Funzioni - echo ' - - '; - - $prev_mese = $rs[$i]['data_scadenza']; - } - echo ' -
'.tr('Scadenza').''.tr('Zona').''.tr('Importo').''.tr('Documento').''.tr('Stato').'
'; - // Data scadenza - if ($prev_mese != $rs[$i]['data_scadenza']) { - ++$n_rata; - echo ' - '.$mesi[intval(date('m', strtotime($rs[$i]['data_scadenza']))) - 1].' '.date('Y', strtotime($rs[$i]['data_scadenza'])).''.$zona.' ('.$n_sedi.') - '.moneyFormat($importo).'
- '.moneyFormat($rs[$i]['budget_contratto']).' x '.$n_sedi_pianificate.' sedi / '.$n_rate[$rs[$i]['idzona']].' rate'.$extra.' -
'.$documento.''.$stato.''; - if ($rs[$i]['iddocumento'] == 0) { - // Creazione fattura - echo " - '; - - // Eliminazione pianificazione - echo ' - - - '; - } - - echo ' -
'; -} -echo ' -

'; - -/* - Schema per pianificare la fatturazione per zona -*/ -$rs = $dbo->fetchArray('SELECT id, descrizione FROM an_zone WHERE ( id IN (SELECT idzona FROM an_sedi WHERE id IN (SELECT idsede FROM my_impianti WHERE id IN (SELECT idimpianto FROM co_ordiniservizio WHERE idcontratto='.prepare($id_record).'))) ) OR ( id=(SELECT idzona FROM an_anagrafiche WHERE idanagrafica=(SELECT idanagrafica FROM co_contratti WHERE id='.prepare($id_record).") AND idzona=an_zone.id) ) UNION SELECT 0, 'Altro'"); - -if (sizeof($rs) == 0) { - echo ' -

'.tr('Non sono ancora stati pianificati ordini di servizio').'...

'; -} - -// Elenco voci di servizio con mesi in cui eseguirle -else { - // Calcolo mese iniziale e finale del contratto - $rs2 = $dbo->fetchArray('SELECT data_accettazione, data_conclusione, TIMESTAMPDIFF( MONTH, data_accettazione, data_conclusione ) AS mesi FROM co_contratti WHERE id='.prepare($id_record)); - $n_mesi = $rs2[0]['mesi'] + 1; - $mese_start = date('m', strtotime($rs2[0]['data_accettazione'])); - - echo " - -
'; - - echo " -
- "; - - // Indice zone fatturabili - echo ' -
-
- {[ "type": "select", "label": "'.tr('Zone per le quali pianificare la fatturazione').'", "name": "idzona[]", "class": "unblockable", "values": "query=SELECT id, descrizione FROM an_zone WHERE (id IN (SELECT idzona FROM an_sedi WHERE id IN (SELECT idsede FROM my_impianti WHERE id IN (SELECT idimpianto FROM co_ordiniservizio WHERE idcontratto='.prepare($id_record).')))) OR ( id=(SELECT idzona FROM an_anagrafiche WHERE idanagrafica=(SELECT idanagrafica FROM co_contratti WHERE id='.prepare($id_record).') AND idzona=an_zone.id) ) UNION SELECT 0, \'Altro\'", "multiple": 1, "extra": "onchange=\"$(this).find(\'option\').each( function(){ if( $(this).is(\':selected\') ){ $(\'#zona_\'+$(this).val()).removeClass(\'hide\'); }else{ $(\'#zona_\'+$(this).val()).addClass(\'hide\'); } });\"" ]} -
-
'; - - // Zone - for ($i = 0; $i < sizeof($rs); ++$i) { - echo ' -
- '.$rs[$i]['descrizione'].' -
-
'; - - for ($j = 0; $j < $n_mesi; ++$j) { - echo ' -
- -
'; - } - - echo ' -
-
'; - } - - echo " - -
-
"; - - $disabled_pianificazione = $record['is_fatturabile'] && !empty($rs_documento) && !empty($record['data_conclusione']) && !empty($record['data_accettazione']); - // Pianificazione - echo " - '; - - echo ' -
'; -} - -echo ' -
-
'; diff --git a/modules/contratti/src/Contratto.php b/modules/contratti/src/Contratto.php index d3c4d7a69..d1146f1e2 100755 --- a/modules/contratti/src/Contratto.php +++ b/modules/contratti/src/Contratto.php @@ -8,6 +8,7 @@ use Common\Document; use Modules\Anagrafiche\Anagrafica; use Modules\Interventi\Intervento; use Modules\TipiIntervento\Tipo as TipoSessione; +use Plugins\PianificazioneFatturazione\Pianificazione; use Plugins\PianificazioneInterventi\Promemoria; use Traits\RecordTrait; use Util\Generator; @@ -149,6 +150,11 @@ class Contratto extends Document return $this->hasMany(Promemoria::class, 'idcontratto'); } + public function pianificazioni() + { + return $this->hasMany(Pianificazione::class, 'idcontratto'); + } + public function fixBudget() { $this->budget = $this->totale_imponibile ?: 0; diff --git a/modules/contratti/widgets/contratti.ratecontrattuali.php b/modules/contratti/widgets/contratti.ratecontrattuali.php index 21cb0278c..9830a55f5 100755 --- a/modules/contratti/widgets/contratti.ratecontrattuali.php +++ b/modules/contratti/widgets/contratti.ratecontrattuali.php @@ -21,18 +21,18 @@ $mesi = [ // Righe inserite //idcontratto IN( SELECT id FROM co_contratti WHERE idstato IN(SELECT id FROM co_staticontratti WHERE is_pianificabile = 1) ) AND $qp = "SELECT *, - (SELECT SUM(subtotale) FROM co_righe_contratti WHERE idcontratto=co_ordiniservizio_pianificazionefatture.idcontratto) AS budget_contratto, + (SELECT SUM(subtotale) FROM co_righe_contratti WHERE idcontratto=co_fatturazione_contratti.idcontratto) AS budget_contratto, DATE_FORMAT(data_scadenza, '%m-%Y') AS mese, (SELECT idanagrafica FROM co_contratti WHERE id=idcontratto) AS idcliente, (SELECT nome FROM co_contratti WHERE id=idcontratto) AS nome, (SELECT ragione_sociale FROM an_anagrafiche WHERE idanagrafica=(SELECT idanagrafica FROM co_contratti WHERE id=idcontratto)) AS ragione_sociale, - (SELECT descrizione FROM an_zone WHERE id=co_ordiniservizio_pianificazionefatture.idzona) AS zona -FROM co_ordiniservizio_pianificazionefatture WHERE co_ordiniservizio_pianificazionefatture.iddocumento=0 ORDER BY data_scadenza ASC, idcliente ASC"; + (SELECT descrizione FROM an_zone WHERE id=co_fatturazione_contratti.idzona) AS zona +FROM co_fatturazione_contratti WHERE co_fatturazione_contratti.iddocumento=0 ORDER BY data_scadenza ASC, idcliente ASC"; $rsp = $dbo->fetchArray($qp); if (!empty($rsp)) { // Lettura numero di rate e totale già fatturato - $rs2 = $dbo->fetchArray('SELECT * FROM co_ordiniservizio_pianificazionefatture'); + $rs2 = $dbo->fetchArray('SELECT * FROM co_fatturazione_contratti'); for ($j = 0; $j < sizeof($rs2); ++$j) { // Leggo quante rate sono pianificate per dividere l'importo delle sedi in modo corretto diff --git a/modules/fatture/actions.php b/modules/fatture/actions.php index 2d40b2d46..bc01119d2 100755 --- a/modules/fatture/actions.php +++ b/modules/fatture/actions.php @@ -194,7 +194,7 @@ switch (post('op')) { $dbo->query('DELETE FROM co_movimenti WHERE iddocumento='.prepare($id_record)); // Azzeramento collegamento della rata contrattuale alla pianificazione - $dbo->query('UPDATE co_ordiniservizio_pianificazionefatture SET iddocumento=0 WHERE iddocumento='.prepare($id_record)); + $dbo->query('UPDATE co_fatturazione_contratti SET iddocumento=0 WHERE iddocumento='.prepare($id_record)); flash()->info(tr('Fattura eliminata!')); } catch (InvalidArgumentException $e) { diff --git a/plugins/pianificazione_fatturazione/actions.php b/plugins/pianificazione_fatturazione/actions.php new file mode 100755 index 000000000..fa626a2c0 --- /dev/null +++ b/plugins/pianificazione_fatturazione/actions.php @@ -0,0 +1,96 @@ + $selezione) { + $data_scadenza = $periodi[$key]; + ++$numero_fatture; + + // Creazione pianificazione + Pianificazione::build($contratto, $data_scadenza); + } + + if ($numero_fatture > 0) { + // Rimozione righe precedenti del contratto + $righe_contratto = $contratto->getRighe(); + $iva_righe = collect($righe_contratto->toArray())->groupBy('idiva'); + foreach ($righe_contratto as $riga) { + $riga->delete(); + } + + // Creazione nuove righe + $descrizioni = post('descrizione'); + $qta = post('qta'); + foreach ($iva_righe as $id_iva => $righe) { + $iva = $righe->first()->aliquota; + $righe = $righe->toArray(); + + $totale = sum(array_column($righe, setting('Utilizza prezzi di vendita con IVA incorporata') ? 'totale' : 'totale_imponibile')); + + $qta_riga = $qta[$id_iva]; + $descrizione_riga = $descrizioni[$id_iva]; + + $prezzo_unitario = $totale / $qta_riga / $numero_fatture; + + for($rata = 1; $rata <= $numero_fatture; $rata++) { + $riga = Riga::build($contratto); + + $riga->descrizione = $descrizione_riga; + $riga->id_iva = $id_iva; + $riga->prezzo_unitario = $prezzo_unitario; + $riga->qta = $qta_riga; + + $riga->save(); + } + } + } + + break; + + case 'add_fattura': + $contratto = Contratto::find($id_record); + + $rata = post('rata'); + $pianificazione = $contratto->pianificazioni[$rata]; + + $data = post('data'); + $id_segment = post('id_segment'); + $tipo = Tipo::find(post('idtipodocumento')); + + // Creazione fattura + $fattura = Fattura::build($contratto->anagrafica, $tipo, $data, $id_segment); + + // Copia righe + $righe = $pianificazione->getRighe(); + foreach ($righe as $riga) { + $copia = $riga->copiaIn($fattura, $riga->qta); + + // Aggiornamento movimentazioni + if ($copia->isArticolo()) { + $copia->movimenta($copia->qta); + } + } + + // Salvataggio fattura nella pianificazione + $pianificazione->fattura()->associate($fattura); + $pianificazione->save(); + + break; +} diff --git a/plugins/pianificazione_fatturazione/add_pianificazione.php b/plugins/pianificazione_fatturazione/add_pianificazione.php new file mode 100644 index 000000000..8d8c26ec9 --- /dev/null +++ b/plugins/pianificazione_fatturazione/add_pianificazione.php @@ -0,0 +1,94 @@ + + + + + + + + + +
+
+ +
+
+'; + +echo ' +'; diff --git a/plugins/pianificazione_fatturazione/crea_fattura.php b/plugins/pianificazione_fatturazione/crea_fattura.php new file mode 100755 index 000000000..ede5a66a8 --- /dev/null +++ b/plugins/pianificazione_fatturazione/crea_fattura.php @@ -0,0 +1,68 @@ +pianificazioni[$rata]; + +$module_fattura = Modules::get('Fatture di vendita'); + +echo ' +
+ + + + + + '; + +// Data +echo ' +
+
+ {[ "type": "date", "label": "'.tr('Data').'", "name": "data", "required": 1, "class": "text-center", "value": "-now-" ]} +
'; + +// Tipo di documento +echo ' +
+ {[ "type": "select", "label": "'.tr('Tipo di fattura').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT * FROM co_tipidocumento WHERE dir=\'entrata\'" ]} +
'; + +// Sezionale +echo ' +
+ {[ "type": "select", "label": "'.tr('Sezionale').'", "name": "id_segment", "required": 1, "values": "query=SELECT id, name AS descrizione FROM zz_segments WHERE id_module='.$module_fattura['id'].' ORDER BY name", "value":"'.$_SESSION['module_'.$module_fattura['id']]['id_segment'].'" ]} +
+
'; + +// Descrizione fattura +$descrizione = tr('Rata _N_ del contratto numero _NUM_', [ + '_N_' => ($rata + 1), + '_NUM_' => $contratto->numero, +]); + +echo ' +
+
+ {[ "type": "textarea", "label": "'.tr('Note della fattira').'", "name": "note", "value": "'.$descrizione.'" ]} +
+
'; + +echo ' + +
+
+ +
+
+
'; + +echo ' +'; diff --git a/plugins/pianificazione_fatturazione/edit.php b/plugins/pianificazione_fatturazione/edit.php new file mode 100755 index 000000000..2fc9dc7d1 --- /dev/null +++ b/plugins/pianificazione_fatturazione/edit.php @@ -0,0 +1,110 @@ +stato->is_pianificabile && !empty($contratto['data_accettazione']); // Contratto permette la pianificazione + +$stati_pianificabili = Stato::where('is_pianificabile', 1)->get(); +$elenco_stati = $stati_pianificabili->implode('descrizione', ', '); + +echo ' +

'.tr('Qui puoi pianificare la suddivisione del budget del contratto in rate uguali fatturabili in modo separato').'. '.tr('Questa procedura può essere effettuata solo una volta, e sovrascriverà in modo irreversibile tutte le righe del contratto').'.

+

'.tr('Per poter procedere, il contratto deve avere data accettazione e data conclusione definita ed essere in uno dei seguenti stati: _LINK_', [ + '_LINK_' => ''.$elenco_stati.'', +]).'.

+ +
+ '.tr("Tutte le righe del contratto vengono convertite in righe generiche, rendendo impossibile risalire ad eventuali articoli utilizzati all'interno del contratto e pertanto non movimentando il magazzino").'. +
'; + +$pianificazioni = $contratto->pianificazioni; +if (!$pianificazioni->isEmpty()) { + echo ' +
+ + + + + + + + + + '; + + $previous = null; + foreach ($pianificazioni as $rata => $pianificazione){ + echo ' + + + + '; + + // Documento collegato + echo ' + '; + + // Creazione fattura + echo ' + + '; + } + + echo ' + +
'.tr('Scadenza').''.tr('Importo').''.tr('Documento').'#
'; + + // Data scadenza + if (!$pianificazione->data_scadenza->equalTo($previous)) { + $previous = $pianificazione->data_scadenza; + echo ' + '.$pianificazione->data_scadenza->formatLocalized('%B %Y').''; + } + + echo ' + + '.moneyFormat($pianificazione->totale).' + '; + $fattura = $pianificazione->fattura; + if (!empty($fattura)) { + echo ' + '.Modules::link('Fatture di vendita', $fattura->id, tr('Fattura num. _NUM_ del _DATE_', [ + '_NUM_' => $fattura->numero, + '_DATE_' => dateFormat($fattura->data), + ])).' ( '.$fattura->stato->descrizione.')'; + } else { + echo ' + '.tr('Non ancora fatturato'); + } + echo ' + + +
'; +} else { + echo ' +
+ '.tr('Pianificazione non ancora effettuata per il contratto corrente').'. +
+ + +
'; +} + +echo ' +'; diff --git a/plugins/pianificazione_fatturazione/src/Pianificazione.php b/plugins/pianificazione_fatturazione/src/Pianificazione.php new file mode 100755 index 000000000..8c019a1d4 --- /dev/null +++ b/plugins/pianificazione_fatturazione/src/Pianificazione.php @@ -0,0 +1,104 @@ +contratto()->associate($contratto); + + $model->data_scadenza = $data_scadenza; + + // Salvataggio delle informazioni + $model->save(); + + return $model; + } + + public function getPluginAttribute() + { + return 'Pianificazione fatturazione'; + } + + public function getDirezioneAttribute() + { + return 'entrata'; + } + + public function anagrafica() + { + return $this->contratto->anagrafica(); + } + + public function contratto() + { + return $this->belongsTo(Contratto::class, 'idcontratto'); + } + + public function fattura() + { + return $this->belongsTo(Fattura::class, 'iddocumento'); + } + + public function getRighe() + { + $righe = $this->contratto->getRighe(); + $pianificazioni = $this->contratto->pianificazioni; + $numero_righe = $righe->count() / $pianificazioni->count(); + + $p = $this; + $index = $pianificazioni->search(function($item) use($p){ + return $item->id == $p->id; + }); + + return $righe->splice($index*$numero_righe, $numero_righe); + } + + public function articoli() + { + return $this->contratto->articoli(); + } + + public function righe() + { + return $this->contratto->righe(); + } + + public function sconti() + { + return $this->contratto->sconti(); + } + + public function descrizioni() + { + return $this->contratto->descrizioni(); + } +} diff --git a/plugins/pianificazione_interventi/actions.php b/plugins/pianificazione_interventi/actions.php index c9583d806..a8372016b 100755 --- a/plugins/pianificazione_interventi/actions.php +++ b/plugins/pianificazione_interventi/actions.php @@ -128,7 +128,7 @@ switch ($operazione) { ]); } - $count_promemoria++; + ++$count_promemoria; } else { $promemoria_corrente = $promemoria_contratto[$data_promemoria]->first(); $date_con_promemoria[] = dateFormat($data_promemoria); @@ -152,7 +152,7 @@ switch ($operazione) { // Copia delle informazioni del promemoria $promemoria_corrente->pianifica($intervento); - $count_interventi++; + ++$count_interventi; } elseif (post('pianifica_intervento')) { $date_con_intervento[] = dateFormat($data_promemoria); } diff --git a/plugins/pianificazione_interventi/edit.php b/plugins/pianificazione_interventi/edit.php index 9690af203..4a36b6497 100755 --- a/plugins/pianificazione_interventi/edit.php +++ b/plugins/pianificazione_interventi/edit.php @@ -14,10 +14,11 @@ $stati_pianificabili = Stato::where('is_pianificabile', 1)->get(); $elenco_stati = $stati_pianificabili->implode('descrizione', ', '); echo ' +

'.tr('Puoi pianificare dei "promemoria" o direttamente gli interventi da effettuare entro determinate scadenze').'. '.tr('Per poter pianificare i promemoria, il contratto deve avere data accettazione e data conclusione definita ed essere in uno dei seguenti stati: _LINK_', [ + '_LINK_' => ''.$elenco_stati.'', +]).' -

'.tr('Puoi pianificare dei "promemoria" o direttamente gli interventi da effettuare entro determinate scadenze. Per poter pianificare i promemoria, il contratto deve avere data accettazione e data conclusione definita ed essere in uno dei seguenti stati: '.$elenco_stati.'').'. - - +

'; diff --git a/update/2_4_14.sql b/update/2_4_14.sql index bd06a3c59..4c739b41f 100755 --- a/update/2_4_14.sql +++ b/update/2_4_14.sql @@ -158,3 +158,10 @@ ALTER TABLE `in_righe_interventi` ADD `original_id` int(11), ADD `original_type` -- Aggiunta supporto a prezzi ivati INSERT INTO `zz_settings` (`id`, `nome`, `valore`, `tipo`, `editable`, `sezione`, `created_at`, `updated_at`, `order`, `help`) VALUES (NULL, 'Utilizza prezzi di vendita con IVA incorporata', '0', 'boolean', '1', 'Fatturazione', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, 'Abilita la gestione degli importi ivati per i documenti di vendita.'); + +-- Fix plugin "Pianificazione fatturazione" +UPDATE `zz_plugins` SET `options` = 'custom', `script` = '', `directory` = 'pianificazione_fatturazione' WHERE `name` = 'Pianificazione fatturazione'; +DROP TABLE `co_ordiniservizio_vociservizio`; +ALTER TABLE `co_ordiniservizio_pianificazionefatture` RENAME TO `co_fatturazione_contratti`; + +UPDATE `zz_widgets` SET `query` = 'SELECT COUNT(id) AS dato FROM co_fatturazione_contratti WHERE idcontratto IN( SELECT id FROM co_contratti WHERE idstato IN(SELECT id FROM co_staticontratti WHERE descrizione IN("Bozza", "Accettato", "In lavorazione", "In attesa di pagamento")) ) AND co_fatturazione_contratti.iddocumento=0' WHERE `name` = 'Rate contrattuali';