1
0
mirror of https://github.com/devcode-it/openstamanager.git synced 2025-03-10 00:00:18 +01:00
This commit is contained in:
Beppe 2022-09-30 13:09:19 +02:00
commit e7d2661e80
62 changed files with 609 additions and 267 deletions

1
.gitignore vendored
View File

@ -92,6 +92,7 @@ REVISION
manifest.json
checksum.json
database.json
database_5_7.json
/tests/_log/*
/tests/_temp/*

View File

@ -4,6 +4,7 @@ Tutti i maggiori cambiamenti di questo progetto saranno documentati in questo fi
Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://keepachangelog.com/), e il progetto segue il [Semantic Versioning](http://semver.org/) per definire le versioni delle release.
- [2.4.36 (2022-09-16)](#2436-2022-09-16)
- [2.4.35 (2022-08-12)](#2435-2022-08-12)
- [2.4.34 (2022-07-15)](#2434-2022-07-15)
- [2.4.33 (2022-05-17)](#2433-2022-05-17)
@ -46,6 +47,38 @@ Il formato utilizzato è basato sulle linee guida di [Keep a Changelog](http://k
- [2.2 (2016-11-10)](#22-2016-11-10)
- [2.1 (2015-04-02)](#21-2015-04-02)
## 2.4.36 (2022-09-16)
### Aggiunto (Added)
- Aggiunta selezione modulo iniziale per gruppo utenti
- Aggiunta validazione matricola in impianti
- Aggiunta anagrafica nelle scadenze
- Aggiunta prezzi ivati nella stampa documenti
### Modificato (Changed)
- Miglioria barra dei menu in modalità compatta
- Rimozione file deprecato controller_after.php
- Miglioria creazione conto anagrafica in piano dei conti
- Miglioria importazione articoli in CSV
- Rimozione delle aliquote IVA non utilizzate
- Miglioria riepilogo totali in stampa intervento
- Miglioria gestione ritenuta previdenziale
### Fixed
- Correzione controllo dei totali in fattura elettronica
- Correzione eliminazione attività collegate ai documenti
- Correzione numerazione progressiva
- Correzione creazione autofattura da nota di credito
- Correzione creazione intervento da ordine fornitore
- Correzione calcolo cassa previdenziale in importazione di fatture elettroniche
- Correzione stato di default in creazione attività
- Correzione selezione sottocategorie in Combinazioni
- Correzione registrazione autofattura
- Correzione aggiunta modelli prima nota
- Correzione movimentazione articoli tra DDT
- Correzione emissione fatture non fiscali da azioni di gruppo
- Correzione regime fiscale per fatture conto terzi
- Correzione date di inizio e fine attività
## 2.4.35 (2022-08-12)
### Aggiunto (Added)

View File

@ -324,7 +324,7 @@ elseif (post('op') == 'send-email') {
// Contenuti
$mail->subject = post('subject');
$mail->content = post('body');
$mail->content = $_POST['body']; // post('body', true);
// Conferma di lettura
$mail->read_notify = post('read_notify');

View File

@ -407,6 +407,7 @@ function release(done) {
'**/*',
'!checksum.json',
'!database.json',
'!database_5_7.json',
'!.idea/**',
'!.git/**',
'!node_modules/**',

View File

@ -176,7 +176,7 @@ if (!empty($type) && $type != 'menu' && $type != 'custom') {
<div class="col-md-2 dropdown">';
if (!empty($bulk) && $structure->permission == 'rw') {
if (!empty($bulk) && $structure->permission == 'rw' && empty($id_plugin)) {
echo '
<button class="btn btn-primary btn-block dropdown-toggle actions-container disabled" type="button" data-toggle="dropdown" disabled>'.tr('Azioni di gruppo').' <span class="caret"></span></button>
<ul class="dropdown-menu" data-target="'.$table_id.'" role="menu">';

View File

@ -44,7 +44,11 @@ switch (filter('op')) {
break;
case 'upload':
include base_dir().'/modules/aggiornamenti/upload_modules.php';
if (setting('Attiva aggiornamenti')){
include base_dir().'/modules/aggiornamenti/upload_modules.php';
}else{
flash()->error(tr('Non è permesso il caricamento di aggiornamenti o moduli!'));
}
break;

View File

@ -72,14 +72,18 @@ $(document).ready(function () {
return;
}
$contents = file_get_contents(base_dir().'/database.json');
$mysql_min_version = '5.7.0';
$mysql_max_version = '5.7.99';
$contents = ((version_compare($database->getMySQLVersion(), $mysql_min_version, ">=") && version_compare($database->getMySQLVersion(), $mysql_max_version, "<=")) ? $file_to_check_database = 'database_5_7.json' : $file_to_check_database = 'database.json' );
$contents = file_get_contents(base_dir().'/'.$file_to_check_database);
$data = json_decode($contents, true);
if (empty($data)) {
echo '
<div class="alert alert-warning">
<i class="fa fa-warning"></i> '.tr('Impossibile effettuare controlli di integrità in assenza del file _FILE_', [
'_FILE_' => '<b>database.json</b>',
'_FILE_' => '<b>'.$file_to_check_database.'</b>',
]).'.
</div>';
@ -96,8 +100,9 @@ if (!empty($results)) {
<p>'.tr("Segue l'elenco delle tabelle del database che presentano una struttura diversa rispetto a quella prevista nella versione ufficiale del gestionale").'.</p>
<div class="alert alert-warning">
<i class="fa fa-warning"></i>
'.tr('Attenzione: questa funzionalità può presentare dei risultati falsamente positivi, sulla base del contenuto del file _FILE_', [
'_FILE_' => '<b>database.json</b>',
'.tr('Attenzione: questa funzionalità può presentare dei risultati falsamente positivi, sulla base del contenuto del file _FILE_ e la versione di _MYSQL_VERSION_ di MySQL rilevata a sistema', [
'_FILE_' => '<b>'.$file_to_check_database.'</b>',
'_MYSQL_VERSION_' => '<b>'.$database->getMySQLVersion().'</b>',
]).'.
</div>';

View File

@ -92,7 +92,6 @@ if (!function_exists('base_dir')) {
}
// Aggiornamenti
if (setting('Attiva aggiornamenti')) {
$alerts = [];
if (!extension_loaded('zip')) {
@ -184,19 +183,22 @@ function search(button) {
}
</script>
<div class="row">
<div class="row">';
echo'
<div class="col-md-4">
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">
'.tr('Carica un aggiornamento').' <span class="tip" title="'.tr('Form di caricamento aggiornamenti del gestionale e innesti di moduli e plugin').'."><i class="fa fa-question-circle-o"></i></span>
'.tr('Carica aggiornamenti o nuovi moduli').' <span class="tip" title="'.tr('Form di caricamento aggiornamenti del gestionale e innesti di moduli e plugin').'."><i class="fa fa-question-circle-o"></i></span>
</h3>
</div>
<div class="box-body">
<form action="'.base_path().'/controller.php?id_module='.$id_module.'" method="post" enctype="multipart/form-data" id="update">
<input type="hidden" name="op" value="upload">
{[ "type": "file", "name": "blob", "required": 1, "accept": ".zip" ]}
{[ "type": "file", "name": "blob", "required": 1, "accept": ".zip", "disabled": '.(setting('Attiva aggiornamenti')? 0 : 1).' ]}
';
@ -218,12 +220,16 @@ echo '
<button type="button" class="btn btn-primary pull-right '.$disabled.'" id="aggiorna" onclick="update()">
<i class="fa fa-upload"></i> '.tr('Carica').'
</button>
</button>';
echo '
</form>
</div>
</div>
</div>
</div>';
echo '
<div class="col-md-4">
<div class="box box-warning">
<div class="box-header with-border">
@ -245,7 +251,9 @@ echo '
</button>
</div>
</div>
</div>
</div>';
echo '
<div class="col-md-4">
<div class="box box-info">
@ -265,11 +273,12 @@ echo '
</button>';
}
echo ' </div>
echo ' </div>
</div>
</div>
</div>';
echo '
</div>';
}
// Requisiti
echo '

View File

@ -40,7 +40,6 @@ class DatiFattureElettroniche extends Controllo
->whereNotIn('codice_stato_fe', ['ERR', 'NS', 'EC02', 'ERVAL'])
->where('data', '>=', $_SESSION['period_start'])
->where('data', '<=', $_SESSION['period_end'])
->where('is_fattura_conto_terzi', '=', 0)
->orderBy('data')
->get();
@ -57,12 +56,13 @@ class DatiFattureElettroniche extends Controllo
// Totale basato sul campo ImportoTotaleDocumento
$dati_generali = $xml['FatturaElettronicaBody']['DatiGenerali']['DatiGeneraliDocumento'];
$dati_anagrafici = $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici'];
$dati_anagrafici = $fattura_vendita->is_fattura_conto_terzi ? $xml['FatturaElettronicaHeader']['CedentePrestatore']['DatiAnagrafici'] : $xml['FatturaElettronicaHeader']['CessionarioCommittente']['DatiAnagrafici'];
if (isset($dati_generali['ImportoTotaleDocumento'])) {
$totale_documento_indicato = abs(floatval($dati_generali['ImportoTotaleDocumento']));
// Calcolo del totale basato sui DatiRiepilogo
if (empty($totale_documento_xml) && empty($dati_generali['ScontoMaggiorazione'])) {
if (empty($totale_documento_indicato) && empty($dati_generali['ScontoMaggiorazione'])) {
$totale_documento_xml = 0;
$riepiloghi = $xml['FatturaElettronicaBody']['DatiBeniServizi']['DatiRiepilogo'];
@ -81,7 +81,7 @@ class DatiFattureElettroniche extends Controllo
}
// Se riscontro un'anomalia
if ($fattura_vendita->anagrafica->piva != $dati_anagrafici['IdFiscaleIVA']['IdCodice'] || $fattura_vendita->anagrafica->codice_fiscale != $dati_anagrafici['CodiceFiscale'] || numberFormat($fattura_vendita->totale) != numberFormat($totale_documento_xml)) {
if ($fattura_vendita->anagrafica->piva != $dati_anagrafici['IdFiscaleIVA']['IdCodice'] || $fattura_vendita->anagrafica->codice_fiscale != $dati_anagrafici['CodiceFiscale'] || numberFormat(abs($fattura_vendita->totale)) != numberFormat($totale_documento_xml)) {
$anomalia = [
'fattura_vendita' => $fattura_vendita,
'codice_fiscale_xml' => !empty($dati_anagrafici['CodiceFiscale']) ? $dati_anagrafici['CodiceFiscale'] : null,
@ -89,7 +89,7 @@ class DatiFattureElettroniche extends Controllo
'piva_xml' => !empty($dati_anagrafici['IdFiscaleIVA']['IdCodice']) ? $dati_anagrafici['IdFiscaleIVA']['IdCodice'] : null,
'piva' => $fattura_vendita->anagrafica->piva,
'totale_documento_xml' => moneyFormat($totale_documento_xml, 2),
'totale_documento' => moneyFormat($fattura_vendita->totale, 2),
'totale_documento' => moneyFormat(abs($fattura_vendita->totale), 2),
];
$riepilogo_anomalie = '

View File

@ -43,7 +43,7 @@ class UpdateHook extends CachedManager
public function response()
{
$update = $this->getCache()->content;
$update = $this->getCache()->content[0];
if ($update == Update::getVersion() || empty(setting('Attiva aggiornamenti'))) {
$update = null;
}

View File

@ -81,8 +81,8 @@ switch ($resource) {
];
}
// Tutti gli agenti
$q = "SELECT DISTINCT(email), ragione_sociale, an_anagrafiche.idanagrafica FROM an_anagrafiche INNER JOIN an_tipianagrafiche_anagrafiche ON an_anagrafiche.idanagrafica=an_tipianagrafiche_anagrafiche.idanagrafica WHERE idtipoanagrafica = (SELECT idtipoanagrafica FROM an_tipianagrafiche WHERE descrizione='Agente') AND email != '' ORDER BY idanagrafica";
// Tutti gli agenti del cliente
$q = "SELECT DISTINCT(email), ragione_sociale, idanagrafica FROM an_anagrafiche WHERE email != '' AND (idanagrafica=(SELECT idagente FROM an_anagrafiche AS agenti WHERE 1=1 ".$where.") OR idanagrafica IN (SELECT idagente FROM an_anagrafiche_agenti WHERE 1=1 ".$where."))";
$rs = $dbo->fetchArray($q);
foreach ($rs as $r) {
@ -96,7 +96,7 @@ switch ($resource) {
$query = "SELECT DISTINCT(email) AS email, ragione_sociale, idanagrafica FROM an_anagrafiche WHERE email != '' ".$where;
// Se type pec, propongo anche la pec
if (get('type') == 'pec') {
$query .= " UNION SELECT DISTINCT(pec), ragione_sociale, idanagrafica FROM an_anagrafiche WHERE email != '' ".$where;
$query .= " UNION SELECT DISTINCT(pec), ragione_sociale, idanagrafica FROM an_anagrafiche WHERE pec != '' ".$where;
}
$query .= ' ORDER BY idanagrafica';

View File

@ -370,17 +370,19 @@ class Anagrafica extends Model
->where('idpianodeiconti2', '=', $categoria_conto_id);
// Verifica su un possibile conto esistente ma non collegato
$conto = (clone $table)
->where('descrizione', 'like', '%'.$anagrafica->ragione_sociale.'%')
->first();
if (!empty($conto)) {
$anagrafiche_collegate = Anagrafica::where($campo, '=', $conto->id)->count();
$conto = $anagrafiche_collegate == 0 ? $conto : null;
}
if (!empty($anagrafica->ragione_sociale)) {
$conto = (clone $table)
->where('descrizione', 'like', '%'.$anagrafica->ragione_sociale.'%')
->first();
if (!empty($conto)) {
$anagrafiche_collegate = Anagrafica::where($campo, '=', $conto->id)->count();
$conto = $anagrafiche_collegate == 0 ? $conto : null;
}
// Collegamento a conto esistente
if (!empty($conto)) {
return $conto->id;
// Collegamento a conto esistente
if (!empty($conto)) {
return $conto->id;
}
}
// Calcolo prossimo numero cliente
@ -394,7 +396,7 @@ class Anagrafica extends Model
$id_conto = $database->table('co_pianodeiconti3')
->insertGetId([
'numero' => $new_numero,
'descrizione' => $anagrafica->ragione_sociale,
'descrizione' => $anagrafica->ragione_sociale ?: 'N.D.',
'idpianodeiconti2' => $categoria_conto_id,
]);

View File

@ -21,9 +21,22 @@ use Modules\Anagrafiche\Anagrafica;
$anagrafica = Anagrafica::find($id_record);
//cliente
if ($anagrafica->idconto_cliente != '') {
$conto = $anagrafica->idconto_cliente;
$conto_descrizione = $dbo->fetchOne('SELECT CONCAT ((SELECT numero FROM co_pianodeiconti2 WHERE id=co_pianodeiconti3.idpianodeiconti2), ".", numero, " ", descrizione) AS descrizione FROM co_pianodeiconti3 WHERE id='.prepare($conto))['descrizione'];
}
//Fornitore
elseif ($anagrafica->idconto_fornitore != '') {
$conto = $anagrafica->idconto_fornitore;
$conto_descrizione = $dbo->fetchOne('SELECT CONCAT ((SELECT numero FROM co_pianodeiconti2 WHERE id=co_pianodeiconti3.idpianodeiconti2), ".", numero, " ", descrizione) AS descrizione FROM co_pianodeiconti3 WHERE id='.prepare($conto))['descrizione'];
}
// Variabili da sostituire
return [
'ragione_sociale' => $anagrafica->ragione_sociale,
'codice' => $anagrafica->codice,
'id_anagrafica' => $anagrafica->idanagrafica,
];
'conto' => $conto,
'conto_descrizione' => $conto_descrizione,
];

View File

@ -37,8 +37,8 @@ switch ($resource) {
$idagente = $superselect['idagente'];
$query = "SELECT
DISTINCT mg_articoli.id,
IF(`categoria`.`nome` IS NOT NULL, CONCAT(`categoria`.`nome`, IF(`sottocategoria`.`nome` IS NOT NULL, CONCAT(' (', `sottocategoria`.`nome`, ')'), '-')), '<i>".tr('Nessuna categoria')."</i>') AS optgroup,
mg_articoli.id,
mg_articoli.barcode,
mg_articoli.".($prezzi_ivati ? 'prezzo_vendita_ivato' : 'prezzo_vendita').' AS prezzo_vendita,

View File

@ -231,10 +231,12 @@ class CSV extends CSVImporter
continue;
}
$database->query('DELETE FROM mg_prezzi_articoli WHERE id_articolo = '.prepare($articolo->id).' AND id_anagrafica = '.prepare($anagrafica->id));
if (!empty($record['prezzo_listino'])) {
$database->query('DELETE FROM mg_prezzi_articoli WHERE id_articolo = '.prepare($articolo->id).' AND id_anagrafica = '.prepare($anagrafica->id));
}
if (!empty($dettagli['codice_fornitore']) && !empty($dettagli['descrizione_fornitore'])) {
$database->query('DELETE FROM mg_fornitore_articolo WHERE id_articolo = '.prepare($articolo->id).' AND id_anagrafica = '.prepare($anagrafica->id));
if (!empty($record['codice_fornitore']) && !empty($record['descrizione_fornitore'])) {
$database->query('DELETE FROM mg_fornitore_articolo WHERE id_articolo = '.prepare($articolo->id).' AND id_fornitore = '.prepare($anagrafica->id));
}
}
}
@ -285,12 +287,6 @@ class CSV extends CSVImporter
}
}
// Individuazione dell'IVA di vendita tramite il relativo Codice
$aliquota = null;
if (!empty($record['codice_iva_vendita'])) {
$aliquota = Aliquota::where('codice', $record['codice_iva_vendita'])->first();
}
// Individuazione articolo e generazione
$articolo = null;
// Ricerca sulla base della chiave primaria se presente
@ -303,7 +299,13 @@ class CSV extends CSVImporter
$articolo->restore();
}
$articolo->idiva_vendita = $aliquota->id;
// Individuazione dell'IVA di vendita tramite il relativo Codice
$aliquota = null;
if (!empty($record['codice_iva_vendita'])) {
$aliquota = Aliquota::where('codice', $record['codice_iva_vendita'])->first();
$articolo->idiva_vendita = $aliquota->id;
}
$articolo->attivo = 1;
// Esportazione della quantità indicata
@ -387,12 +389,13 @@ class CSV extends CSVImporter
]);
// Prezzo di vendita
$articolo->setPrezzoVendita($record['prezzo_vendita'], $aliquota->id ? $aliquota->id : setting('Iva predefinita'));
if (!empty($record['prezzo_vendita'])) {
$articolo->setPrezzoVendita($record['prezzo_vendita'], $aliquota ? $aliquota->id : setting('Iva predefinita'));
}
$articolo->save();
// Movimentazione della quantità registrata
$giacenze = $articolo->getGiacenze();
$anagrafica_azienda = Anagrafica::find(setting('Azienda predefinita'));
$id_sede = 0;
if (!empty($nome_sede)) {
@ -403,6 +406,7 @@ class CSV extends CSVImporter
}
if( isset($record['qta']) ) {
$giacenze = $articolo->getGiacenze();
$qta_movimento = $qta_registrata - $giacenze[$id_sede][0];
$articolo->movimenta($qta_movimento, tr('Movimento da importazione'), new Carbon(), false, [
@ -442,7 +446,7 @@ class CSV extends CSVImporter
}
// Aggiungo Listino
if (!empty($anagrafica) && !empty($dettagli['dir'])) {
if (!empty($anagrafica) && !empty($dettagli['dir']) && $dettagli['prezzo_listino']) {
$dettaglio_predefinito = DettaglioPrezzo::build($articolo, $anagrafica, $dettagli['dir']);
$dettaglio_predefinito->sconto_percentuale = $dettagli['sconto_listino'];
$dettaglio_predefinito->setPrezzoUnitario($dettagli['prezzo_listino']);
@ -453,15 +457,15 @@ class CSV extends CSVImporter
}
$dettaglio_predefinito->save();
}
// Aggiungo dettagli fornitore
if ($dettagli['dir'] == 'uscita' && !empty($dettagli['codice_fornitore']) && !empty($dettagli['descrizione_fornitore'])) {
$fornitore = DettaglioFornitore::build($anagrafica, $articolo);
$fornitore->codice_fornitore = $dettagli['codice_fornitore'];
$fornitore->barcode_fornitore = $dettagli['barcode_fornitore'];
$fornitore->descrizione = $dettagli['descrizione_fornitore'];
$fornitore->save();
}
// Aggiungo dettagli fornitore
if (!empty($anagrafica) && $dettagli['dir'] == 'uscita' && !empty($dettagli['codice_fornitore']) && !empty($dettagli['descrizione_fornitore'])) {
$fornitore = DettaglioFornitore::build($anagrafica, $articolo);
$fornitore->codice_fornitore = $dettagli['codice_fornitore'];
$fornitore->barcode_fornitore = $dettagli['barcode_fornitore'];
$fornitore->descrizione = $dettagli['descrizione_fornitore'];
$fornitore->save();
}
// Imposto fornitore e prezzo predefinito

View File

@ -21,7 +21,6 @@ echo '
<div class="row">
<div class="col-md-6">
'.Modules::link('Categorie articoli', $record['id_categoria'], null, null, 'class="pull-right"').'
{[ "type": "select", "label": "'.tr('Categoria').'", "name": "id_categoria", "required": 0, "value": "$id_categoria$", "ajax-source": "categorie", "icon-after": "add|'.Modules::get('Categorie articoli')['id'].'" ]}
</div>
@ -44,4 +43,12 @@ echo '
</button>
</div>
</div>
</form>';
</form>
<script>
$("#id_categoria").change(function() {
updateSelectOption("id_categoria", $(this).val());
$("#id_sottocategoria").val(null).trigger("change");
});
</script>';

View File

@ -26,8 +26,12 @@ echo '
</div>
<div class="row">
<div class="col-md-6">
'.Modules::link('Categorie articoli', $record['id_categoria'], null, null, 'class="pull-right"').'
<div class="col-md-6">';
if (!empty($record['id_categoria'])) {
echo '
'.Modules::link('Categorie articoli', $record['id_categoria'], null, null, 'class="pull-right"');
}
echo '
{[ "type": "select", "label": "'.tr('Categoria').'", "name": "id_categoria", "required": 0, "value": "$id_categoria$", "ajax-source": "categorie", "icon-after": "add|'.Modules::get('Categorie articoli')['id'].'" ]}
</div>
@ -127,4 +131,10 @@ function generaVarianti(button) {
backto: "record-edit",
});
}
$("#id_categoria").change(function() {
updateSelectOption("id_categoria", $(this).val());
$("#id_sottocategoria").val(null).trigger("change");
});
</script>';

View File

@ -21,6 +21,7 @@ $r = $dbo->fetchOne('SELECT *,
an_anagrafiche.pec,
IF((an_referenti.email IS NOT NULL AND an_referenti.email != ""), an_referenti.email, an_anagrafiche.email) AS email,
an_anagrafiche.idanagrafica,
an_referenti.nome,
an_anagrafiche.ragione_sociale
FROM co_contratti
INNER JOIN an_anagrafiche ON co_contratti.idanagrafica=an_anagrafiche.idanagrafica
@ -35,4 +36,5 @@ return [
'descrizione' => $r['descrizione'],
'data' => Translator::dateToLocale($r['data_bozza']),
'id_anagrafica' => $r['idanagrafica'],
'nome_referente' => $r['nome'],
];

View File

@ -351,12 +351,17 @@ switch (filter('op')) {
$ddt->save();
$evadi_qta_parent = true;
if ($documento->tipo->descrizione=='Ddt in uscita' || $documento->tipo->descrizione=='Ddt in entrata') {
$evadi_qta_parent = false;
}
$righe = $documento->getRighe();
foreach ($righe as $riga) {
if (post('evadere')[$riga->id] == 'on' and !empty(post('qta_da_evadere')[$riga->id])) {
$qta = post('qta_da_evadere')[$riga->id];
$copia = $riga->copiaIn($ddt, $qta);
$copia = $riga->copiaIn($ddt, $qta, $evadi_qta_parent);
// Aggiornamento seriali dalla riga dell'ordine
if ($copia->isArticolo()) {
@ -555,7 +560,7 @@ switch (filter('op')) {
// Aggiornamento stato degli ordini presenti in questa fattura in base alle quantità totali evase
if (!empty($id_record) && setting('Cambia automaticamente stato ordini fatturati')) {
$rs = $dbo->fetchArray('SELECT idordine FROM dt_righe_ddt WHERE idddt='.prepare($id_record));
$rs = $dbo->fetchArray('SELECT idordine FROM dt_righe_ddt WHERE idddt='.prepare($id_record).' AND idordine!=0');
for ($i = 0; $i < sizeof($rs); ++$i) {
$dbo->query('UPDATE or_ordini SET idstatoordine=(SELECT id FROM or_statiordine WHERE descrizione="'.get_stato_ordine($rs[$i]['idordine']).'") WHERE id = '.prepare($rs[$i]['idordine']));

View File

@ -19,10 +19,12 @@
$r = $dbo->fetchOne('SELECT dt_ddt.*,
IF((an_referenti.email IS NOT NULL AND an_referenti.email != ""), an_referenti.email, an_anagrafiche.email) AS email,
an_anagrafiche.pec
an_anagrafiche.pec,
an_anagrafiche.ragione_sociale,
an_referenti.nome
FROM dt_ddt
INNER JOIN an_anagrafiche ON dt_ddt.idanagrafica = an_anagrafiche.idanagrafica
LEFT OUTER JOIN an_referenti ON an_referenti.id = dt_ddt.idreferente
INNER JOIN an_referenti ON an_referenti.id = dt_ddt.idreferente
WHERE dt_ddt.id='.prepare($id_record));
// Variabili da sostituire
@ -33,4 +35,5 @@ return [
'data' => Translator::dateToLocale($r['data']),
'id_anagrafica' => $r['idanagrafica'],
'ragione_sociale' => $r['ragione_sociale'],
'nome_referente' => $r['nome'],
];

View File

@ -464,7 +464,7 @@ switch (post('op')) {
$fattura = Fattura::find($id);
$stato_precedente = Stato::find($fattura->idstatodocumento);
if ($stato_precedente->descrizione == 'Bozza') {
if ($stato_precedente->descrizione == 'Bozza' && $fattura->isFiscale()) {
$fattura->stato()->associate($new_stato);
$results = $fattura->save();
$message = '';

View File

@ -29,7 +29,7 @@ echo '
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT id, CONCAT_WS(\" - \",codice_tipo_documento_fe, descrizione) AS descrizione FROM co_tipidocumento WHERE dir=\"entrata\" AND codice_tipo_documento_fe IN(\"TD16\", \"TD17\", \"TD18\", \"TD19\", \"TD20\") ORDER BY codice_tipo_documento_fe" ]}
{[ "type": "select", "label": "'.tr('Tipo documento').'", "name": "idtipodocumento", "required": 1, "values": "query=SELECT id, CONCAT_WS(\" - \",codice_tipo_documento_fe, descrizione) AS descrizione FROM co_tipidocumento WHERE dir=\"entrata\" AND codice_tipo_documento_fe IN(\"TD16\", \"TD17\", \"TD18\", \"TD19\", \"TD20\", \"TD21\") ORDER BY codice_tipo_documento_fe" ]}
</div>
<div class="col-md-6">

View File

@ -755,7 +755,7 @@ class Fattura extends Document
public function isAutofattura()
{
return in_array($this->tipo->codice_tipo_documento_fe, ['TD16','TD17','TD18','TD19',
'TD20']);
'TD20', 'TD21']);
}
/**

View File

@ -23,6 +23,7 @@ $r = $dbo->fetchOne('SELECT co_documenti.*,
an_anagrafiche.idconto_cliente,
an_anagrafiche.idconto_fornitore,
an_anagrafiche.ragione_sociale,
an_referenti.nome,
co_tipidocumento.descrizione AS tipo_documento,
(SELECT pec FROM em_accounts WHERE em_accounts.id='.prepare($template['id_account']).') AS is_pec
FROM co_documenti
@ -38,17 +39,6 @@ if (!empty(setting('Logo stampe'))) {
$logo_azienda = str_replace('\\', '/', $logo_azienda);
}
//cliente
if ($r['idconto_cliente'] != '') {
$conto = $r['idconto_cliente'];
$conto_descrizione = $dbo->fetchOne('SELECT CONCAT ((SELECT numero FROM co_pianodeiconti2 WHERE id=co_pianodeiconti3.idpianodeiconti2), ".", numero, " ", descrizione) AS descrizione FROM co_pianodeiconti3 WHERE id='.prepare($conto))['descrizione'];
}
//Fornitore
elseif ($r['idconto_fornitore'] != '') {
$conto = $r['idconto_fornitore'];
$conto_descrizione = $dbo->fetchOne('SELECT CONCAT ((SELECT numero FROM co_pianodeiconti2 WHERE id=co_pianodeiconti3.idpianodeiconti2), ".", numero, " ", descrizione) AS descrizione FROM co_pianodeiconti3 WHERE id='.prepare($conto))['descrizione'];
}
$r_user = $dbo->fetchOne('SELECT * FROM an_anagrafiche WHERE idanagrafica='.prepare(Auth::user()['idanagrafica']));
$r_company = $dbo->fetchOne('SELECT * FROM an_anagrafiche WHERE idanagrafica='.prepare(setting('Azienda predefinita')));
@ -62,9 +52,8 @@ return [
'note' => $r['note'],
'data' => Translator::dateToLocale($r['data']),
'logo_azienda' => !empty($logo_azienda) ? '<img src="'.$logo_azienda.'" />' : '',
'conto' => $conto,
'conto_descrizione' => $conto_descrizione,
'nome_utente' => $r_user['ragione_sociale'],
'telefono_utente' => $r_user['cellulare'],
'sito_web' => $r_company['sitoweb'],
'nome_referente' => $r['nome'],
];

View File

@ -28,8 +28,8 @@ switch (post('op')) {
$exporter = new CSV($file);
// Esportazione dei record selezionati
$fatture = Impianto::whereIn('id', $id_records)->get();
$exporter->setRecords($fatture);
$impianti = Impianto::whereIn('id', $id_records)->get();
$exporter->setRecords($impianti);
$count = $exporter->exportRecords();

View File

@ -32,6 +32,7 @@ use Modules\Interventi\Intervento;
use Modules\Interventi\Stato;
use Modules\TipiIntervento\Tipo as TipoSessione;
use Plugins\ComponentiImpianti\Componente;
use Plugins\ListinoClienti\DettaglioPrezzo;
use Plugins\PianificazioneInterventi\Promemoria;
switch (post('op')) {
@ -629,18 +630,39 @@ switch (post('op')) {
$id_record = $intervento->id;
}
// Evado le righe solo se il documento originale non è un Ordine fornitore
$evadi_qta_parent = true;
if (post('op') == 'add_intervento') {
$evadi_qta_parent = false;
}
$righe = $documento->getRighe();
foreach ($righe as $riga) {
if (post('evadere')[$riga->id] == 'on' and !empty(post('qta_da_evadere')[$riga->id])) {
$qta = post('qta_da_evadere')[$riga->id];
$copia = $riga->copiaIn($intervento, $qta);
$copia = $riga->copiaIn($intervento, $qta, $evadi_qta_parent);
// Aggiornamento seriali
if ($copia->isArticolo()) {
// Aggiornamento seriali
$serials = is_array(post('serial')[$riga->id]) ? post('serial')[$riga->id] : [];
$copia->serials = $serials;
// Aggiornamento prezzi se il documento originale è un Ordine fornitore
if (post('op') == 'add_intervento') {
$articolo = $copia->articolo;
$cliente = DettaglioPrezzo::dettagli($riga->idarticolo, $anagrafica->id, 'entrata', $qta)->first();
if (empty($cliente)) {
$cliente = DettaglioPrezzo::dettaglioPredefinito($riga->idarticolo, $anagrafica->id, 'entrata')->first();
}
$prezzo_unitario = $cliente->prezzo_unitario - ($cliente->prezzo_unitario * $cliente->percentuale / 100);
$copia->setPrezzoUnitario($cliente ? $prezzo_unitario : $cliente->prezzo_vendita, $copia->aliquota->id);
$copia->setSconto($cliente->sconto_percentuale ?: 0, 'PRC');
$copia->costo_unitario = $riga->prezzo_unitario ?: 0;
}
}
$copia->save();
@ -780,6 +802,7 @@ switch (post('op')) {
$data_richiesta = post('data_richiesta');
$copia_sessioni = post('copia_sessioni');
$copia_righe = post('copia_righe');
$copia_impianti = post('copia_impianti');
$new = $intervento->replicate();
$new->idstatointervento = $id_stato;
@ -840,6 +863,25 @@ switch (post('op')) {
}
}
// Copia degli impianti
if (!empty($copia_impianti)) {
$impianti = $dbo->select('my_impianti_interventi', '*', ['idintervento' => $intervento->id]);
foreach ($impianti as $impianto) {
$dbo->insert('my_impianti_interventi', [
'idintervento' => $id_record,
'idimpianto' => $impianto['idimpianto']
]);
}
$componenti = $dbo->select('my_componenti_interventi', '*', ['id_intervento' => $intervento->id]);
foreach ($componenti as $componente) {
$dbo->insert('my_componenti_interventi', [
'id_intervento' => $id_record,
'id_componente' => $componente['id_componente']
]);
}
}
flash()->info(tr('Attività duplicata correttamente!'));
break;

View File

@ -47,8 +47,8 @@ if ($user['gruppo'] == 'Tecnici' && !empty($user['idanagrafica'])) {
$id_cliente = $user['idanagrafica'];
}
// Stato di default associato all'attivitò
$stato = $dbo->fetchArray("SELECT * FROM in_statiintervento WHERE codice = 'WIP'");
// Stato di default associato all'attività
$stato = $dbo->fetchOne("SELECT * FROM in_statiintervento WHERE codice = 'WIP'");
$id_stato = $stato['idstatointervento'];
// Se è indicata un'anagrafica relativa, si carica il tipo di intervento di default impostato
@ -462,8 +462,15 @@ echo '
let orario_inizio = input("orario_inizio").getElement();
let orario_fine = input("orario_fine").getElement();
orario_inizio.on("dp.change", function (e) {
orario_fine.data("DateTimePicker").minDate(e.date);
orario_fine.change();
if(orario_fine.data("DateTimePicker").date() < e.date){
orario_fine.data("DateTimePicker").date(e.date);
}
});
orario_fine.on("dp.change", function (e) {
if(orario_inizio.data("DateTimePicker").date() > e.date){
orario_inizio.data("DateTimePicker").date(e.date);
}
});
// Refresh modulo dopo la chiusura di una pianificazione attività derivante dalle attività

View File

@ -172,6 +172,7 @@ switch (post('op')) {
$data_richiesta = post('data_richiesta');
$copia_sessioni = post('sessioni');
$copia_righe = post('righe');
$copia_impianti = post('impianti');
foreach ($id_records as $idintervento) {
$intervento = Intervento::find($idintervento);
@ -227,6 +228,25 @@ switch (post('op')) {
}
}
// Copia degli impianti
if (!empty($copia_impianti)) {
$impianti = $dbo->select('my_impianti_interventi', '*', ['idintervento' => $intervento->id]);
foreach ($impianti as $impianto) {
$dbo->insert('my_impianti_interventi', [
'idintervento' => $id_record,
'idimpianto' => $impianto['idimpianto']
]);
}
$componenti = $dbo->select('my_componenti_interventi', '*', ['id_intervento' => $intervento->id]);
foreach ($componenti as $componente) {
$dbo->insert('my_componenti_interventi', [
'id_intervento' => $id_record,
'id_componente' => $componente['id_componente']
]);
}
}
flash()->info(tr('Attività duplicate correttamente!'));
break;
@ -303,7 +323,8 @@ if (App::debug()) {
'msg' => '<br>{[ "type": "timestamp", "label": "'.tr('Data/ora richiesta').'", "name": "data_richiesta", "required": 0, "value": "-now-", "required":1 ]}
<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "idstatointervento", "required": 1, "values": "query=SELECT idstatointervento AS id, descrizione, colore AS _bgcolor_ FROM in_statiintervento WHERE deleted_at IS NULL ORDER BY descrizione", "value": "" ]}
<br>{[ "type":"checkbox", "label":"'.tr('Duplica righe').'", "name":"righe", "value":"" ]}
<br>{[ "type":"checkbox", "label":"'.tr('Duplica sessioni').'", "name":"sessioni", "value":"" ]}',
<br>{[ "type":"checkbox", "label":"'.tr('Duplica sessioni').'", "name":"sessioni", "value":"" ]}
<br>{[ "type":"checkbox", "label":"'.tr('Duplica impianti').'", "name":"impianti", "value":"" ]}',
'button' => tr('Procedi'),
'class' => 'btn btn-lg btn-warning',
'blank' => false,

View File

@ -66,8 +66,15 @@ echo '
$(document).ready(function () {
// Quando modifico orario inizio, allineo anche l\'orario fine
$("#orario_inizio").on("dp.change", function (e) {
$("#orario_fine").data("DateTimePicker").minDate(e.date);
$("#orario_fine").change();
if($("#orario_fine").data("DateTimePicker").date() < e.date){
$("#orario_fine").data("DateTimePicker").date(e.date);
}
});
$("#orario_fine").on("dp.change", function (e) {
if($("#orario_inizio").data("DateTimePicker").date() > e.date){
$("#orario_inizio").data("DateTimePicker").date(e.date);
}
});
});
</script>';

View File

@ -39,12 +39,16 @@ echo '
{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT idstatointervento AS id, descrizione, colore AS _bgcolor_ FROM in_statiintervento WHERE deleted_at IS NULL ORDER BY descrizione", "value": "" ]}
</div>
<div class="col-md-3">
{["type": "checkbox", "label": "'.tr('Duplica righe').'", "name": "copia_righe", "help": "'.tr('Selezione per riportare anche le righe nella nuova attività').'", "value": 1 ]}
<div class="col-md-2">
{["type": "checkbox", "label": "'.tr('Duplica righe').'", "name": "copia_righe", "help": "'.tr('Selezione per riportare anche le righe nella nuova attività').'" ]}
</div>
<div class="col-md-3">
{["type": "checkbox", "label": "'.tr('Duplica sessioni').'", "name": "copia_sessioni", "help": "'.tr('Selezione per riportare anche le sessioni di lavoro nella nuova attività').'", "value": 1 ]}
<div class="col-md-2">
{["type": "checkbox", "label": "'.tr('Duplica sessioni').'", "name": "copia_sessioni", "help": "'.tr('Selezione per riportare anche le sessioni di lavoro nella nuova attività').'" ]}
</div>
<div class="col-md-2">
{["type": "checkbox", "label": "'.tr('Duplica impianti').'", "name": "copia_impianti", "help": "'.tr('Selezione per riportare anche gli impianti nella nuova attività').'" ]}
</div>
</div>

View File

@ -123,8 +123,15 @@ echo '
$(document).ready(function () {
// Quando modifico orario inizio, allineo anche l\'orario fine
$("#orario_inizio").on("dp.change", function (e) {
$("#orario_fine").data("DateTimePicker").minDate(e.date);
$("#orario_fine").change();
if($("#orario_fine").data("DateTimePicker").date() < e.date){
$("#orario_fine").data("DateTimePicker").date(e.date);
}
});
$("#orario_fine").on("dp.change", function (e) {
if($("#orario_inizio").data("DateTimePicker").date() > e.date){
$("#orario_inizio").data("DateTimePicker").date(e.date);
}
});
$("#idtipointerventot").change(function() {

View File

@ -18,8 +18,10 @@
*/
$r = $dbo->fetchOne('SELECT *,
an_anagrafiche.idanagrafica AS id_anagrafica,
an_anagrafiche.email,
an_anagrafiche.pec,
an_referenti.nome,
in_interventi.codice AS codice,
(SELECT MAX(orario_fine) FROM in_interventi_tecnici WHERE idintervento=in_interventi.id) AS data_fine,
(SELECT descrizione FROM in_statiintervento WHERE idstatointervento=in_interventi.idstatointervento) AS stato,
@ -27,6 +29,7 @@ $r = $dbo->fetchOne('SELECT *,
in_interventi.descrizione AS descrizione
FROM in_interventi
INNER JOIN an_anagrafiche ON in_interventi.idanagrafica = an_anagrafiche.idanagrafica
LEFT OUTER JOIN an_referenti ON an_referenti.id=in_interventi.idreferente
LEFT JOIN (SELECT GROUP_CONCAT(CONCAT(matricola, IF(nome != "", CONCAT(" - ", nome), "")) SEPARATOR "<br>") AS descrizione, my_impianti_interventi.idintervento FROM my_impianti INNER JOIN my_impianti_interventi ON my_impianti.id = my_impianti_interventi.idimpianto GROUP BY my_impianti_interventi.idintervento) AS impianti ON impianti.idintervento = in_interventi.id
WHERE in_interventi.id='.prepare($id_record));
@ -40,7 +43,8 @@ return [
'data' => Translator::dateToLocale($r['data_richiesta']),
'data richiesta' => Translator::dateToLocale($r['data_richiesta']),
'data fine intervento' => empty($r['data_fine']) ? Translator::dateToLocale($r['data_richiesta']) : Translator::dateToLocale($r['data_fine']),
'id_anagrafica' => $r['idanagrafica'],
'id_anagrafica' => $r['id_anagrafica'],
'stato' => $r['stato'],
'impianti' => $r['impianti'],
'nome_referente' => $r['nome'],
];

View File

@ -164,15 +164,18 @@ echo '
});
$(document).on("change", "select", function() {
let row = $(this).parent().parent();
let row = $(this).parent().parent().parent();
if (row.find("input[disabled]").length > 1) {
row.find("input").prop("disabled", !$(this).val());
}
// Trigger dell\'evento keyup() per la prima volta, per eseguire i dovuti controlli nel caso siano predisposte delle righe in prima nota
$("input[id*=dare][value!=\'\'], input[id*=avere][value!=\'\']").keyup();
});
$(document).on("keyup change", "input[id*=dare]", function() {
let row = $(this).parent().parent();
let row = $(this).parent().parent().parent();
if (!$(this).prop("disabled")) {
row.find("input[id*=avere]").prop("disabled", $(this).val().toEnglish());
@ -180,7 +183,7 @@ echo '
});
$(document).on("keyup change", "input[id*=avere]", function() {
let row = $(this).parent().parent();
let row = $(this).parent().parent().parent();
if (!$(this).prop("disabled")) {
row.find("input[id*=dare]").prop("disabled", $(this).val().toEnglish());

View File

@ -27,7 +27,7 @@ switch ($resource) {
case 'ordini-cliente':
if (isset($superselect['idanagrafica'])) {
$query = 'SELECT or_ordini.id AS id,
CONCAT("Ordine ", numero, " del ", DATE_FORMAT(data, "%d/%m/%Y"), " [", (SELECT `descrizione` FROM `or_statiordine` WHERE `or_statiordine`.`id` = `idstatoordine`) , "]") AS descrizione
CONCAT("Ordine ", numero_esterno, " del ", DATE_FORMAT(data, "%d/%m/%Y"), " [", (SELECT `descrizione` FROM `or_statiordine` WHERE `or_statiordine`.`id` = `idstatoordine`) , "]") AS descrizione
FROM or_ordini
INNER JOIN or_tipiordine ON or_ordini.idtipoordine = or_tipiordine.id
INNER JOIN an_anagrafiche ON or_ordini.idanagrafica = an_anagrafiche.idanagrafica

View File

@ -19,10 +19,12 @@
$r = $dbo->fetchOne('SELECT or_ordini.*,
an_anagrafiche.pec,
an_referenti.nome,
an_anagrafiche.ragione_sociale,
IF((an_referenti.email IS NOT NULL AND an_referenti.email != ""), an_referenti.email, an_anagrafiche.email) AS email
FROM or_ordini
INNER JOIN an_anagrafiche ON or_ordini.idanagrafica = an_anagrafiche.idanagrafica
LEFT OUTER JOIN an_referenti ON an_referenti.id = or_ordini.idreferente
LEFT JOIN an_referenti ON an_referenti.id = or_ordini.idreferente
WHERE or_ordini.id='.prepare($id_record));
// Variabili da sostituire
@ -32,4 +34,6 @@ return [
'numero' => empty($r['numero_esterno']) ? $r['numero'] : $r['numero_esterno'],
'note' => $r['note'],
'data' => Translator::dateToLocale($r['data']),
'nome_referente' => $r['nome'],
'ragione_sociale' => $r['ragione_sociale'],
];

View File

@ -147,8 +147,8 @@ switch ($resource) {
$results[count($results) - 1]['children'][] = ['id' => $r2['id'], 'text' => $r['numero'].'.'.$r2['numero'].' '.$r2['descrizione']];
}
$results[] = ['text' => 'Conto cliente/fornitore fattura', 'children' => []];
$results[count($results) - 1]['children'][] = ['id' => '-1', 'text' => '{Conto cliente/fornitore fattura}'];
$results[] = ['text' => 'Conto cliente/fornitore', 'children' => []];
$results[count($results) - 1]['children'][] = ['id' => '-1', 'text' => '{Conto cliente/fornitore}'];
}
break;

View File

@ -258,7 +258,7 @@ $diff = sum($budget, -$totale);
echo '
<div class="well text-center">
<br><span><big>
<b>'.tr('Rapporto budget/spesa').':<br>';
<b>'.tr('Budget rimanente').':<br>';
if ($diff > 0) {
echo '
<span class="text-success"><big>+'.moneyFormat($diff).'</big></span>';
@ -278,11 +278,11 @@ if ($diff > 0) {
<table class="table text-left table-striped table-bordered">
<tr>
<th>'.tr('Tipologia').'</th>
<th width="10%">'.tr('Ore').'</th>
<th width="16%">'.tr('Costo').'</th>
<th width="16%">'.tr('Ricavo').'</th>
<th width="10%">'.tr('Margine').'</th>
<th width="10%">'.tr('Ricarico').'</th>
<th width="11%">'.tr('Ore').'</th>
<th width="15%">'.tr('Costo').'</th>
<th width="15%">'.tr('Ricavo').'</th>
<th width="15%">'.tr('Margine').'</th>
<th width="15%">'.tr('Ricarico').'</th>
</tr>';
ksort($tipologie);
foreach ($tipologie as $key => $tipologia){
@ -307,12 +307,12 @@ if ($diff > 0) {
<table class="table text-left table-striped table-bordered">
<tr>
<th>'.tr('Tecnici').'</th>
<th width="7%">'.tr('km').'</th>
<th width="10%">'.tr('Ore').'</th>
<th width="16%">'.tr('Costo').'</th>
<th width="16%">'.tr('Ricavo').'</th>
<th width="10%">'.tr('Margine').'</th>
<th width="10%">'.tr('Ricarico').'</th>
<th width="11%">'.tr('Km').'</th>
<th width="11%">'.tr('Ore').'</th>
<th width="15%">'.tr('Costo').'</th>
<th width="15%">'.tr('Ricavo').'</th>
<th width="15%">'.tr('Margine').'</th>
<th width="15%">'.tr('Ricarico').'</th>
</tr>';
ksort($tecnici);
foreach ($tecnici as $key => $tecnico){
@ -322,8 +322,8 @@ if ($diff > 0) {
echo '
<tr>
<td>'.$key.'</td>
<td class="text-right">'.Translator::numberToLocale($tecnico['km']).'</td>
<td class="text-right">'.Translator::numberToLocale($tecnico['ore']).'</td>
<td class="text-right">'.(int)$tecnico['km'].'</td>
<td class="text-right">'.Translator::numberToLocale($tecnico['costo']).' </td>
<td class="text-right">'.Translator::numberToLocale($tecnico['ricavo']).' </td>
<td class="text-right '.($margine>0 ? 'bg-success' : 'bg-danger').'">'.Translator::numberToLocale($margine).' ('.$margine_prc.'%)</td>
@ -340,11 +340,11 @@ if ($diff > 0) {
<table class="table text-left table-striped table-bordered">
<tr>
<th>'.tr('Stato').'</th>
<th width="10%">'.tr('Ore').'</th>
<th width="16%">'.tr('Costo').'</th>
<th width="16%">'.tr('Ricavo').'</th>
<th width="10%">'.tr('Margine').'</th>
<th width="10%">'.tr('Ricarico').'</th>
<th width="11%">'.tr('Ore').'</th>
<th width="15%">'.tr('Costo').'</th>
<th width="15%">'.tr('Ricavo').'</th>
<th width="15%">'.tr('Margine').'</th>
<th width="15%">'.tr('Ricarico').'</th>
</tr>';
ksort($stati_intervento);
foreach ($stati_intervento as $key => $stato){
@ -369,11 +369,11 @@ if ($diff > 0) {
<table class="table text-left table-striped table-bordered">
<tr>
<th>'.tr('Materiale').'</th>
<th width="8%">'.tr('Qtà').'</th>
<th width="16%">'.tr('Costo').'</th>
<th width="16%">'.tr('Ricavo').'</th>
<th width="10%">'.tr('Margine').'</th>
<th width="10%">'.tr('Ricarico').'</th>
<th width="11%">'.tr('Qtà').'</th>
<th width="15%">'.tr('Costo').'</th>
<th width="15%">'.tr('Ricavo').'</th>
<th width="15%">'.tr('Margine').'</th>
<th width="15%">'.tr('Ricarico').'</th>
</tr>';
ksort($materiali_art);
foreach ($materiali_art as $key => $materiali_array1){

View File

@ -18,7 +18,7 @@
*/
$r = $dbo->fetchOne('SELECT *,
an_anagrafiche.ragione_sociale, co_preventivi.idanagrafica,
an_anagrafiche.ragione_sociale, co_preventivi.idanagrafica, an_referenti.nome,
IF( (an_referenti.email IS NOT NULL AND an_referenti.email!=""), an_referenti.email, an_anagrafiche.email) AS email
FROM co_preventivi INNER JOIN an_anagrafiche ON co_preventivi.idanagrafica=an_anagrafiche.idanagrafica LEFT OUTER JOIN an_referenti ON an_referenti.id=co_preventivi.idreferente WHERE co_preventivi.id='.prepare($id_record));
@ -33,4 +33,5 @@ return [
'data' => Translator::dateToLocale($r['data_bozza']),
'id_anagrafica' => $r['idanagrafica'],
'revisione' => $revisione,
'nome_referente' => $r['nome'],
];

View File

@ -260,8 +260,12 @@ if (!empty($id_records) && get('origine') == 'fatture' && !empty($counter)) {
}
if (!empty(get('id_anagrafica'))) {
$id_anagrafica = get('id_anagrafica');
} else {
$id_anagrafica = $dbo->fetchOne('SELECT idanagrafica FROM co_documenti WHERE id IN('.(get('id_documenti') ?: '0').')')['idanagrafica'];
}
if (empty($id_anagrafica)) {
$id_anagrafica = $dbo->fetchOne('SELECT idanagrafica FROM co_documenti WHERE id IN('.($id_documenti ? implode(',',$id_documenti) : 0).')')['idanagrafica'];
}
if (empty($id_anagrafica)) {
$id_anagrafica = $dbo->fetchOne('SELECT idanagrafica FROM co_scadenziario WHERE id IN('.($id_scadenze ? implode(',',$id_scadenze) : 0).')')['idanagrafica'];
}
echo '
<form action="'.base_path().'/controller.php?id_module='.$module->id.'" method="post" id="add-form">
@ -358,7 +362,7 @@ $("#modals > div #add-form").on("submit", function(e) {
</script>';
if ($permetti_modelli) {
$variables = Modules::get('Fatture di vendita')->getPlaceholders($id_documenti[0]);
$variables = Modules::get('Anagrafiche')->getPlaceholders($id_anagrafica);
echo '
<script type="text/javascript">
@ -427,9 +431,9 @@ if ($permetti_modelli) {
let totale = dati_conto[2];
// Sostituzione del conto dell\'Anagrafica
if (id_conto === -1 && globals.prima_nota.id_documento !== ""){
id_conto = parseInt(globals.prima_nota.variables["conto"]);
descrizione_conto = globals.prima_nota.variables["conto_descrizione"];
if (id_conto === -1){
id_conto = parseInt(globals.prima_nota.variables["{conto}"]);
descrizione_conto = globals.prima_nota.variables["{conto_descrizione}"];
}
// Selezione del conto

View File

@ -30,8 +30,8 @@ switch (filter('op')) {
$dbo->query('UPDATE `an_relazioni` SET `descrizione`='.prepare($descrizione).', `colore`='.prepare($colore).', `is_bloccata`='.prepare($is_bloccata).' WHERE `id`='.prepare($id_record));
flash()->info(tr('Salvataggio completato.'));
} else {
flash()->error(tr("E' già presente una relazione _NAME_.", [
'_TYPE_' => $descrizione,
flash()->error(tr("E' già presente una relazione '_NAME_'.", [
'_NAME_' => $descrizione,
]));
}
} else {

View File

@ -22,12 +22,14 @@ include_once __DIR__.'/../../core.php';
switch (filter('op')) {
case 'update':
$descrizione = filter('descrizione');
$tipologia = filter('tipologia');
$causale = filter('causale');
$percentuale = filter('percentuale');
$percentuale_imponibile = filter('percentuale_imponibile');
if (isset($descrizione) && isset($percentuale) && isset($percentuale_imponibile)) {
if ($dbo->fetchNum('SELECT * FROM `co_ritenuta_contributi` WHERE `descrizione`='.prepare($descrizione).' AND `id`!='.prepare($id_record)) == 0) {
$dbo->query('UPDATE `co_ritenuta_contributi` SET `descrizione`='.prepare($descrizione).', `percentuale`='.prepare($percentuale).', `percentuale_imponibile`='.prepare($percentuale_imponibile).' WHERE `id`='.prepare($id_record));
$dbo->query('UPDATE `co_ritenuta_contributi` SET `descrizione`='.prepare($descrizione).', `tipologia`='.prepare($tipologia).', `causale`='.prepare($causale).', `percentuale`='.prepare($percentuale).', `percentuale_imponibile`='.prepare($percentuale_imponibile).' WHERE `id`='.prepare($id_record));
flash()->info(tr('Salvataggio completato!'));
} else {
flash()->error(tr("E' già presente una tipologia di _TYPE_ con la stessa descrizione!", [
@ -42,12 +44,14 @@ switch (filter('op')) {
case 'add':
$descrizione = filter('descrizione');
$tipologia = filter('tipologia');
$causale = filter('causale');
$percentuale = filter('percentuale');
$percentuale_imponibile = filter('percentuale_imponibile');
if (isset($descrizione) && isset($percentuale) && isset($percentuale_imponibile)) {
if ($dbo->fetchNum('SELECT * FROM `co_ritenuta_contributi` WHERE `descrizione`='.prepare($descrizione)) == 0) {
$dbo->query('INSERT INTO `co_ritenuta_contributi` (`descrizione`, `percentuale`, `percentuale_imponibile`) VALUES ('.prepare($descrizione).', '.prepare($percentuale).', '.prepare($percentuale_imponibile).')');
$dbo->query('INSERT INTO `co_ritenuta_contributi` (`descrizione`, `tipologia`, `causale`, `percentuale`, `percentuale_imponibile`) VALUES ('.prepare($descrizione).', '.prepare($tipologia).', '.prepare($causale).', '.prepare($percentuale).', '.prepare($percentuale_imponibile).')');
$id_record = $dbo->lastInsertedID();
flash()->info(tr('Aggiunta nuova tipologia di _TYPE_', [

View File

@ -29,6 +29,16 @@ include_once __DIR__.'/../../core.php';
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "<?php echo tr('Causale ritenuta'); ?>", "name": "causale", "values": "query=SELECT codice AS id, CONCAT_WS(' - ', codice, descrizione) AS descrizione FROM fe_causali_pagamento_ritenuta", "required": "1" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "<?php echo tr('Tipo ritenuta'); ?>", "name": "tipologia", "values": "query=SELECT codice AS id, CONCAT_WS(' - ', codice, descrizione) AS descrizione FROM fe_tipi_ritenuta", "required": "1" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "number", "label": "<?php echo tr('Percentuale'); ?>", "name": "percentuale", "min-value": "1", "max-value": "100","icon-after": "<i class=\"fa fa-percent\"></i>", "value": "100" ]}

View File

@ -46,6 +46,16 @@ if ($record['doc_associati'] > 0) {
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "<?php echo tr('Causale ritenuta'); ?>", "name": "causale", "values": "query=SELECT codice AS id, CONCAT_WS(' - ', codice, descrizione) AS descrizione FROM fe_causali_pagamento_ritenuta", "value": "$causale$", "required": "1" ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "<?php echo tr('Tipo ritenuta'); ?>", "name": "tipologia", "values": "query=SELECT codice AS id, CONCAT_WS(' - ', codice, descrizione) AS descrizione FROM fe_tipi_ritenuta", "value": "$tipologia$", "required": "1" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "number", "label": "<?php echo tr('Percentuale'); ?>", "name": "percentuale", "min-value": "1", "max-value": "100", "value": "$percentuale$", "icon-after": "<i class=\"fa fa-percent\"></i>" ]}

View File

@ -21,12 +21,14 @@ $r = $dbo->fetchOne('SELECT co_scadenziario.*, co_documenti.*,
an_anagrafiche.email,
an_anagrafiche.pec,
an_anagrafiche.ragione_sociale,
an_referenti.nome,
co_scadenziario.da_pagare - co_scadenziario.pagato AS totale,
(SELECT pec FROM em_accounts WHERE em_accounts.id='.prepare($template['id_account']).') AS is_pec,
(SELECT descrizione FROM co_pagamenti WHERE co_pagamenti.id = co_documenti.idpagamento) AS pagamento
FROM co_scadenziario
INNER JOIN co_documenti ON co_documenti.id = co_scadenziario.iddocumento
INNER JOIN an_anagrafiche ON co_documenti.idanagrafica = an_anagrafiche.idanagrafica
INNER JOIN an_anagrafiche ON co_documenti.idanagrafica = an_anagrafiche.idanagrafica
LEFT JOIN an_referenti ON an_referenti.idanagrafica = an_anagrafiche.idanagrafica
WHERE co_scadenziario.pagato != co_scadenziario.da_pagare AND co_scadenziario.iddocumento = (SELECT iddocumento FROM co_scadenziario s WHERE id='.prepare($id_record).')');
$logo_azienda = str_replace(base_dir(), base_path(), App::filepath('templates/base|custom|/logo_azienda.jpg'));
@ -43,4 +45,5 @@ return [
'data_scadenza' => Translator::dateToLocale($r['scadenza']),
'data' => Translator::dateToLocale($r['data']),
'logo_azienda' => !empty($logo_azienda) ? '<img src="'.$logo_azienda.'" />' : '',
'nome_referente' => $r['nome'],
];

View File

@ -164,7 +164,7 @@ class FatturaElettronica
$documento = $this->getDocumento();
$database = database();
$ordini = $database->fetchArray('SELECT `or_ordini`.`numero_cliente` AS id_documento, `or_ordini`.`num_item`, `or_ordini`.`codice_cig`, `or_ordini`.`codice_cup`, `or_ordini`.`codice_commessa`, `or_ordini`.`data_cliente`, `co_righe_documenti`.`order` AS riferimento_linea FROM `or_ordini` INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`idordine` = `or_ordini`.`id` WHERE `co_righe_documenti`.`iddocumento` = '.prepare($documento['id']));
$ordini = $database->fetchArray('SELECT `or_ordini`.`numero_cliente` AS id_documento, `or_ordini`.`num_item`, `or_ordini`.`codice_cig`, `or_ordini`.`codice_cup`, `or_ordini`.`codice_commessa`, `or_ordini`.`data_cliente` AS `data`, `co_righe_documenti`.`order` AS riferimento_linea FROM `or_ordini` INNER JOIN `co_righe_documenti` ON `co_righe_documenti`.`idordine` = `or_ordini`.`id` WHERE `co_righe_documenti`.`iddocumento` = '.prepare($documento['id']));
$dati_aggiuntivi = $documento->dati_aggiuntivi_fe;
$dati = $dati_aggiuntivi['dati_ordine'] ?: [];
@ -719,7 +719,11 @@ class FatturaElettronica
// Informazioni specifiche azienda
if ($azienda) {
$result['RegimeFiscale'] = setting('Regime Fiscale');
if ($anagrafica == static::getAzienda()) {
$result['RegimeFiscale'] = setting('Regime Fiscale');
} else {
$result['RegimeFiscale'] = 'RF18';
}
}
return $result;
@ -887,8 +891,12 @@ class FatturaElettronica
$righe = $fattura->getRighe();
// Ritenuta d'Acconto
$id_ritenuta = null;
$totale_ritenutaacconto = 0;
$id_ritenuta_acconto = null;
$totale_ritenuta_acconto = 0;
// Ritenuta Contributi
$id_ritenuta_contributi = $documento->id_ritenuta_contributi;
$totale_ritenuta_contributi = $documento->totale_ritenuta_contributi;
// Rivalsa
$id_rivalsainps = null;
@ -896,8 +904,8 @@ class FatturaElettronica
foreach ($righe as $riga) {
if (!empty($riga['idritenutaacconto']) and empty($riga['is_descrizione'])) {
$id_ritenuta = $riga['idritenutaacconto'];
$totale_ritenutaacconto += $riga['ritenutaacconto'];
$id_ritenuta_acconto = $riga['idritenutaacconto'];
$totale_ritenuta_acconto += $riga['ritenutaacconto'];
}
if (!empty($riga['idrivalsainps']) and empty($riga['is_descrizione'])) {
@ -907,17 +915,28 @@ class FatturaElettronica
}
}
if (!empty($id_ritenuta)) {
$percentuale = database()->fetchOne('SELECT percentuale FROM co_ritenutaacconto WHERE id = '.prepare($id_ritenuta))['percentuale'];
if (!empty($id_ritenuta_acconto)) {
$percentuale = database()->fetchOne('SELECT percentuale FROM co_ritenutaacconto WHERE id = '.prepare($id_ritenuta_acconto))['percentuale'];
// Con la nuova versione in vigore dal 01/01/2021, questo nodo diventa ripetibile.
$result['DatiRitenuta'] = [
$result[]['DatiRitenuta'] = [
'TipoRitenuta' => ($azienda['piva'] != $azienda['codice_fiscale'] & $azienda['tipo'] != 'Ente pubblico') ? 'RT01' : 'RT02',
'ImportoRitenuta' => $totale_ritenutaacconto,
'ImportoRitenuta' => $totale_ritenuta_acconto,
'AliquotaRitenuta' => $percentuale,
'CausalePagamento' => setting("Causale ritenuta d'acconto"),
];
}
if (!empty($id_ritenuta_contributi)) {
$ritenuta_contributi = database()->fetchOne('SELECT * FROM co_ritenuta_contributi WHERE id = '.prepare($id_ritenuta_contributi));
// Con la nuova versione in vigore dal 01/01/2021, questo nodo diventa ripetibile.
$result[]['DatiRitenuta'] = [
'TipoRitenuta' => $ritenuta_contributi['tipologia'],
'ImportoRitenuta' => $totale_ritenuta_contributi,
'AliquotaRitenuta' => $ritenuta_contributi['percentuale'],
'CausalePagamento' => $ritenuta_contributi['causale'],
];
}
// Bollo (2.1.1.6)
// ImportoBollo --> con la nuova versione in vigore dal 01/01/2021, la compilazione di questo nodo è diventata facoltativa.
// considerato che l'importo è noto e può essere solo di 2,00 Euro.

View File

@ -23,6 +23,7 @@ use Carbon\Carbon;
use Modules\DDT\DDT;
use Modules\Ordini\Ordine;
use Modules\Fatture\Fattura;
use Modules\Fatture\Stato;
use Modules\PrimaNota\Mastrino;
use Modules\PrimaNota\Movimento;
use Plugins\ImportFE\FatturaElettronica;
@ -145,11 +146,16 @@ switch (filter('op')) {
$fattura_pa->delete();
$fattura = Fattura::find($id_fattura);
$id_autofattura = post('autofattura');
$new_stato = Stato::where('descrizione', 'Pagato')->first();
if ($fattura->isAutofattura() && !empty($id_autofattura)) {
$autofattura_collegata = Fattura::find($id_autofattura);
$fattura->registraScadenze(true);
$autofattura_collegata->registraScadenze(true);
$fattura->stato()->associate($new_stato);
$autofattura_collegata->stato()->associate($new_stato);
$mastrino = Mastrino::build('Compensazione autofattura', $fattura->data, false, true);
$movimento1 = Movimento::build($mastrino, $fattura->anagrafica->idconto_cliente);
@ -162,6 +168,7 @@ switch (filter('op')) {
$fattura->id_autofattura = $id_autofattura;
$fattura->save();
$autofattura_collegata->save();
}
// Aggiorno la tipologia di anagrafica fornitore
@ -305,39 +312,65 @@ switch (filter('op')) {
$replaces = ['n ','N ','n. ','N. ','nr ','NR ','nr. ','NR. ','num ','NUM ','num. ','NUM. ','numero ','NUMERO '];
// Riorganizzazione dati ordini per numero di riga
$dati_ordini = [];
foreach ($DatiOrdini as $dato) {
foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) {
foreach ($replaces as $replace) {
if(string_starts_with($dato['IdDocumento'], $replace)) {
$dato['IdDocumento'] = str_replace($replace, '', $dato['IdDocumento']);
break;
// Riorganizzazione dati ordini per numero di riga
$dati_ordini = [];
foreach ($DatiOrdini as $dato) {
if (is_array($dato['RiferimentoNumeroLinea'])) {
foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) {
foreach ($replaces as $replace) {
if(string_starts_with($dato['IdDocumento'], $replace)) {
$dato['IdDocumento'] = str_replace($replace, '', $dato['IdDocumento']);
break;
}
}
$dati_ordini[(int)$linea] = [
'numero' => $dato['IdDocumento'],
'anno' => ( new Carbon($dato['Data']) )->format('Y'),
];
}
} else {
foreach ($replaces as $replace) {
if(string_starts_with($dato['IdDocumento'], $replace)) {
$dato['IdDocumento'] = str_replace($replace, '', $dato['IdDocumento']);
break;
}
}
$dati_ordini[(int)$dato['RiferimentoNumeroLinea']] = [
'numero' => $dato['IdDocumento'],
'anno' => ( new Carbon($dato['Data']) )->format('Y'),
];
}
}
$dati_ordini[(int)$linea] = [
'numero' => $dato['IdDocumento'],
'anno' => ( new Carbon($dato['Data']) )->format('Y'),
];
}
}
// Riorganizzazione dati ordini per numero di riga
$dati_ddt = [];
foreach ($DatiDDT as $dato) {
foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) {
foreach ($replaces as $replace) {
if(string_starts_with($dato['NumeroDDT'], $replace)) {
$dato['NumeroDDT'] = str_replace($replace, '', $dato['NumeroDDT']);
break;
// Riorganizzazione dati ordini per numero di riga
$dati_ddt = [];
foreach ($DatiDDT as $dato) {
if (is_array($dato['RiferimentoNumeroLinea'])) {
foreach ($dato['RiferimentoNumeroLinea'] as $dati => $linea) {
foreach ($replaces as $replace) {
if(string_starts_with($dato['NumeroDDT'], $replace)) {
$dato['NumeroDDT'] = str_replace($replace, '', $dato['NumeroDDT']);
break;
}
}
$dati_ddt[(int)$linea] = [
'numero' => $dato['NumeroDDT'],
'anno' => ( new Carbon($dato['DataDDT']) )->format('Y'),
];
}
} else {
foreach ($replaces as $replace) {
if(string_starts_with($dato['NumeroDDT'], $replace)) {
$dato['NumeroDDT'] = str_replace($replace, '', $dato['NumeroDDT']);
break;
}
}
$dati_ddt[(int)$dato['RiferimentoNumeroLinea']] = [
'numero' => $dato['NumeroDDT'],
'anno' => ( new Carbon($dato['DataDDT']) )->format('Y'),
];
}
}
$dati_ddt[(int)$linea] = [
'numero' => $dato['NumeroDDT'],
'anno' => ( new Carbon($dato['DataDDT']) )->format('Y'),
];
}
}
// Iterazione sulle singole righe
$righe = $fattura_pa->getRighe();

View File

@ -126,7 +126,7 @@ if (isset($fattura_body['DatiPagamento'])) {
}
$is_autofattura = false;
if (in_array($dati_generali['TipoDocumento'], ['TD16', 'TD17', 'TD18', 'TD19', 'TD20'])) {
if (in_array($dati_generali['TipoDocumento'], ['TD16', 'TD17', 'TD18', 'TD19', 'TD20', 'TD21'])) {
$is_autofattura = true;
}
@ -273,7 +273,7 @@ if (!empty($anagrafica)) {
INNER JOIN co_tipidocumento ON co_tipidocumento.id = co_documenti.idtipodocumento
WHERE
co_tipidocumento.dir = 'entrata' AND
co_tipidocumento.codice_tipo_documento_fe IN('TD16', 'TD17', 'TD18', 'TD19', 'TD20') AND
co_tipidocumento.codice_tipo_documento_fe IN('TD16', 'TD17', 'TD18', 'TD19', 'TD20', 'TD21') AND
(co_documenti.data BETWEEN NOW() - INTERVAL 1 YEAR AND NOW()) AND
co_documenti.idstatodocumento IN (SELECT id FROM co_statidocumento WHERE descrizione != 'Bozza') AND
co_documenti.idanagrafica = ".prepare($anagrafica->id);

View File

@ -211,9 +211,7 @@ class FatturaOrdinaria extends FatturaElettronica
$conto_arrotondamenti = $conto[$key];
}
if ($riga['Ritenuta'] == 'SI') {
$obj->id_rivalsa_inps = $id_rivalsa;
}
$obj->id_rivalsa_inps = $id_rivalsa;
$obj->ritenuta_contributi = $ritenuta_contributi;
@ -341,7 +339,7 @@ class FatturaOrdinaria extends FatturaElettronica
$totale_righe = sum($totali_righe, null, 2);
}
$diff = round(abs($totale_righe) - abs($fattura->totale_imponibile), 2);
$diff = round(abs($totale_righe) - abs($fattura->totale_imponibile + $fattura->rivalsa_inps), 2);
if (!empty($diff)) {
// Rimozione dell'IVA calcolata automaticamente dal gestionale
$iva_arrotondamento = database()->fetchOne('SELECT * FROM co_iva WHERE percentuale=0 AND deleted_at IS NULL');
@ -418,9 +416,7 @@ class FatturaOrdinaria extends FatturaElettronica
if (!empty($casse)) {
$totale = 0;
foreach ($righe as $riga) {
if ($riga['Ritenuta'] == 'SI') {
$totale += $riga['PrezzoTotale'];
}
$totale += $riga['PrezzoTotale'];
}
$casse = isset($casse[0]) ? $casse : [$casse];

View File

@ -29,7 +29,7 @@ $mesi = [
'07' => 'Luglio',
'08' => 'Agosto',
'09' => 'Settembre',
'11' => 'Ottobre',
'10' => 'Ottobre',
'11' => 'Novembre',
'12' => 'Dicembre',
];

View File

@ -29,7 +29,7 @@ $mesi = [
'07' => 'Luglio',
'08' => 'Agosto',
'09' => 'Settembre',
'11' => 'Ottobre',
'10' => 'Ottobre',
'11' => 'Novembre',
'12' => 'Dicembre',
];

View File

@ -164,11 +164,15 @@ class Backup
$ignores = [
'files' => [
'config.inc.php',
'*.lock',
'*.phar',
'*.log',
],
'dirs' => [
'node_modules',
'tests',
'tmp',
'.git',
],
];

View File

@ -129,6 +129,11 @@ class HTMLWrapper implements WrapperInterface
var message = container.find("span");
var icon = container.find("i");
var id_record = "'.$id_record.'";
if ($(".modal-content").is(":visible")) {
var id_record = "";
}
icon.attr("class", "fa fa-spinner fa-spin");
$.ajax({
@ -136,7 +141,7 @@ class HTMLWrapper implements WrapperInterface
type: "post",
data: {
id_module: "'.$id_module.'",
id_record: "'.$id_record.'",
id_record: id_record,
name: "'.$name.'",
value: value,
op: "validate",

View File

@ -201,9 +201,6 @@ class Generator
$maschera = Generator::complete($maschera, [], $date);
$maschera = str_replace('#', '%', $maschera);
//Lunghezza maschera
$mask_length = strlen($maschera);
$query = Manager::table($table)->select($field)->where($field, 'like', $maschera)->orderByRaw('LENGTH('.$field.') DESC')->orderByRaw($order);
foreach ($where as $and) {

View File

@ -21,6 +21,8 @@ use Carbon\CarbonInterval;
include_once __DIR__.'/../../core.php';
$prezzi_ivati = setting('Utilizza prezzi di vendita comprensivi di IVA');
// Creazione righe fantasma
$autofill = new \Util\Autofill($options['pricing'] ? 4 : 2);
$autofill->setRows(20, 10);
@ -159,7 +161,7 @@ foreach ($righe as $riga) {
// Prezzo unitario
echo '
<td class="text-right">
'.moneyFormat($riga->prezzo_unitario);
'.moneyFormat($prezzi_ivati ? $riga->prezzo_unitario_ivato : $riga->prezzo_unitario);
if ($riga->sconto > 0) {
$text = discountInfo($riga, false);
@ -176,7 +178,7 @@ foreach ($righe as $riga) {
// Imponibile
echo '
<td class="text-right">
'.moneyFormat($riga->totale_imponibile).'
'.moneyFormat($prezzi_ivati ? $riga->totale : $riga->totale_imponibile).'
</td>';
}
} else {

View File

@ -19,6 +19,8 @@
include_once __DIR__.'/../../core.php';
$prezzi_ivati = setting('Utilizza prezzi di vendita comprensivi di IVA');
// Creazione righe fantasma
$autofill = new \Util\Autofill($options['pricing'] ? 7 : 4);
$rows_per_page = 16;
@ -142,7 +144,7 @@ foreach ($righe as $riga) {
// Prezzo unitario
echo '
<td class="text-right" nowrap="nowrap">
'.moneyFormat($riga->prezzo_unitario);
'.moneyFormat($prezzi_ivati ? $riga->prezzo_unitario_ivato : $riga->prezzo_unitario);
if ($riga->sconto > 0) {
$text = discountInfo($riga, false);
@ -159,7 +161,7 @@ foreach ($righe as $riga) {
// Imponibile
echo '
<td class="text-right" nowrap="nowrap">
'.moneyFormat($riga->totale_imponibile).'
'.moneyFormat($prezzi_ivati ? $riga->totale : $riga->totale_imponibile).'
</td>';
// Iva

View File

@ -24,6 +24,8 @@ include_once __DIR__.'/../../core.php';
$v_iva = [];
$v_totale = [];
$prezzi_ivati = setting('Utilizza prezzi di vendita comprensivi di IVA');
// Creazione righe fantasma
$autofill = new \Util\Autofill(6, 40);
$rows_per_page = $fattura_accompagnatoria ? 13 : 18;
@ -178,7 +180,7 @@ foreach ($righe as $riga) {
// Prezzo unitario
echo '
<td class="text-right">
'.moneyFormat($riga->prezzo_unitario);
'.moneyFormat($prezzi_ivati ? $riga->prezzo_unitario_ivato : $riga->prezzo_unitario);
if ($riga->sconto > 0) {
$text = discountInfo($riga, false);
@ -195,7 +197,7 @@ foreach ($righe as $riga) {
// Imponibile
echo '
<td class="text-right">
'.moneyFormat($riga->totale_imponibile).'
'.moneyFormat($prezzi_ivati ? ($riga->totale_imponibile + $riga->iva) : $riga->totale_imponibile).'
</td>';
// Iva

View File

@ -38,7 +38,7 @@ $peso_lordo = $documento->peso ?: $documento->peso_calcolato;
$width = round(100 / ($show_sconto ? 5 : 3), 2);
$has_rivalsa = !empty($record['rivalsainps']);
$has_ritenuta = !empty($record['ritenutaacconto']) || !empty($documento->totale_ritenuta_contributi) || !empty($record['spit_payment']);
$has_ritenuta = !empty($record['ritenutaacconto']) || !empty($documento->totale_ritenuta_contributi) || !empty($record['split_payment']);
$has_split_payment = !empty($record['split_payment']);
$has_sconto_finale = !empty($sconto_finale);
@ -267,22 +267,41 @@ if ($has_ritenuta) {
--$second_colspan;
}
$contributi = (!empty($record['ritenutaacconto']) ? ' - ' : '').tr('contributi: _PRC_%', [
$contributi = tr('_DESCRIZIONE_: _PRC_%', [
'_DESCRIZIONE_' => $documento->ritenutaContributi->descrizione,
'_PRC_' => Translator::numberToLocale($documento->ritenutaContributi->percentuale, 2),
]);
$ritenuta_contributi_totale = abs($documento->totale_ritenuta_contributi);
$acconto = tr('acconto: _PRC_%', [
'_PRC_' => Translator::numberToLocale($rs2[0]['percentuale'], 2),
]);
$ritenuta_totale = abs($documento->ritenuta_acconto) + abs($documento->totale_ritenuta_contributi);
$ritenuta_acconto_totale = abs($documento->ritenuta_acconto);
if (!empty($ritenuta_acconto_totale) && !empty($ritenuta_contributi_totale)) {
--$first_colspan;
}
echo '
<tr>
<tr>';
if (!empty($ritenuta_acconto_totale)) {
echo '
<th class="text-center small" colspan="'.$first_colspan.'">
'.tr('Ritenuta (_ACCONTO__CONTRIBUTI_)', [
'.tr('Ritenuta _ACCONTO_', [
'_ACCONTO_' => $acconto,
], ['upper' => true]).'
</th>';
}
if (!empty($ritenuta_contributi_totale)) {
echo '
<th class="text-center small" colspan="'.$first_colspan.'">
'.tr('_CONTRIBUTI_', [
'_ACCONTO_' => $acconto,
'_CONTRIBUTI_' => empty($documento->ritenutaContributi) ? null : $contributi,
], ['upper' => true]).'
</th>';
}
echo '
<th class="text-center small" colspan="'.$second_colspan.'">
@ -292,12 +311,22 @@ if ($has_ritenuta) {
echo '
</tr>
<tr>
<tr>';
if (!empty($ritenuta_acconto_totale)) {
echo '
<td class="cell-padded text-center" colspan="'.$first_colspan.'">
'.moneyFormat($ritenuta_totale, 2).'
'.moneyFormat($ritenuta_acconto_totale, 2).'
</td>';
}
$totale = $totale - $ritenuta_totale;
if (!empty($ritenuta_contributi_totale)) {
echo '
<td class="cell-padded text-center" colspan="'.$first_colspan.'">
'.moneyFormat($ritenuta_contributi_totale, 2).'
</td>';
}
$totale = $totale - ($ritenuta_acconto_totale + $ritenuta_contributi_totale);
echo '
<td class="cell-padded text-center" colspan="'.$second_colspan.'">

View File

@ -411,24 +411,10 @@ $netto_a_pagare = abs($documento->netto);
$show_sconto = $sconto > 0;
$incorpora_iva = setting('Utilizza prezzi di vendita comprensivi di IVA');
// TOTALE COSTI FINALI
if ($options['pricing']) {
if ($incorpora_iva) {
// TOTALE INTERVENTO
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Totale intervento', [], ['upper' => true]).':</b>
</td>
<th class="text-center">
<b>'.moneyFormat($totale, 2).'</b>
</th>
</tr>';
} else {
// Totale imponibile
echo '
// Totale imponibile
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Imponibile', [], ['upper' => true]).':</b>
@ -439,35 +425,35 @@ if ($options['pricing']) {
</th>
</tr>';
// Eventuale sconto totale
if ($show_sconto) {
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Sconto', [], ['upper' => true]).':</b>
</td>
<th class="text-center">
<b>'.moneyFormat($sconto, 2).'</b>
</th>
</tr>';
// Totale imponibile
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Totale imponibile', [], ['upper' => true]).':</b>
</td>
<th class="text-center">
<b>'.moneyFormat($totale_imponibile, 2).'</b>
</th>
</tr>';
}
// IVA
// Totale intervento
// Eventuale sconto totale
if ($show_sconto) {
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Sconto', [], ['upper' => true]).':</b>
</td>
<th class="text-center">
<b>'.moneyFormat($sconto, 2).'</b>
</th>
</tr>';
// Totale imponibile
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Totale imponibile', [], ['upper' => true]).':</b>
</td>
<th class="text-center">
<b>'.moneyFormat($totale_imponibile, 2).'</b>
</th>
</tr>';
}
// IVA
// Totale intervento
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Iva', [], ['upper' => true]).':</b>
@ -478,8 +464,8 @@ if ($options['pricing']) {
</th>
</tr>';
// TOTALE INTERVENTO
echo '
// TOTALE INTERVENTO
echo '
<tr>
<td colspan="4" class="text-right">
<b>'.tr('Totale intervento', [], ['upper' => true]).':</b>
@ -488,7 +474,6 @@ if ($options['pricing']) {
<b>'.moneyFormat($totale, 2).'</b>
</th>
</tr>';
}
}
echo '

View File

@ -19,6 +19,8 @@
include_once __DIR__.'/../../core.php';
$prezzi_ivati = setting('Utilizza prezzi di vendita comprensivi di IVA');
// Righe documento
$righe = $documento->getRighe();
@ -169,7 +171,7 @@ foreach ($righe as $riga) {
// Prezzo unitario
echo '
<td class="text-right">
'.moneyFormat($riga->prezzo_unitario);
'.moneyFormat($prezzi_ivati ? $riga->prezzo_unitario_ivato : $riga->prezzo_unitario);
if ($riga->sconto > 0) {
$text = discountInfo($riga, false);
@ -186,7 +188,7 @@ foreach ($righe as $riga) {
// Imponibile
echo '
<td class="text-right">
'.moneyFormat($riga->totale_imponibile).'
'.moneyFormat($prezzi_ivati ? $riga->totale : $riga->totale_imponibile).'
</td>';
// Iva

View File

@ -27,6 +27,7 @@ include_once __DIR__.'/../../core.php';
$anagrafica = Anagrafica::find($documento['idanagrafica']);
$anagrafica_azienda = Anagrafica::find(setting('Azienda predefinita'));
$prezzi_ivati = setting('Utilizza prezzi di vendita comprensivi di IVA');
$pagamento = Pagamento::find($documento['idpagamento']);
@ -197,7 +198,7 @@ foreach ($righe as $riga) {
if ($riga->isArticolo() && !empty($riga->articolo->image)) {
echo '
<td align="center">
<img src="'.DOCROOT."/".$riga->articolo->image.'" style="max-height: 60px; max-width:80px">
<img src="'.$riga->articolo->image.'" style="max-height: 60px; max-width:80px">
</td>';
$autofill->set(5);
@ -235,7 +236,7 @@ foreach ($righe as $riga) {
// Prezzo unitario
echo '
<td class="text-right" style="vertical-align: middle">
'.moneyFormat($riga->prezzo_unitario);
'.moneyFormat($prezzi_ivati ? $riga->prezzo_unitario_ivato : $riga->prezzo_unitario);
if ($riga->sconto > 0) {
$text = discountInfo($riga, false);
@ -252,7 +253,7 @@ foreach ($righe as $riga) {
// Imponibile
echo '
<td class="text-right" style="vertical-align: middle" >
'.( $options['hide_total'] ? moneyFormat($riga->totale) : moneyFormat($riga->totale_imponibile) ).'
'.( ($options['hide_total'] || $prezzi_ivati) ? moneyFormat($riga->totale) : moneyFormat($riga->totale_imponibile) ).'
</td>';
// Iva

View File

@ -1,7 +1,21 @@
<?php
$scadenze = $dbo->fetchArray('SELECT * FROM co_scadenziario');
// File e cartelle deprecate
use PhpParser\Node\Stmt\Foreach_;
$files = [
'modules/scadenzario/controller_after.php',
];
foreach ($files as $key => $value) {
$files[$key] = realpath(base_dir().'/'.$value);
}
delete($files);
// Set dell'anagrafica a tutte le scadenze
$scadenze = $dbo->fetchArray('SELECT * FROM co_scadenziario');
foreach ($scadenze as $scadenza) {
$idanagrafica = $dbo->selectOne('co_documenti', 'idanagrafica', ['id' => $scadenza['iddocumento']])['idanagrafica'];
$dbo->update('co_scadenziario', [
@ -9,4 +23,33 @@ foreach ($scadenze as $scadenza) {
], ['id' => $scadenza['id']]);
}
// Eliminazione definitiva delle aliquote iva già eliminate, non utilizzate in nessuna tabella
$aliquote_eliminate = $dbo->fetchArray('SELECT * FROM co_iva WHERE deleted_at IS NOT NULL');
foreach ($aliquote_eliminate as $aliquota) {
$elimina_iva = true;
if(!empty($dbo->select('mg_articoli', 'id', ['idiva_vendita' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('an_anagrafiche', 'idanagrafica', ['idiva_vendite' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('an_anagrafiche', 'idanagrafica', ['idiva_acquisti' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('co_righe_contratti', 'id', ['idiva' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('dt_righe_ddt', 'id', ['idiva' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('co_righe_documenti', 'id', ['idiva' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('in_righe_interventi', 'id', ['idiva' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('co_righe_preventivi', 'id', ['idiva' => $aliquota['id']]))) {
$elimina_iva = false;
} elseif (!empty($dbo->select('or_righe_ordini', 'id', ['idiva' => $aliquota['id']]))) {
$elimina_iva = false;
}
if ($elimina_iva) {
$dbo->query('DELETE FROM co_iva WHERE id='.prepare($aliquota['id']));
}
}
?>

View File

@ -18,4 +18,7 @@ INSERT INTO `co_tipi_scadenze` (`id`, `nome`, `descrizione`, `ctgypurp`, `can_de
UPDATE `zz_views` SET `query` = 'an_anagrafiche.ragione_sociale' WHERE `zz_views`.`name` = 'Anagrafica' AND `id_module`=(SELECT `id` FROM `zz_modules` WHERE `name`='Scadenzario');
UPDATE `zz_modules` SET `options` = 'SELECT |select| FROM `co_scadenziario`\nLEFT JOIN `co_documenti` ON `co_scadenziario`.`iddocumento` = `co_documenti`.`id`\nLEFT JOIN `an_anagrafiche` ON `co_scadenziario`.`idanagrafica` = `an_anagrafiche`.`idanagrafica`\nLEFT JOIN `co_pagamenti` ON `co_documenti`.`idpagamento` = `co_pagamenti`.`id`\nLEFT JOIN `co_tipidocumento` ON `co_documenti`.`idtipodocumento` = `co_tipidocumento`.`id`\nLEFT JOIN `co_statidocumento` ON `co_documenti`.`idstatodocumento` = `co_statidocumento`.`id`\nLEFT JOIN (\n SELECT `zz_operations`.`id_email`, `zz_operations`.`id_record`\n FROM `zz_operations`\n INNER JOIN `em_emails` ON `zz_operations`.`id_email` = `em_emails`.`id`\n INNER JOIN `em_templates` ON `em_emails`.`id_template` = `em_templates`.`id`\n INNER JOIN `zz_modules` ON `zz_operations`.`id_module` = `zz_modules`.`id`\n WHERE `zz_modules`.`name` = \'Scadenzario\' AND `zz_operations`.`op` = \'send-email\'\n GROUP BY `zz_operations`.`id_record`\n ) AS `email` ON `email`.`id_record` = `co_scadenziario`.`id`\nWHERE 1=1 AND\n(`co_statidocumento`.`descrizione` IS NULL OR `co_statidocumento`.`descrizione` IN(\'Emessa\',\'Parzialmente pagato\',\'Pagato\'))\nHAVING 2=2\nORDER BY `scadenza` ASC' WHERE `zz_modules`.`name` = 'Scadenzario';
UPDATE `zz_modules` SET `options` = 'SELECT |select| FROM `co_scadenziario`\nLEFT JOIN `co_documenti` ON `co_scadenziario`.`iddocumento` = `co_documenti`.`id`\nLEFT JOIN `an_anagrafiche` ON `co_scadenziario`.`idanagrafica` = `an_anagrafiche`.`idanagrafica`\nLEFT JOIN `co_pagamenti` ON `co_documenti`.`idpagamento` = `co_pagamenti`.`id`\nLEFT JOIN `co_tipidocumento` ON `co_documenti`.`idtipodocumento` = `co_tipidocumento`.`id`\nLEFT JOIN `co_statidocumento` ON `co_documenti`.`idstatodocumento` = `co_statidocumento`.`id`\nLEFT JOIN (\n SELECT `zz_operations`.`id_email`, `zz_operations`.`id_record`\n FROM `zz_operations`\n INNER JOIN `em_emails` ON `zz_operations`.`id_email` = `em_emails`.`id`\n INNER JOIN `em_templates` ON `em_emails`.`id_template` = `em_templates`.`id`\n INNER JOIN `zz_modules` ON `zz_operations`.`id_module` = `zz_modules`.`id`\n WHERE `zz_modules`.`name` = \'Scadenzario\' AND `zz_operations`.`op` = \'send-email\'\n GROUP BY `zz_operations`.`id_record`\n ) AS `email` ON `email`.`id_record` = `co_scadenziario`.`id`\nWHERE 1=1 AND\n(`co_statidocumento`.`descrizione` IS NULL OR `co_statidocumento`.`descrizione` IN(\'Emessa\',\'Parzialmente pagato\',\'Pagato\'))\nHAVING 2=2\nORDER BY `scadenza` ASC' WHERE `zz_modules`.`name` = 'Scadenzario';
-- Aggiunta causale e tipologia in ritenute contributi
ALTER TABLE `co_ritenuta_contributi` ADD `tipologia` VARCHAR(100) NOT NULL AFTER `descrizione`, ADD `causale` VARCHAR(100) NOT NULL AFTER `tipologia`;