This commit is contained in:
MatteoPistorello 2023-12-05 10:48:10 +01:00
commit 1f4fca3c6e
48 changed files with 1398 additions and 194 deletions

View File

@ -90,3 +90,7 @@ ServerSignature Off
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</IfModule>
<IfModule mod_mime.c>
AddType text/javascript mjs
</IfModule>

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.52 ](#2452)
- [2.4.51 (2023-10-30)](#2451-2023-10-30)
- [2.4.50 (2023-10-06)](#2450-2023-10-06)
- [2.4.49 (2023-09-22)](#2449-2023-09-25)
@ -62,6 +63,17 @@ 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.52
### Aggiunto (Added)
- Aggiunta la gestione delle sedi definite come automezzi con pratico modulo per il carico/scarico degli articoli nell'automezzo, l'assegnazione di tecnici/autisti con date di validità e stampe di carico filtrabili
### Modificato (Changed)
- Aggiunta una limitazione sulle quantità scaricabili nei documenti di vendita in modo da non poter vendere più articoli di quelli presenti fisicamente nel magazzino selezionato. Questa limitazione è legata all'impostazione **Permetti selezione articoli con quantità minore o uguale a zero in Documenti di Vendita**
### Fixed
- Risolto il problema di visualizzazione dei PDF negli allegati
- Risolto un problema di movimentazione magazzino: gli articoli nelle attività venivano sempre movimentati da sede legale anche se specificata diversa sede di partenza nel documento (solo da popup di modifica articolo)
## 2.4.51 (2023-10-30)
### Aggiunto (Added)
- Aggiunta la gestione checklist nel plugin impianti

View File

@ -39,7 +39,7 @@ $(document).ready(function () {
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-right",
"positionClass": "toast-bottom-right",
//"preventDuplicates": true,
"onclick": null,
"showDuration": "300",

View File

@ -383,11 +383,6 @@ function renderMessages() {
let info = messages.info ? messages.info : [];
info.forEach(function (element) {
if (element) toastr["success"](element);
Toast.fire({
icon: "success",
title: element,
position: 'top',
});
});
let warning = messages.warning ? messages.warning : [];
@ -456,17 +451,17 @@ function alertPush() {
$('.alert-success.push').each(function () {
i++;
tops = 60 * i + 95;
bottoms = 60 * i;
$(this).css({
'position': 'fixed',
'z-index': 3000,
'right': '10px',
'top': -100,
'z-index': 300000,
'right': '10px',
'bottom': -100,
}).delay(1000).animate({
'top': tops,
'bottom': bottoms,
}).delay(3000).animate({
'top': -100,
'bottom': -100,
});
});
}
@ -474,7 +469,7 @@ function alertPush() {
// Nascondo la notifica se passo sopra col mouse
$('.alert-success.push').on('mouseover', function () {
$(this).stop().animate({
'top': -100,
'bottom': -100,
'opacity': 0
});
});

View File

@ -396,17 +396,24 @@ function csrf() {
}
function pdfjs() {
// Elenca tutte le cartelle dentro public e salva in una variabile l'ultima
const nodeModules = fs.readdirSync(config.nodeDirectory + '/pdf.js/public/',)
.filter(function (x) {
return x.indexOf('.') !== 0 && fs.statSync(config.nodeDirectory + '/pdf.js/public/' + x).isDirectory();
})
distDirectory = config.nodeDirectory + '/pdf.js/public/' + nodeModules[nodeModules.length - 1];
const web = gulp.src([
config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/**/*',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/cmaps/*',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/*.map',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/web/*.pdf',
distDirectory + '/web/**/*',
'!' + distDirectory + '/web/cmaps/*',
'!' + distDirectory + '/web/*.map',
'!' + distDirectory + '/web/*.pdf',
])
.pipe(gulp.dest(config.production + '/pdfjs/web'));
const build = gulp.src([
config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/build/*',
'!' + config.nodeDirectory + '/pdf.js/demo/vue/public/pdfjs-prebuilt/build/*.map',
distDirectory + '/build/*',
'!' + distDirectory + '/build/*.map',
])
.pipe(gulp.dest(config.production + '/pdfjs/build'));

View File

@ -630,10 +630,12 @@ if (Auth::check()) {
// Infomazioni
if (!empty($messages['info'])) {
foreach ($messages['info'] as $value) {
echo '
<div class="alert alert-success push">
<i class="fa fa-check"></i> '.$value.'
</div>';
echo '
<script>
$(document).ready( function(){
window.parent.toastr.success("'.$value.'", toastr.options);
});
</script>';
}
}

View File

@ -62,4 +62,26 @@ class Sede extends Model
{
return $this->belongsTo(Nazione::class, 'id_nazione');
}
public function save(array $options = [])
{
$this->fixRappresentanteFiscale();
return parent::save($options);
}
protected function fixRappresentanteFiscale()
{
$rappresentante_fiscale = post('is_rappresentante_fiscale');
if (!empty($rappresentante_fiscale)) {
self::where('idanagrafica', $this->idanagrafica)
->where('id', '!=', $this->id)
->update([
'is_rappresentante_fiscale' => 0,
]);
$this->attributes['is_rappresentante_fiscale'] = $rappresentante_fiscale;
}
}
}

View File

@ -444,16 +444,8 @@ class CSV extends CSVImporter
public static function getExample()
{
return [
['Codice', 'Barcode', 'Immagine', 'Import immagine', 'Descrizione', 'Fornitore predefinito', 'Quantità', 'Unità di misura', 'Prezzo acquisto', 'Prezzo vendita', 'Peso lordo (KG)', 'Volume (M3)', 'Categoria', 'Sottocategoria', 'Ubicazione', 'Note', 'Anagrafica listino', 'Codice fornitore', 'Barcode fornitore', 'Descrizione fornitore', 'Qta minima', 'Qta massima', 'Prezzo listino', 'Sconto listino', 'Cliente/Fornitore listino', 'Sede'],
['00004', '719376861871', 'https://immagini.com/immagine.jpg', '1', 'Articolo', 'Mario Rossi', '10', 'Kg', '5.25', '12.72', '10.2', '500', 'Categoria4', 'Sottocategoria2', 'Scaffale 1', 'Articolo di prova', 'Mario Rossi', 'artforn01', '384574557484', 'Articolo di prova fornitore', '', '', '10', '5', 'Fornitore', 'Sede2'],
['00004', '719376861871', 'https://immagini.com/immagine.jpg', '2', 'Articolo', 'Mario Rossi', '10', 'Kg', '5.25', '12.72', '10.2', '500', 'Categoria4', 'Sottocategoria2', 'Scaffale 1', 'Articolo di prova', 'Mario Rossi', 'artforn01', '384574557484', 'Articolo di prova fornitore', '1', '10', '9', '', 'Fornitore', 'Sede2'],
['00004', '719376861871', 'https://immagini.com/immagine.jpg', '3', 'Articolo', 'Mario Rossi', '10', 'Kg', '5.25', '12.72', '10.2', '500', 'Categoria4', 'Sottocategoria2', 'Scaffale 1', 'Articolo di prova', 'Mario Rossi', 'artforn01', '384574557484', 'Articolo di prova fornitore', '11', '20', '8', '5', 'Fornitore', 'Sede2'],
['00004', '719376861871', '', '', 'Articolo', 'Mario Rossi', '10', 'Kg', '5.25', '12.72', '10.2', '500', 'Categoria4', 'Sottocategoria2', 'Scaffale 1', 'Articolo di prova', 'Mario Verdi', '', '', '', '1', '10', '20', '10', 'Cliente', 'Sede2'],
[],
['Import immagine = 1 -> Permette di importare l\'immagine come principale dell\'articolo mantenendo gli altri allegati già presenti'],
['Import immagine = 2 -> Permette di importare l\'immagine come principale dell\'articolo rimuovendo tutti gli allegati presenti'],
['Import immagine = 3 -> Permette di importare l\'immagine come allegato dell\'articolo mantenendo gli altri allegati già presenti'],
['Import immagine = 4 -> Permette di importare l\'immagine come allegato dell\'articolo rimuovendo tutti gli allegati presenti'],
['Codice', 'Immagine', 'Import immagine', 'Descrizione', 'Quantità', 'Data inventario', 'Unità misura', 'Prezzo acquisto', 'Prezzo vendita', 'Peso', 'Volume', 'Categoria', 'Sottocategoria', 'Barcode', 'Fornitore', 'Partita IVA', 'Codice IVA vendita', 'Ubicazione', 'Note', 'Anagrafica listino', 'Codice fornitore', 'Barcode fornitore', 'Descrizione fornitore', 'Qta minima', 'Qta massima', 'Prezzo listino', 'Sconto listino', 'Cliente/Fornitore listino', 'Sede'],
['001', 'https://openstamanager.com/moduli/budget/budget.webp', '2', 'Modulo Budget', '1', '2023-11-28', 'PZ', '180.00', '180.00', '', '', 'Licenze', 'Moduli aggiuntivi', '0001', 'DevCode s.r.l.', '05024030289', '', '', '', '', 'Budget', '', 'Modulo Budget', '', '', '', '', 'Fornitore', 'Sede'],
];
}

View File

@ -0,0 +1,191 @@
<?php
include_once __DIR__.'/../../core.php';
use Carbon\Carbon;
use Modules\Articoli\Articolo;
switch (post('op')) {
case 'update':
$targa = post('targa');
$nome = post('nome');
$descrizione = post('descrizione');
if ($dbo->fetchNum('SELECT targa FROM an_sedi WHERE targa='.prepare($targa).' AND NOT id='.prepare($id_record)) == 0) {
$query = 'UPDATE an_sedi SET targa='.prepare($targa).', descrizione='.prepare($descrizione).', nome='.prepare($nome).' WHERE id='.prepare($id_record);
if ($dbo->query($query)) {
flash()->info(tr('Informazioni salvate correttamente!'));
}
} else {
flash()->error(tr('Esiste già un automezzo con questa targa!'));
}
break;
// Aggiunta automezzo
case 'add':
$targa = post('targa');
$nome = post('nome');
// Inserisco l'automezzo solo se non esiste un altro articolo con stesso targa
if ($dbo->fetchNum('SELECT targa FROM an_sedi WHERE targa='.prepare($targa)) == 0) {
$dbo->insert('an_sedi', [
'idanagrafica' => setting('Azienda predefinita'),
'nomesede' => $nome.' - '.$targa,
'is_automezzo' => 1,
'targa' => $targa,
'nome' => $nome,
]);
$id_record = $dbo->lastInsertedID();
flash()->info(tr('Aggiunto un nuovo automezzo!'));
} else {
flash()->error(tr('Esiste già un automezzo con questa targa!'));
}
break;
// Aggiunta tecnico
case 'addtech':
$idtecnico = post('idtecnico');
$data_inizio = post('data_inizio');
$data_fine = null;
// Controllo sull'effettivo inserimento di una data di fine successiva a quella di inizio
if (!empty(post('data_fine'))) {
if (new DateTime(post('data_fine')) >= new DateTime($data_inizio)) {
$data_fine = post('data_fine');
}
}
$data_fine = isset($data_fine) ? $data_fine : '0000-00-00';
// Inserisco il tecnico
$dbo->insert('an_sedi_tecnici', [
'idtecnico' => $idtecnico,
'idsede' => $id_record,
'data_inizio' => $data_inizio,
'data_fine' => $data_fine,
]);
flash()->info(tr('Collegato un nuovo tecnico!'));
break;
// Salvataggio tecnici collegati
case 'savetech':
$errors = 0;
foreach (post('data_inizio') as $idautomezzotecnico => $data) {
$idautomezzotecnico = $idautomezzotecnico;
$data_inizio = post('data_inizio')[$idautomezzotecnico];
$data_fine = null;
// Controllo sull'effettivo inserimento di una data di fine successiva a quella di inizio
if (!empty(post('data_fine')[$idautomezzotecnico])) {
if (new DateTime(post('data_fine')[$idautomezzotecnico]) >= new DateTime($data_inizio)) {
$data_fine = post('data_fine')[$idautomezzotecnico];
}
}
$data_fine = isset($data_fine) ? $data_fine : '0000-00-00';
$dbo->update('an_sedi_tecnici', [
'idtecnico' => $idtecnico,
'idsede' => $id_record,
'data_inizio' => $data_inizio,
'data_fine' => $data_fine,
], ['id' => $idautomezzotecnico]);
if (!$dbo->query($query)) {
++$errors;
}
}
if ($errors == 0) {
flash()->info(tr('Informazioni salvate correttamente!'));
} else {
flash()->error(tr('Errore durante il salvataggio del tecnico!'));
}
break;
// Eliminazione associazione con tecnico
case 'deltech':
$idautomezzotecnico = post('id');
$query = 'DELETE FROM an_sedi_tecnici WHERE id='.prepare($idautomezzotecnico);
if ($dbo->query($query)) {
flash()->info(tr('Tecnico rimosso!'));
}
break;
// Aggiunta quantità nell'automezzo
case 'addrow':
$idarticolo = post('idarticolo');
$qta = post('qta');
$articolo = Articolo::find($idarticolo);
$automezzo = $dbo->table('an_sedi')->where('id', $id_record)->first();
// Registrazione del movimento verso la sede di destinazione
$articolo->registra($qta, tr('Carico dal magazzino sull\'automezzo _SEDE_', ['_SEDE_' => $automezzo->nomesede]), Carbon::now(), 1, [
'idsede' => $id_record,
]);
// Registrazione del movimento dalla sede di origine
$articolo->registra(-$qta, tr('Scarico nel magazzino dall\'automezzo _SEDE_', ['_SEDE_' => $automezzo->nomesede]), Carbon::now(), 1, [
'idsede' => 0,
]);
flash()->info(tr("Caricato il magazzino dell'automezzo!"));
break;
case 'editrow':
$idarticolo = post('idarticolo');
$articolo = Articolo::find($idarticolo);
$automezzo = $dbo->table('an_sedi')->where('id', $id_record)->first();
$qta = post('qta') - $dbo->fetchOne('SELECT SUM(mg_movimenti.qta) AS qta FROM mg_movimenti WHERE mg_movimenti.idarticolo='.prepare($idarticolo).' AND mg_movimenti.idsede='.prepare($id_record))['qta'];
// Registrazione del movimento verso la sede di destinazione
$articolo->registra($qta, tr('Carico dal magazzino sull\'automezzo _SEDE_', ['_SEDE_' => $automezzo->nomesede]), Carbon::now(), 1, [
'idsede' => $id_record,
]);
// Registrazione del movimento dalla sede di origine
$articolo->registra(-$qta, tr('Scarico nel magazzino dall\'automezzo _SEDE_', ['_SEDE_' => $automezzo->nomesede]), Carbon::now(), 1, [
'idsede' => 0,
]);
flash()->info(tr("Caricato il magazzino dell'automezzo!"));
break;
// Spostamento scorta da automezzo a magazzino generale
case 'moverow':
$idarticolo = post('idarticolo');
$idautomezzotecnico = post('idautomezzotecnico');
$articolo = Articolo::find($idarticolo);
$automezzo = $dbo->table('an_sedi')->where('id', $idautomezzotecnico)->first();
$qta = $dbo->fetchOne('SELECT SUM(qta) AS qta FROM mg_movimenti WHERE idarticolo='.prepare($idarticolo).' AND idsede='.prepare($idautomezzotecnico))['qta'];
// Registrazione del movimento verso la sede di destinazione
$articolo->registra($qta, tr('Carico nel magazzino dall\'automezzo _SEDE_', ['_SEDE_' => $automezzo->nomesede]), Carbon::now(), 1, [
'idsede' => 0,
]);
// Registrazione del movimento dalla sede di origine
$descrizione = tr('Scarico dall\'automezzo _SEDE_ nel magazzino', [
'_SEDE_' => $automezzo->nomesede,
]);
$articolo->registra(-$qta, $descrizione, Carbon::now(), 1, [
'idsede' => $idautomezzotecnico,
]);
break;
case 'delete':
$dbo->query('DELETE FROM `an_sedi` WHERE `id`='.prepare($id_record));
flash()->info(tr('Automezzo eliminato e articoli riportati in magazzino!'));
break;
}

25
modules/automezzi/add.php Normal file
View File

@ -0,0 +1,25 @@
<?php
include_once __DIR__.'/../../core.php';
?><form action="" method="post" id="add-form">
<input type="hidden" name="op" value="add">
<input type="hidden" name="backto" value="record-edit">
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "<?php echo tr('Nome'); ?>", "name": "nome", "required": 1 ]}
</div>
<div class="col-md-6">
{[ "type": "text", "label": "<?php echo tr('Targa'); ?>", "name": "targa", "required": 1, "maxlength": 10, "class": "alphanumeric-mask" ]}
</div>
</div>
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary"><i class="fa fa-plus"></i> <?php echo tr('Aggiungi'); ?></button>
</div>
</div>
</form>

View File

@ -0,0 +1,48 @@
<?php
include_once __DIR__.'/../../core.php';
$idautomezzo = get('idautomezzo');
$idarticolo = get('idarticolo');
$op = 'addrow';
$qta = 1;
if (!empty($idarticolo) && !empty($idautomezzo)) {
$qta = $dbo->fetchOne('SELECT SUM(mg_movimenti.qta) AS qta FROM mg_movimenti WHERE mg_movimenti.idarticolo='.prepare($idarticolo).' AND mg_movimenti.idsede='.prepare($idautomezzo))['qta'];
$op = 'editrow';
}
/*
Form di inserimento riga documento
*/
echo '
<form id="link_form" action="'.$rootdir.'/editor.php?id_module='.Modules::get('Automezzi')['id'].'&id_record='.$idautomezzo.'" method="post">
<input type="hidden" name="op" value="'.$op.'">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="id_record" value="'.$idautomezzo.'">';
// Seleziona articolo
echo '
<div class="col-md-8">
{[ "type": "select", "label": "'.tr('Articolo').'", "name": "idarticolo", "required": 1, "value": "'.$idarticolo.'", "ajax-source": "articoli" ]}
</div>';
// Quantità
echo '
<div class="col-md-4">
{[ "type": "number", "label": "'.tr('Q.tà su questo automezzo').'", "name": "qta", "value": "'.$qta.'", "decimals": "qta" ]}
</div>';
echo '
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary pull-right"><i class="fa fa-plus"></i> '.tr('Aggiungi').'</button>
</div>
</div>
</form>';
echo '
<script>
$(document).ready(function(){init();});
</script>';

View File

@ -0,0 +1,58 @@
<?php
include_once __DIR__.'/../../core.php';
$id_record = get('idautomezzo');
// Form di inserimento responsabili automezzo
echo '
<form action="'.$rootdir.'/editor.php?id_module='.Modules::get('Automezzi')['id'].'&id_record='.$id_record.'" method="post">
<input type="hidden" name="op" value="addtech">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="id_record" value="'.$id_record.'">
<div class="row">';
// Tecnico
echo '
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Tecnico').'", "name": "idtecnico", "required": 1, "values": "query=SELECT an_anagrafiche.idanagrafica AS id, ragione_sociale AS descrizione FROM an_anagrafiche INNER JOIN (an_tipianagrafiche_anagrafiche INNER JOIN an_tipianagrafiche ON an_tipianagrafiche_anagrafiche.idtipoanagrafica=an_tipianagrafiche.idtipoanagrafica) ON an_anagrafiche.idanagrafica=an_tipianagrafiche_anagrafiche.idanagrafica WHERE (descrizione=\'Tecnico\') AND deleted_at IS NULL ORDER BY ragione_sociale", "value": "'.$idtecnico.'" ]}
</div>';
// Data di partenza
echo '
<div class="col-md-3">
{[ "type": "date", "label": "'.tr('Data dal').'", "name": "data_inizio", "required": 1, "value": "-now-" ]}
</div>';
// Data di fine
echo '
<div class="col-md-3">
{[ "type": "date", "label": "'.tr('Data al').'", "name": "data_fine", "min-date": "-now-" ]}
</div>';
echo '
</div>
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary pull-right"><i class="fa fa-plus"></i> '.tr('Aggiungi').'</button>
</div>
</div>
</form>';
echo '
<script type="text/javascript">
$(document).ready(function(){init();});
$(function () {
$("#data_inizio").on("dp.change", function (e) {
$("#data_fine").data("DateTimePicker").minDate(e.date);
if($("#data_fine").data("DateTimePicker").date() < e.date){
$("#data_fine").data("DateTimePicker").date(e.date);
}
})
});
</script>';

View File

@ -0,0 +1,47 @@
<?php
include_once __DIR__.'/../../../core.php';
$link_id = Modules::get('Automezzi')['id'];
$fields = [
'Nome' => 'nome',
'Descrizione' => 'descrizione',
'Targa' => 'targa',
];
$query = 'SELECT *';
foreach ($fields as $name => $value) {
$query .= ', '.$value." AS '".str_replace("'", "\'", $name)."'";
}
$query .= ' FROM dt_automezzi WHERE 1=0 ';
foreach ($fields as $name => $value) {
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
}
$query .= Modules::getAdditionalsQuery('Automezzi');
$rs = $dbo->fetchArray($query);
foreach ($rs as $r) {
$result = [];
$result['link'] = ROOTDIR.'/editor.php?id_module='.$link_id.'&id_record='.$r['id'];
$result['title'] = $r['nome'];
$result['category'] = 'Automezzi';
// Campi da evidenziare
$result['labels'] = [];
foreach ($fields as $name => $value) {
if (str_contains($r[$name], $term)) {
$text = str_replace($term, "<span class='highlight'>".$term.'</span>', $r[$name]);
$result['labels'][] = $name.': '.$text.'<br/>';
}
}
$results[] = $result;
}

115
modules/automezzi/edit.php Normal file
View File

@ -0,0 +1,115 @@
<?php
include_once __DIR__.'/../../core.php';
unset($_SESSION['superselect']['idautomezzo']);
?><form action="" method="post" id="edit-form">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="op" value="update">
<input type="hidden" name="id_record" value="<?php echo $id_record; ?>">
<!-- DATI ARTICOLO -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"><?php echo tr('Automezzo'); ?></h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
{[ "type": "text", "label": "<?php echo tr('Nome'); ?>", "name": "nome", "required": 1, "value": "$nome$" ]}
</div>
<div class="col-md-4">
{[ "type": "text", "label": "<?php echo tr('Targa'); ?>", "name": "targa", "required": 1, "maxlength": 10, "class": "alphanumeric-mask", "value": "$targa$" ]}
</div>
</div>
<div class="row">
<div class="col-md-12">
{[ "type": "textarea", "label": "<?php echo tr('Descrizione'); ?>", "name": "descrizione", "value": "$descrizione$" ]}
</div>
</div>
</div>
</div>
</form>
<!-- TECNICI + MAGAZZINO AUTOMEZZO -->
<div class="row">
<!--TECNICI -->
<div class="col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="row">
<div class="col-md-12">
<h3 class="panel-title"><?php echo tr('Tecnici responsabili automezzo'); ?></h3>
</div>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-12" >
<form action="<?php echo $rootdir; ?>/editor.php?id_module=<?php echo Modules::get('Automezzi')['id']; ?>&id_record=<?php echo $id_record; ?>" id="updatetech-form" method="post" role="form">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="id_record" value="<?php echo $id_record; ?>">
<input type="hidden" name="op" value="">
<?php
include $docroot.'/modules/automezzi/row-list-tecnici.php';
?>
</form>
<a href="javascript:;" class="btn btn-sm btn-success pull-right" title="Aggiorna date" onclick="$('#updatetech-form input[name=op]').val('savetech'); $('#updatetech-form').submit();"><i class="fa fa-edit"></i> <?php echo tr('Salva date'); ?></a>
<div class="pull-left">
<a class="btn btn-sm btn-primary" data-href="<?php echo $rootdir; ?>/modules/automezzi/add_tecnico.php?idautomezzo=<?php echo $id_record; ?>" data-toggle="modal" data-title="Aggiungi tecnico"><i class="fa fa-plus"></i> <?php echo tr('Aggiungi tecnico'); ?></a><br>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</div>
<!-- MAGAZZINO AUTOMEZZO -->
<div class="col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="row">
<div class="col-md-12">
<h3 class="panel-title"><?php echo tr('Magazzino automezzo'); ?></h3>
</div>
</div>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<?php
include $docroot.'/modules/automezzi/row-list-articoli.php';
?>
<div class="pull-left">
<a class="btn btn-sm btn-primary" data-href="<?php echo $rootdir; ?>/modules/automezzi/add_articolo.php?idautomezzo=<?php echo $id_record; ?>" data-toggle="modal" data-title="Aggiungi articoli"><i class="fa fa-plus"></i> <?php echo tr('Articolo magazzino'); ?></a><br>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="btn btn-danger ask" data-backto="record-list">
<i class="fa fa-trash"></i> <?php echo tr('Elimina'); ?>
</a>
<script>
$(document).ready(function(){
$("#pulsanti .btn-info").addClass("hidden");
});
</script>

View File

@ -0,0 +1,7 @@
<?php
include_once __DIR__.'/../../core.php';
if (isset($id_record)) {
$record = $dbo->fetchOne('SELECT * FROM an_sedi WHERE an_sedi.id='.prepare($id_record));
}

View File

@ -0,0 +1,66 @@
<?php
include_once __DIR__.'/../../core.php';
// Elenco articoli caricati sull'automezzo
$rs2 = $dbo->fetchArray('SELECT mg_movimenti.idsede AS id, mg_articoli.codice AS codice, idarticolo, SUM(mg_movimenti.qta) AS qta_automezzo, mg_articoli.qta AS qta_magazzino, mg_articoli.descrizione, mg_articoli.prezzo_vendita, (SELECT percentuale FROM co_iva WHERE id=mg_articoli.idiva_vendita) AS prciva_vendita FROM mg_movimenti INNER JOIN mg_articoli ON mg_movimenti.idarticolo=mg_articoli.id WHERE mg_movimenti.idsede='.prepare($id_record).' GROUP BY idarticolo HAVING qta_automezzo>0 ORDER BY mg_articoli.descrizione');
if (!empty($rs2)) {
echo '
<div style="max-height: 300px; overflow: auto;">
<table class="table table-striped table-hover table-condensed">
<tr>
<th>'.tr('Articolo').'</th>
<th width="25%">'.tr('Q.').'</th>
<th width="25%">'.tr('Prezzo di vendita').'</th>
<th width="10%"></th>
</tr>';
foreach ($rs2 as $r) {
echo '
<tr>';
// Articolo
echo '
<td class="text-left">
'.Modules::link('Articoli', $r['idarticolo'], $r['codice'].' - '.$r['descrizione']).'
</td>';
// Quantità
echo '
<td class="first_cell center">
<span><big>'.Translator::numberToLocale($r['qta_automezzo']).'</big></span><br/>
<small>'.tr('Q. magazzino').': '.Translator::numberToLocale($r['qta_magazzino']).'</small><br/>
</td>';
// Prezzo di vendita
$netto = $r['prezzo_vendita'];
$iva = $r['prezzo_vendita'] / 100 * $r['prciva_vendita'];
echo '
<td class="table_cell center">
<span>'.Translator::numberToLocale($netto + $iva).' &euro;</span><br/>
<small>'.tr('Netto').': '.Translator::numberToLocale($netto).' &euro;</small><br/>
<small>'.tr('Iva').': '.Translator::numberToLocale($iva).' &euro;</small><br/>
</td>';
// Pulsanti
echo '
<td class="text-center">
<a class="btn btn-warning btn-xs" data-href="'.$structure->fileurl('add_articolo.php').'?idautomezzo='.$id_record.'&idarticolo='.$r['idarticolo'].'" data-toggle="modal" data-title="'.tr('Aggiungi articoli').'">
<i class="fa fa-edit"></i>
</a>
<a class="btn btn-danger btn-xs ask" data-backto="record-edit" data-op="moverow" data-idautomezzotecnico="'.$r['id'].'", data-idarticolo="'.$r['idarticolo'].'" data-msg="'.tr("Rimuovere articolo dell'automezzo?").'">
<i class="fa fa-trash"></i>
</a>
</td>
</tr>';
$tot_articoli += $r['qta_automezzo'];
}
echo '
</table>
</div>';
} else {
echo '
<p>'.tr('Nessun articolo presente').'...</p>';
}

View File

@ -0,0 +1,59 @@
<?php
include_once __DIR__.'/../../core.php';
/*
TECNICI ASSEGNATI ALL'AUTOMEZZO
*/
$q_art = 'SELECT an_sedi_tecnici.*, an_anagrafiche.ragione_sociale FROM an_sedi_tecnici INNER JOIN an_anagrafiche ON an_anagrafiche.idanagrafica=an_sedi_tecnici.idtecnico WHERE an_sedi_tecnici.idsede='.prepare($id_record);
$rs_art = $dbo->fetchArray($q_art);
if (!empty($rs_art)) {
echo '
<div style="max-height: 300px; overflow: auto;">
<table class="table table-striped table-hover table-condensed">
<tr>
<th>'.tr('Tecnico').'</th>
<th width="25%">'.tr('Dal').'</th>
<th width="25%">'.tr('Al').'</th>
<th width="5%"></th>
</tr>';
foreach ($rs_art as $r) {
// Tecnico
echo '
<tr>
<td>
<input type="hidden" name="idautomezzotecnico[]" value="'.$r['id'].'">
'.$r['ragione_sociale'].'
</td>';
// Data di inizio
echo '
<td>
{[ "type": "date", "name": "data_inizio['.$r['id'].']", "required": 1, "value": "'.$r['data_inizio'].'" ]}
</td>';
// Data di fine
echo '
<td>
{[ "type": "date", "name": "data_fine['.$r['id'].']", "required": 1, "value": "'.$r['data_fine'].'", "min-date": "'.$r['data_inizio'].'" ]}
</td>';
// Pulsanti per aggiornamento date tecnici
echo '
<td>
<a class="btn btn-danger ask" data-backto="record-edit" data-op="deltech" data-id="'.$r['id'].'" data-msg="'.tr("Rimuovere il tecnico responsabile dell'automezzo?").'">
<i class="fa fa-trash"></i>
</a>
</td>
</tr>';
}
echo '
</table>
</div>';
} else {
echo '
<p>'.tr('Nessun tecnico inserito').'...</p>';
}

View File

@ -285,7 +285,11 @@ switch (post('op')) {
$riga = null;
}
flash()->info(tr('Righe eliminate!'));
if (count($id_righe) == 1) {
flash()->info(tr('Riga eliminata!'));
} else {
flash()->info(tr('Righe eliminate!'));
}
break;

View File

@ -275,7 +275,7 @@ $operations['cambia_stato'] = [
'text' => '<span><i class="fa fa-refresh"></i> '.tr('Cambia stato'),
'data' => [
'title' => tr('Vuoi davvero aggiornare lo stato di questi contratti?'),
'msg' => '<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione FROM co_staticontratti ORDER BY descrizione" ]}',
'msg' => '<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione, colore as _bgcolor_ FROM co_staticontratti ORDER BY descrizione" ]}',
'button' => tr('Procedi'),
'class' => 'btn btn-lg btn-warning',
'blank' => false,

View File

@ -392,7 +392,12 @@ switch (filter('op')) {
}
ricalcola_costiagg_ddt($id_record);
flash()->info(tr('Righe eliminate!'));
if (count($id_righe) == 1) {
flash()->info(tr('Riga eliminata!'));
} else {
flash()->info(tr('Righe eliminate!'));
}
break;
@ -408,12 +413,13 @@ switch (filter('op')) {
$new_riga = $riga->replicate();
$new_riga->setDocument($ddt);
$new_riga->qta_evasa = 0;
$new_riga->save();
if ($new_riga->isArticolo()) {
$new_riga->movimenta($new_riga->qta);
}
$new_riga->save();
$riga = null;
}
@ -502,12 +508,12 @@ switch (filter('op')) {
$copia_riga->original_id = null;
$copia_riga->original_type = null;
$copia_riga->save();
// Movimentazione forzata in direzione del documento
if ($copia_riga->isArticolo()) {
$copia_riga->movimenta($copia_riga->qta);
}
$copia_riga->save();
}
// Salvataggio riferimento
@ -539,11 +545,12 @@ switch (filter('op')) {
$new_riga->qta_evasa = 0;
$new_riga->idordine = 0;
$new_riga->save();
if ($new_riga->isArticolo()) {
$new_riga->movimenta($new_riga->qta);
}
$new_riga->save();
}
flash()->info(tr('DDT duplicato correttamente!'));

View File

@ -195,7 +195,7 @@ $operations['crea_fattura'] = [
'data' => [
'title' => tr('Vuoi davvero cambiare lo stato per questi DDT?'),
'msg' => tr('Seleziona lo stato in cui spostare tutti i DDT').'.<br>
<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione FROM dt_statiddt" ]}',
<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione, colore as _bgcolor_ FROM dt_statiddt" ]}',
'button' => tr('Procedi'),
'class' => 'btn btn-lg btn-warning',
'blank' => false,

View File

@ -160,10 +160,12 @@ foreach ($righe as $riga) {
$evasione_bar['or_righe_ordini'] = 'success';
foreach ($evasione_bar as $table => $color) {
$righe_ev = $dbo->table($table)->where('original_id', $riga->id)->where('original_type', get_class($riga))->get();
$perc_ev = $righe_ev->sum('qta') * 100 / $riga->qta;
if ($perc_ev > 0) {
echo '
<div class="progress-bar progress-bar-'.$color.'" style="width:'.$perc_ev.'%"></div>';
if ($righe_ev->count() > 0) {
$perc_ev = $righe_ev->sum('qta') * 100 / $riga->qta;
if ($perc_ev > 0) {
echo '
<div class="progress-bar progress-bar-'.$color.'" style="width:'.$perc_ev.'%"></div>';
}
}
}
echo '

View File

@ -31,6 +31,7 @@ use Modules\Fatture\Fattura;
use Modules\Fatture\Stato;
use Modules\Fatture\Tipo;
use Modules\Iva\Aliquota;
use Plugins\ExportFE\Interaction;
use Util\XML;
$module = Modules::get($id_module);
@ -46,10 +47,26 @@ $stato_fe = $dbo->fetchOne('SELECT codice_stato_fe FROM co_documenti WHERE id =
$ops = ['update', 'add_intervento', 'manage_documento_fe', 'manage_riga_fe', 'manage_articolo', 'manage_sconto', 'manage_riga', 'manage_descrizione', 'unlink_intervento', 'delete_riga', 'copy_riga', 'add_serial', 'add_articolo', 'edit-price'];
if ($dir == 'entrata' && $stato_fe['codice_stato_fe'] == 'WAIT' && setting('OSMCloud Services API Token') != '' && in_array($op, $ops)) {
flash()->warning(tr('La fattura numero _NUM_ è già stata inviata allo SDI, non è possibile effettuare modifiche!', [
'_NUM_' => $fattura->numero_esterno,
]));
if ($dir === 'entrata' && in_array($stato_fe['codice_stato_fe'], ['WAIT', 'RC', 'MC', 'QUEUE', 'DT', 'EC01', 'NE']) && Interaction::isEnabled() && in_array($op, $ops)) {
//Permetto sempre la modifica delle note aggiuntive e/o della data di competenza della fattura di vendita
if ($op == 'update' && ($fattura->note_aggiuntive != post('note_aggiuntive') || $fattura->data_competenza != post('data_competenza'))) {
if ($fattura->note_aggiuntive != post('note_aggiuntive')) {
$fattura->note_aggiuntive = post('note_aggiuntive');
$fattura->save();
flash()->info(tr('Note interne modificate correttamente.'));
}
if ($fattura->data_competenza != post('data_competenza')) {
$fattura->data_competenza = post('data_competenza');
$fattura->save();
flash()->info(tr('Data competenza modificata correttamente.'));
}
} else {
flash()->warning(tr('La fattura numero _NUM_ è già stata inviata allo SDI, non è possibile effettuare modifiche.', [
'_NUM_' => $fattura->numero_esterno,
]));
}
$op = null;
}
@ -372,11 +389,12 @@ switch ($op) {
$new_riga->idintervento = 0;
$new_riga->idddt = 0;
$new_riga->idordine = 0;
$new_riga->save();
if ($new_riga->isArticolo()) {
$new_riga->movimenta($new_riga->qta);
}
$new_riga->save();
}
flash()->info(tr('Fattura duplicata correttamente!'));
@ -655,6 +673,11 @@ switch ($op) {
}
$riga = null;
}
if (count($id_righe) == 1) {
flash()->info(tr('Riga eliminata!'));
} else {
flash()->info(tr('Righe eliminate!'));
}
@ -672,12 +695,13 @@ switch ($op) {
$new_riga = $riga->replicate();
$new_riga->setDocument($fattura);
$new_riga->qta_evasa = 0;
$new_riga->save();
if ($new_riga->isArticolo()) {
$new_riga->movimenta($new_riga->qta);
}
$new_riga->save();
$riga = null;
}

View File

@ -74,10 +74,12 @@ class Scadenze
$ultima_scadenza = $this->fattura->scadenze->last();
$scadenza = $ultima_scadenza->scadenza->copy()->startOfMonth()->addMonth();
$scadenza->setDate($scadenza->year, $scadenza->month, 15);
$id_pagamento = $this->fattura->idpagamento;
$id_banca_azienda = $this->fattura->id_banca_azienda;
$id_banca_controparte = $this->fattura->id_banca_controparte;
$importo = -$ritenuta_acconto;
self::registraScadenza($this->fattura, $importo, $scadenza, $is_pagato, 'ritenutaacconto');
self::registraScadenza($this->fattura, $importo, $scadenza, $is_pagato, $id_pagamento, $id_banca_azienda, $id_banca_controparte, 'ritenutaacconto');
}
}
@ -134,12 +136,15 @@ class Scadenze
foreach ($pagamenti as $pagamento) {
$rate = $pagamento['DettaglioPagamento'];
$rate = isset($rate[0]) ? $rate : [$rate];
$id_banca_azienda = $this->fattura->id_banca_azienda;
$id_banca_controparte = $this->fattura->id_banca_controparte;
$id_pagamento = $this->fattura->idpagamento;
foreach ($rate as $rata) {
$scadenza = !empty($rata['DataScadenzaPagamento']) ? FatturaElettronicaImport::parseDate($rata['DataScadenzaPagamento']) : $this->fattura->data;
$importo = $this->fattura->isNota() ? $rata['ImportoPagamento'] : -$rata['ImportoPagamento'];
self::registraScadenza($this->fattura, $importo, $scadenza, $is_pagato);
self::registraScadenza($this->fattura, $importo, $scadenza, $is_pagato, $id_pagamento, $id_banca_azienda, $id_banca_controparte);
}
}

View File

@ -169,7 +169,7 @@ class CSV extends CSVImporter
'id_record' => $impianto->id,
]);
$database->update('mg_articoli', [
$database->update('my_impianti', [
'immagine' => '',
], [
'id' => $impianto->id,
@ -191,7 +191,7 @@ class CSV extends CSVImporter
if ($record['import_immagine'] == 1 || $record['import_immagine'] == 2) {
if (!empty($filename)) {
$database->update('mg_articoli', [
$database->update('my_impianti', [
'immagine' => $filename,
], [
'id' => $impianto->id,
@ -208,16 +208,11 @@ class CSV extends CSVImporter
public static function getExample()
{
return [
['Matricola', 'Nome', 'Categoria', 'Immagine', 'Data installazione', 'Cliente', 'Telefono', 'Sede'],
['00001', 'Marca', 'Lavatrice', 'https://immagini.com/immagine.jpg', '01/10/2023', 'Mario Rossi', '04444444', 'Sede2'],
['00002', 'Marca2', 'Lavastoviglie', 'https://immagini.com/immagine2.jpg', '12/09/2023', 'Mario Rossi', '04444444', 'Sede2'],
['00003', 'Marca3', 'Frigorifero', 'https://immagini.com/immagine3.jpg', '20/09/2023', 'Mario Rossi', '04444444', 'Sede2'],
['00004', 'Marca4', 'Caldaia', 'https://immagini.com/immagine4.jpg', '06/11/2023', 'Mario Rossi', '04444444', 'Sede2'],
[],
['Import immagine = 1 -> Permette di importare l\'immagine come principale dell\'impianto mantenendo gli altri allegati già presenti'],
['Import immagine = 2 -> Permette di importare l\'immagine come principale dell\'impianto rimuovendo tutti gli allegati presenti'],
['Import immagine = 3 -> Permette di importare l\'immagine come allegato dell\'impianto mantenendo gli altri allegati già presenti'],
['Import immagine = 4 -> Permette di importare l\'immagine come allegato dell\'impianto rimuovendo tutti gli allegati presenti'],
['Matricola', 'Immagine', 'Import immagine', 'Nome', 'Cliente', 'Telefono', 'Categoria', 'Sottocategoria', 'Sede', 'Descrizione', 'Data installazione'],
['00001', 'https://openstamanager.com/moduli/budget/budget.webp', '2', 'Lavatrice', 'Mario Rossi', '04444444', 'Elettrodomestici', 'Marca1', '', '', '2023-01-01'],
['00002', 'https://openstamanager.com/moduli/3cx/3cx.webp', '2', 'Caldaia', 'Mario Rossi', '04444444', 'Elettrodomestici', 'Marca2', '', '', '2023-03-06'],
['00003', 'https://openstamanager.com/moduli/disponibilita-tecnici/tecnici.webp', '2', 'Forno', 'Mario Rossi', '04444444', 'Elettrodomestici', 'Marca3', '', '', '2023-04-01'],
['00004', 'https://openstamanager.com/moduli/distinta-base/distinta.webp', '2', 'Lavastoviglie', 'Mario Rossi', '04444444', 'Elettrodomestici', 'Marca4', '', '', '2023-08-06'],
];
}
}

View File

@ -29,7 +29,7 @@ include_once __DIR__.'/../../core.php';
</div>
<div class="col-md-6">
{[ "type": "select", "label": "<?php echo tr('Modulo'); ?>", "name": "id_import", "required": 1, "values": "query=SELECT id, name AS text FROM zz_imports" ]}
{[ "type": "select", "label": "<?php echo tr('Modulo'); ?>", "name": "id_import", "required": 1, "values": "query=SELECT id, name AS text FROM zz_imports ORDER BY name" ]}
</div>
</div>

View File

@ -440,7 +440,11 @@ switch (post('op')) {
$riga = null;
}
flash()->info(tr('Righe eliminate!'));
if (count($id_righe) == 1) {
flash()->info(tr('Riga eliminata!'));
} else {
flash()->info(tr('Righe eliminate!'));
}
break;
@ -455,12 +459,13 @@ switch (post('op')) {
$new_riga = $riga->replicate();
$new_riga->setDocument($intervento);
$new_riga->qta_evasa = 0;
$new_riga->save();
if ($new_riga->isArticolo()) {
$new_riga->movimenta($new_riga->qta);
}
$new_riga->save();
$riga = null;
}
@ -976,11 +981,12 @@ switch (post('op')) {
$new_riga->setDocument($new);
$new_riga->qta_evasa = 0;
$new_riga->save();
if ($new_riga->isArticolo()) {
$new_riga->movimenta($new_riga->qta);
}
$new_riga->save();
}
}
@ -1153,6 +1159,7 @@ switch (post('op')) {
break;
case 'update_inline':
$qta = post('qta');
$id_riga = post('riga_id');
$riga = $riga ?: Riga::find($id_riga);
$riga = $riga ?: Articolo::find($id_riga);
@ -1162,7 +1169,7 @@ switch (post('op')) {
if ($riga->isSconto()) {
$riga->setScontoUnitario(post('sconto'), $riga->idiva);
} else {
$riga->qta = post('qta');
$riga->qta = $qta;
$riga->setPrezzoUnitario(post('prezzo'), $riga->idiva);
$riga->setSconto(post('sconto'), post('tipo_sconto'));
$riga->costo_unitario = post('costo') ?: 0;

View File

@ -107,7 +107,7 @@ class CSV extends CSVImporter
$impianto = Impianto::where('matricola', $record['impianto'])->first();
}
if (!empty($anagrafica) && !empty($impianto)) {
if (!empty($anagrafica)) {
$intervento = null;
// Ricerca sulla base della chiave primaria se presente
@ -128,6 +128,10 @@ class CSV extends CSVImporter
} else {
$stato = Stato::where('descrizione', $record['stato'])->first();
}
if (empty($stato)) {
$stato = Stato::build($record['stato']);
}
unset($record['stato']);
// Crea l'intervento
@ -139,13 +143,15 @@ class CSV extends CSVImporter
unset($record['ora_inizio']);
unset($record['telefono']);
$collegamento = $database->table('my_impianti_interventi')->where('idimpianto', $impianto['id'])->where('idintervento', $intervento['id'])->first();
if (!empty($impianto)) {
$collegamento = $database->table('my_impianti_interventi')->where('idimpianto', $impianto['id'])->where('idintervento', $intervento['id'])->first();
if (empty($collegamento)) {
// Collega l'impianto all'intervento
$database->query('INSERT INTO my_impianti_interventi(idimpianto, idintervento) VALUES('.prepare($impianto['id']).', '.prepare($intervento['id']).')');
if (empty($collegamento)) {
// Collega l'impianto all'intervento
$database->query('INSERT INTO my_impianti_interventi(idimpianto, idintervento) VALUES('.prepare($impianto['id']).', '.prepare($intervento['id']).')');
}
unset($record['impianto']);
}
unset($record['impianto']);
// Inserisce la data richiesta e la richiesta
$intervento->data_richiesta = $record['data_richiesta'];
@ -185,9 +191,9 @@ class CSV extends CSVImporter
public static function getExample()
{
return [
['Codice', 'Telefono', 'Data', 'Data richiesta', 'Ora', 'Tecnico', 'Tipo', 'Note', 'Impianto', 'Richiesta', 'Descrizione', 'Stato'],
['001', '044444444', '07/11/2023', '03/11/2023', '18:30', 'Stefano Bianchi', '', '', '00000000001', 'Manutenzione ordinaria', 'eseguito intervento di manutenzione', 'Bozza'],
['002', '044444444', '08/11/2023', '04/11/2023', '11:20', 'Stefano Bianchi', '', '', '00000000002', 'Manutenzione ordinaria', 'eseguito intervento di manutenzione', ''],
['Codice', 'Telefono', 'Data', 'Data richiesta', 'Ora inizio', 'Tecnico', 'Tipo', 'Note', 'Impianto', 'Richiesta', 'Descrizione', 'Stato'],
['001', '04444444', '07/11/2023', '03/11/2023', '18:30', 'Stefano Bianchi', '', '', '00001', 'Manutenzione ordinaria', 'eseguito intervento di manutenzione', 'Bozza'],
['002', '04444444', '08/11/2023', '04/11/2023', '11:20', 'Stefano Bianchi', '', '', '00002', 'Manutenzione ordinaria', 'eseguito intervento di manutenzione', ''],
];
}
}

View File

@ -33,4 +33,15 @@ class Stato extends Model
{
return $this->hasMany(Intervento::class, 'idstatointervento');
}
public static function build($nome)
{
$model = new static();
$model->codice = 'NEW';
$model->descrizione = $nome;
$model->save();
return $model;
}
}

View File

@ -342,7 +342,11 @@ switch (post('op')) {
ricalcola_costiagg_ordine($id_record);
flash()->info(tr('Righe eliminate!'));
if (count($id_righe) == 1) {
flash()->info(tr('Riga eliminata!'));
} else {
flash()->info(tr('Righe eliminate!'));
}
break;

View File

@ -231,7 +231,7 @@ $operations['cambia_stato'] = [
'data' => [
'title' => tr('Vuoi davvero cambiare lo stato per questi ordini?'),
'msg' => tr('Seleziona lo stato in cui spostare tutti gli ordini').'.<br>
<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione FROM or_statiordine" ]}',
<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione, colore as _bgcolor_ FROM or_statiordine" ]}',
'button' => tr('Procedi'),
'class' => 'btn btn-lg btn-warning',
'blank' => false,

View File

@ -349,7 +349,11 @@ switch (post('op')) {
$riga = null;
}
flash()->info(tr('Righe eliminate!'));
if (count($id_righe) == 1) {
flash()->info(tr('Riga eliminata!'));
} else {
flash()->info(tr('Righe eliminate!'));
}
break;

View File

@ -167,7 +167,7 @@ $operations['cambia_stato'] = [
'text' => '<span><i class="fa fa-refresh"></i> '.tr('Cambia stato'),
'data' => [
'title' => tr('Vuoi davvero aggiornare lo stato di questi preventivi?'),
'msg' => '<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione FROM co_statipreventivi ORDER BY descrizione" ]}',
'msg' => '<br>{[ "type": "select", "label": "'.tr('Stato').'", "name": "id_stato", "required": 1, "values": "query=SELECT id, descrizione, colore as _bgcolor_ FROM co_statipreventivi ORDER BY descrizione" ]}',
'button' => tr('Procedi'),
'class' => 'btn btn-lg btn-warning',
'blank' => false,

View File

@ -175,10 +175,12 @@ foreach ($righe as $key => $riga) {
$evasione_bar['or_righe_ordini'] = 'success';
foreach ($evasione_bar as $table => $color) {
$righe_ev = $dbo->table($table)->where('original_id', $riga->id)->where('original_type', get_class($riga))->get();
$perc_ev = $righe_ev->sum('qta') * 100 / $riga->qta;
if ($perc_ev > 0) {
echo '
<div class="progress-bar progress-bar-'.$color.'" style="width:'.$perc_ev.'%"></div>';
if ($righe_ev->count() > 0) {
$perc_ev = $righe_ev->sum('qta') * 100 / $riga->qta;
if ($perc_ev > 0) {
echo '
<div class="progress-bar progress-bar-'.$color.'" style="width:'.$perc_ev.'%"></div>';
}
}
}
echo '

View File

@ -209,7 +209,7 @@ if (!empty($clienti)) {
<td>'.Modules::link('Anagrafiche', $cliente['idanagrafica'], $cliente['ragione_sociale']).'</td>
<td class="text-right">'.intval($cliente['qta']).'</td>
<td class="text-right">'.moneyFormat($cliente['totale'], 2).'</td>
<td class="text-right">'.Translator::numberToLocale($cliente['totale'] * 100 / $totale[0]['totale'], 2).' %</td>
<td class="text-right">'.Translator::numberToLocale($cliente['totale'] * 100 / ($totale[0]['totale'] != 0 ? $totale[0]['totale'] : 1), 2).' %</td>
</tr>';
}
echo '
@ -256,7 +256,7 @@ if (!empty($articoli)) {
<tr>
<td><div class="shorten"> '.Modules::link('Articoli', $articolo['id'], $articolo['codice'].' - '.$articolo['descrizione']).'</div></td>
<td class="text-right">'.Translator::numberToLocale($articolo['qta'], 'qta').' '.$articolo['um'].'</td>
<td class="text-right">'.Translator::numberToLocale($articolo['qta'] * 100 / $totale[0]['totale_qta'], 2).' %</td>
<td class="text-right">'.Translator::numberToLocale($articolo['qta'] * 100 / ($totale[0]['totale_qta'] != 0 ? $totale[0]['totale_qta'] : 1), 2).' %</td>
<td class="text-right">'.moneyFormat($articolo['totale'], 2).'</td>
</tr>';
}

View File

@ -23,6 +23,7 @@ use FluidXml\FluidXml;
use GuzzleHttp\Client;
use Modules;
use Modules\Anagrafiche\Anagrafica;
use Modules\Anagrafiche\Sede;
use Modules\Banche\Banca;
use Modules\Fatture\Fattura;
use Modules\Fatture\Gestori\Bollo;
@ -829,6 +830,24 @@ class FatturaElettronica
return $result;
}
/**
* Restituisce l'array responsabile per la generazione del tag RappresentanteFiscale (1.3).
*
* @return array
*/
protected static function getRappresentanteFiscale($fattura)
{
//Fattura per conto terzi, il cliente diventa il cedente al posto della mia Azienda (fornitore)
$cliente = $fattura->getCliente();
$azienda = Sede::where('idanagrafica', $cliente->id)->where('is_rappresentante_fiscale', 1)->selectRaw('*, nomesede AS ragione_sociale')->first();
$result = [
'DatiAnagrafici' => static::getDatiAnagrafici($azienda, true),
];
return $result;
}
/**
* Restituisce l'array responsabile per la generazione del tag CessionarioCommittente (Cliente) (1.4).
*
@ -1757,11 +1776,31 @@ class FatturaElettronica
*/
protected static function getHeader($fattura)
{
$result = [
'DatiTrasmissione' => static::getDatiTrasmissione($fattura),
'CedentePrestatore' => static::getCedentePrestatore($fattura),
'CessionarioCommittente' => static::getCessionarioCommittente($fattura),
];
$documento = $fattura->getDocumento();
$rappresentante_fiscale = null;
//Fattura per conto terzi, il cliente diventa il cedente al posto della mia Azienda (fornitore)
if ($documento['is_fattura_conto_terzi']) {
$azienda = $fattura->getCliente();
$rappresentante_fiscale = Sede::where('idanagrafica', $azienda->id)->where('is_rappresentante_fiscale', 1)->first();
} else {
$azienda = static::getAzienda();
}
if ($rappresentante_fiscale) {
$result = [
'DatiTrasmissione' => static::getDatiTrasmissione($fattura),
'CedentePrestatore' => static::getCedentePrestatore($fattura),
'RappresentanteFiscale' => static::getRappresentanteFiscale($fattura),
'CessionarioCommittente' => static::getCessionarioCommittente($fattura),
];
} else {
$result = [
'DatiTrasmissione' => static::getDatiTrasmissione($fattura),
'CedentePrestatore' => static::getCedentePrestatore($fattura),
'CessionarioCommittente' => static::getCessionarioCommittente($fattura),
];
}
// 1.5 Terzo Intermediario
if (!empty(setting('Terzo intermediario'))) {

View File

@ -404,7 +404,7 @@ class FatturaOrdinaria extends FatturaElettronica
$diff = round(abs($totale_righe) + $totale_arrotondamento - abs($fattura->totale_imponibile), 2);
// Aggiunta della riga di arrotondamento nel caso in cui ci sia una differenza tra i totali, o tra l'imponibile dell'XML e quello ricavato dalla somma delle righe
if (($diff != 0 && $diff != $totale_arrotondamento) || (($fattura->totale_imponibile + $fattura->rivalsa_inps) != $totale_imp)) {
if (($diff != 0 && $diff != $totale_arrotondamento) || (($fattura->totale_imponibile + $fattura->rivalsa_inps) != abs($totale_imp))) {
// Rimozione dell'IVA calcolata automaticamente dal gestionale
$iva_arrotondamento = database()->fetchOne('SELECT * FROM co_iva WHERE percentuale=0 AND deleted_at IS NULL');
if ($diff != 0) {

View File

@ -19,75 +19,84 @@
include_once __DIR__.'/../../core.php';
use Modules\Anagrafiche\Sede;
$operazione = filter('op');
switch ($operazione) {
case 'addsede':
if (!empty(post('nomesede'))) {
$opt_out_newsletter = post('disable_newsletter');
$dbo->insert('an_sedi', [
if (!empty(post('nomesede'))) {
$opt_out_newsletter = post('disable_newsletter');
$dbo->insert('an_sedi', [
'idanagrafica' => $id_parent,
'nomesede' => post('nomesede'),
'indirizzo' => post('indirizzo'),
'codice_destinatario' => post('codice_destinatario'),
'citta' => post('citta'),
'cap' => post('cap'),
'provincia' => strtoupper(post('provincia')),
'km' => post('km'),
'id_nazione' => !empty(post('id_nazione')) ? post('id_nazione') : null,
'idzona' => !empty(post('idzona')) ? post('idzona') : 0,
'cellulare' => post('cellulare'),
'telefono' => post('telefono'),
'email' => post('email'),
'id_nazione' => !empty(post('id_nazione')) ? post('id_nazione') : null,
'idzona' => !empty(post('idzona')) ? post('idzona') : 0,
'enable_newsletter' => empty($opt_out_newsletter),
'codice_destinatario' => post('codice_destinatario'),
'is_automezzo' => post('is_automezzo'),
'is_rappresentante_fiscale' => post('is_rappresentante_fiscale'),
]);
$id_record = $dbo->lastInsertedID();
$id_referenti = (array) post('id_referenti');
foreach ($id_referenti as $id_referente) {
$dbo->update('an_referenti', [
'idsede' => $id_record,
], [
'id' => $id_referente,
]);
}
$id_record = $dbo->lastInsertedID();
if (isAjaxRequest() && !empty($id_record)) {
echo json_encode(['id' => $id_record, 'text' => post('nomesede').' - '.post('citta')]);
}
$id_referenti = (array) post('id_referenti');
foreach ($id_referenti as $id_referente) {
$dbo->update('an_referenti', [
'idsede' => $id_record,
], [
'id' => $id_referente,
]);
}
flash()->info(tr('Aggiunta una nuova sede!'));
} else {
flash()->warning(tr('Errore durante aggiunta della sede'));
}
if (isAjaxRequest() && !empty($id_record)) {
echo json_encode(['id' => $id_record, 'text' => post('nomesede').' - '.post('citta')]);
}
flash()->info(tr('Aggiunta una nuova sede!'));
} else {
flash()->warning(tr('Errore durante aggiunta della sede'));
}
$sede = Sede::find($id_record);
$sede->save();
break;
case 'updatesede':
$opt_out_newsletter = post('disable_newsletter');
$sede = Sede::find($id_record);
$dbo->update('an_sedi', [
'nomesede' => post('nomesede'),
'indirizzo' => post('indirizzo'),
'codice_destinatario' => post('codice_destinatario'),
'piva' => post('piva'),
'codice_fiscale' => post('codice_fiscale'),
'citta' => post('citta'),
'cap' => post('cap'),
'provincia' => strtoupper(post('provincia')),
'km' => post('km'),
'cellulare' => post('cellulare'),
'telefono' => post('telefono'),
'email' => post('email'),
'fax' => post('fax'),
'id_nazione' => !empty(post('id_nazione')) ? post('id_nazione') : null,
'telefono' => post('telefono'),
'cellulare' => post('cellulare'),
'email' => post('email'),
'enable_newsletter' => empty($opt_out_newsletter),
'codice_destinatario' => post('codice_destinatario'),
'is_rappresentante_fiscale' => post('is_rappresentante_fiscale'),
'piva' => post('piva'),
'codice_fiscale' => post('codice_fiscale'),
'is_automezzo' => post('is_automezzo'),
'idzona' => post('idzona'),
'km' => post('km'),
'note' => post('note'),
'gaddress' => post('gaddress'),
'lat' => post('lat'),
'lng' => post('lng'),
'enable_newsletter' => empty($opt_out_newsletter),
], ['id' => $id_record]);
$referenti = $dbo->fetchArray('SELECT id FROM an_referenti WHERE idsede = '.$id_record);
@ -110,6 +119,8 @@ switch ($operazione) {
]);
}
$sede->save();
flash()->info(tr('Salvataggio completato!'));
break;

View File

@ -42,18 +42,11 @@ echo '
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Indirizzo').'", "name": "indirizzo", "required": 0 ]}
</div>
<div class="col-md-6">
{[ "type": "text", "label": "'.($record['tipo_anagrafica'] == 'Ente pubblico' ? tr('Codice unico ufficio') : tr('Codice destinatario')).'", "name": "codice_destinatario", "required": 0, "class": "text-center text-uppercase alphanumeric-mask", "value": "$codice_destinatario$", "maxlength": '.($record['tipo_anagrafica'] == 'Ente pubblico' ? '6' : '7').', "help": "'.tr('<b>Attenzione</b>: per impostare il codice specificare prima \'Tipologia\' e \'Nazione\' dell\'anagrafica:<br><ul><li>Ente pubblico (B2G/PA) - Codice Univoco Ufficio (www.indicepa.gov.it), 6 caratteri</li><li>Azienda (B2B) - Codice Destinatario, 7 caratteri</li><li>Privato (B2C) - viene utilizzato il Codice Fiscale</li></ul>').'", "readonly": "'.intval($record['iso2'] ? $record['iso2'] != 'IT' : 0).'" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Città').'", "name": "citta", "required": 1 ]}
</div>
</div>
<div class="row">
<div class="col-md-2">
{[ "type": "text", "label": "'.tr('C.A.P.').'", "name": "cap" ]}
</div>
@ -65,37 +58,41 @@ echo '
<div class="col-md-2">
{[ "type": "text", "label": "'.tr('Km').'", "name": "km" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Nazione').'", "name": "id_nazione", "ajax-source": "nazioni", "required": 1 ]}
</div>
<div class="col-md-6">
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Zona').'", "name": "idzona", "ajax-source": "zone", "placeholder": "'.tr('Nessuna zona').'", "icon-after": "add|'.Modules::get('Zone')['id'].'" ]}
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="col-md-3">
{[ "type": "telefono", "label": "'.tr('Cellulare').'", "name": "cellulare" ]}
</div>
<div class="col-md-4">
<div class="col-md-3">
{[ "type": "telefono", "label": "'.tr('Telefono').'", "name": "telefono" ]}
</div>
<div class="col-md-4">
<div class="col-md-3">
{[ "type": "text", "label": "'.tr('Indirizzo email').'", "name": "email", "class": "email-mask", "validation": "email" ]}
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="col-md-3">
{[ "type": "checkbox", "label": "'.tr('Opt-out per newsletter').'", "name": "disable_newsletter", "id": "disable_newsletter_m", "value": "0", "help": "'.tr("Blocco per l'invio delle email.").'" ]}
</div>
</div>
<div class="row">
<div class="col-md-4">
{[ "type": "text", "label": "'.($record['tipo_anagrafica'] == 'Ente pubblico' ? tr('Codice unico ufficio') : tr('Codice destinatario')).'", "name": "codice_destinatario", "required": 0, "class": "text-center text-uppercase alphanumeric-mask", "value": "$codice_destinatario$", "maxlength": '.($record['tipo_anagrafica'] == 'Ente pubblico' ? '6' : '7').', "help": "'.tr('<b>Attenzione</b>: per impostare il codice specificare prima \'Tipologia\' e \'Nazione\' dell\'anagrafica:<br><ul><li>Ente pubblico (B2G/PA) - Codice Univoco Ufficio (www.indicepa.gov.it), 6 caratteri</li><li>Azienda (B2B) - Codice Destinatario, 7 caratteri</li><li>Privato (B2C) - viene utilizzato il Codice Fiscale</li></ul>').'", "readonly": "'.intval($record['iso2'] ? $record['iso2'] != 'IT' : 0).'" ]}
</div>
<div class="col-md-4">
{[ "type": "checkbox", "label": "'.tr('Automezzo').'", "name": "is_automezzo", "id": "is_automezzo", "value": "0", "help": "'.tr('Seleziona se questa sede rappresenta un automezzo.').'" ]}
</div>
<div class="col-md-4">
{[ "type": "checkbox", "label": "'.tr('Rappresentante fiscale').'", "name": "is_rappresentante_fiscale", "value": "'.($record['is_rappresentante_fiscale']).'", "help": "'.tr("Utilizza questa sede come rappresentante fiscale per l'anagrafica.").'" ]}
</div>
</div>
<div class="row">
<div class="col-md-12">
{[ "type": "select", "multiple": "1", "label": "'.tr('Referenti').'", "name": "id_referenti[]", "ajax-source": "referenti", "select-options": {"idanagrafica": '.$id_parent.'}, "icon-after": "add|'.Modules::get('Anagrafiche')['id'].'|id_plugin='.Plugins::get('Referenti')['id'].'&id_parent='.$id_parent.'" ]}

View File

@ -40,72 +40,70 @@ echo '
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Indirizzo').'", "name": "indirizzo", "id": "indirizzo_", "required": 0, "value": "$indirizzo$" ]}
</div>
<div class="col-md-6">
{[ "type": "text", "label": "'.($record['tipo_anagrafica'] == 'Ente pubblico' ? tr('Codice unico ufficio') : tr('Codice destinatario')).'", "name": "codice_destinatario", "required": 0, "class": "text-center text-uppercase alphanumeric-mask", "value": "$codice_destinatario$", "maxlength": '.($record['tipo_anagrafica'] == 'Ente pubblico' ? '6' : '7').', "help": "'.tr('<b>Attenzione</b>: per impostare il codice specificare prima \'Tipologia\' e \'Nazione\' dell\'anagrafica:<br><ul><li>Ente pubblico (B2G/PA) - Codice Univoco Ufficio (www.indicepa.gov.it), 6 caratteri</li><li>Azienda (B2B) - Codice Destinatario, 7 caratteri</li><li>Privato (B2C) - viene utilizzato il Codice Fiscale</li></ul>').'", "readonly": "'.intval($record['iso2'] ? $record['iso2'] != 'IT' : 0).'" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Città').'", "name": "citta", "id": "citta_", "value": "$citta$", "required": 1 ]}
</div>
</div>
<div class="col-md-2">
{[ "type": "text", "label": "'.tr('C.A.P.').'", "name": "cap", "value": "$cap$" ]}
<div class="row">
<div class="col-md-4">
{[ "type": "text", "label": "'.tr('C.A.P.').'", "name": "cap", "value": "$cap$", "required":1 ]}
</div>
<div class="col-md-2">
<div class="col-md-4">
{[ "type": "text", "label": "'.tr('Provincia').'", "name": "provincia", "value": "$provincia$", "maxlength": 2, "class": "text-center provincia-mask text-uppercase", "extra": "onkeyup=\"this.value = this.value.toUpperCase();\"" ]}
</div>
<div class="col-md-2">
{[ "type": "number", "label": "'.tr('Km').'", "name": "km", "value": "$km$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="col-md-4">
{[ "type": "select", "label": "'.tr('Nazione').'", "name": "id_nazione", "value": "$id_nazione$", "ajax-source": "nazioni", "required": 1 ]}
</div>
<div class="col-md-6">
</div>
<div class="row">
<div class="col-md-3">
{[ "type": "telefono", "label": "'.tr('Telefono').'", "name": "telefono", "value": "$telefono$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Fax').'", "name": "fax", "value": "$fax$" ]}
</div>
<div class="col-md-6">
<div class="col-md-3">
{[ "type": "telefono", "label": "'.tr('Cellulare').'", "name": "cellulare", "value": "$cellulare$" ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="col-md-3">
{[ "type": "text", "label": "'.tr('Indirizzo email').'", "name": "email", "value": "$email$", "class": "email-mask", "validation": "email" ]}
</div>
<div class="col-md-3">
{[ "type": "checkbox", "label": "'.tr('Opt-out per newsletter').'", "name": "disable_newsletter", "id": "disable_newsletter_m", "value": "'.empty($record['enable_newsletter']).'", "help": "'.tr("Blocco per l'invio delle email.").'" ]}
</div>
</div>
<div class="row">
<div class="col-md-3">
{[ "type": "text", "label": "'.($record['tipo_anagrafica'] == 'Ente pubblico' ? tr('Codice unico ufficio') : tr('Codice destinatario')).'", "name": "codice_destinatario", "required": 0, "class": "text-center text-uppercase alphanumeric-mask", "value": "$codice_destinatario$", "maxlength": '.($record['tipo_anagrafica'] == 'Ente pubblico' ? '6' : '7').', "help": "'.tr('<b>Attenzione</b>: per impostare il codice specificare prima \'Tipologia\' e \'Nazione\' dell\'anagrafica:<br><ul><li>Ente pubblico (B2G/PA) - Codice Univoco Ufficio (www.indicepa.gov.it), 6 caratteri</li><li>Azienda (B2B) - Codice Destinatario, 7 caratteri</li><li>Privato (B2C) - viene utilizzato il Codice Fiscale</li></ul>').'", "readonly": "'.intval($record['iso2'] ? $record['iso2'] != 'IT' : 0).'" ]}
</div>
<div class="col-md-3">
{[ "type": "checkbox", "label": "'.tr('Rappresentante fiscale').'", "name": "is_rappresentante_fiscale", "value": "'.($record['is_rappresentante_fiscale']).'", "help": "'.tr("Utilizza questa sede come rappresentante fiscale per l'anagrafica.").'" ]}
</div>
<div class="col-md-3">
{[ "type": "text", "label": "'.tr('Partita IVA').'", "name": "piva", "value": "'.($record['piva']).'", "help": "'.tr('Partita IVA del rappresentante fiscale.').'", "disabled":"disabled"]}
</div>
<div class="col-md-3">
{[ "type": "text", "label": "'.tr('Codice fiscale').'", "name": "codice_fiscale", "value": "'.($record['codice_fiscale']).'", "help": "'.tr('Codice fiscale del rappresentante fiscale.').'", "disabled":"disabled" ]}
</div>
</div>
<div class="row">
<div class="col-md-4">
{[ "type": "checkbox", "label": "'.tr('Automezzo').'", "name": "is_automezzo", "id": "is_automezzo", "value": "'.$record['is_automezzo'].'", "help": "'.tr('Seleziona se questa sede rappresenta un automezzo.').'" ]}
</div>
<div class="col-md-4">
{[ "type": "select", "label": "'.tr('Zona').'", "name": "idzona", "ajax-source": "zone", "value": "$idzona$", "placeholder": "'.tr('Nessuna zona').'", "icon-after": "add|'.Modules::get('Zone')['id'].'" ]}
</div>
</div>
<div class="row">
<div class="col-md-12">
{[ "type": "select", "multiple": "1", "label": "'.tr('Referenti').'", "name": "id_referenti[]", "value": "'.$referenti.'", "ajax-source": "referenti", "select-options": {"idanagrafica": '.$id_parent.'}, "icon-after": "add|'.Modules::get('Anagrafiche')['id'].'|id_plugin='.Plugins::get('Referenti')['id'].'&id_parent='.$id_parent.'" ]}
<div class="col-md-4">
{[ "type": "number", "label": "'.tr('Km').'", "name": "km", "value": "$km$" ]}
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="col-md-6">
{[ "type": "select", "multiple": "1", "label": "'.tr('Referenti').'", "name": "id_referenti[]", "value": "'.$referenti.'", "ajax-source": "referenti", "select-options": {"idanagrafica": '.$id_parent.'}, "icon-after": "add|'.Modules::get('Anagrafiche')['id'].'|id_plugin='.Plugins::get('Referenti')['id'].'&id_parent='.$id_parent.'" ]}
</div>
<div class="col-md-6">
{[ "type": "textarea", "label": "'.tr('Note').'", "name": "note", "value": "$note$" ]}
</div>
</div>
@ -210,6 +208,29 @@ echo '
<script>$(document).ready(init)</script>
<script>
function rappresentante_fiscale() {
let rappresentante_fiscale = input("is_rappresentante_fiscale");
let piva = input("piva");
let codice_fiscale = input("codice_fiscale");
if(rappresentante_fiscale.get()==1){
input("piva").enable();
input("codice_fiscale").enable();
} else {
input("piva").disable();
input("codice_fiscale").disable();
}
}
$(document).ready(function() {
rappresentante_fiscale();
});
input("is_rappresentante_fiscale").change(function () {
rappresentante_fiscale();
});
$("#modals > div").on("shown.bs.modal", function () {
if (input("lat").get() && input("lng").get()) {
caricaMappaSede();
@ -284,5 +305,4 @@ function rimuoviSede(button) {
});
}).catch(swal.noop);
}
</script>';

View File

@ -293,19 +293,48 @@ abstract class Article extends Accounting
$movimento = Movimento::descrizioneMovimento($qta_movimento, $documento->direzione).' - '.$documento->getReference();
if ($documento instanceof \Modules\Interventi\Intervento) {
$id_sede = $this->idsede_partenza;
$id_sede = $documento->idsede_partenza;
} else {
$id_sede = $documento->direzione == 'uscita' ? $documento->idsede_destinazione : $documento->idsede_partenza;
}
// Fix per valori di sede a NULL
$id_sede = $id_sede ?: 0;
$qta_finale = $qta_movimento;
$this->articolo->movimenta($qta_movimento, $movimento, $data, false, [
if (!setting('Permetti selezione articoli con quantità minore o uguale a zero in Documenti di Vendita') && $documento->direzione == 'entrata') {
$qta_sede = Movimento::where('idarticolo', $this->articolo->id)
->where('idsede', $id_sede)
->groupBy('idarticolo')
->sum('qta');
$qta_modifica = $this->attributes['qta']-$this->original['qta'];
//Se la quantità supera la giacenza in sede allora movimento solo quello che resta
if (($qta_sede + $qta_finale) < 0 && $qta_sede >= 0) {
$qta_finale = -$qta_sede;
$this->attributes['qta'] = $qta_sede + ($qta_modifica != 0 ? $this->original['qta'] : 0);
}
// Se la quantità sede per qualche motivo è negativa correggo la quantità della riga con la differenza
elseif ($qta_sede < 0 && $this->original['qta'] >= abs($qta_sede)) {
$qta_finale = abs($qta_sede);
$this->attributes['qta'] = $this->original['qta'] - abs($qta_sede);
}
// Se la quantità sede per qualche motivo è negativa e supera la quantità della riga azzero quest'ultima
elseif ($qta_sede < 0 && $this->original['qta'] < abs($qta_sede)) {
$qta_finale = $this->original['qta'];
$this->attributes['qta'] = 0;
}
}
$this->articolo->movimenta($qta_finale, $movimento, $data, false, [
'reference_type' => get_class($documento),
'reference_id' => $documento->id,
'idsede' => $id_sede,
]);
}
protected static function boot()

View File

@ -0,0 +1,93 @@
<?php
echo '
<br><br><span><big><b>CARICO SUGLI AUTOMEZZI IL '.date('d/m/Y', strtotime($dt_carico)).'</b></big></span><br>';
$targa = '';
$totale_qta = 0.000;
$totale_ven = 0.00;
for ($r = 0; $r < sizeof($rs); ++$r) {
if ($targa != $rs[$r]['targa']) {
if ($targa != '') {
echo "
<table cellspacing='0' style='table-layout:fixed;'>
<col width='35'><col width='275'><col width='50'><col width='70'><col width='45'><col width='65'><col width='65'>
<tr>
<td class='first_cell cell-padded'>".'&nbsp;'."</td>
<td class='table_cell cell-padded'>".'&nbsp;'."</td>
<td class='table_cell cell-padded'>".'&nbsp;'."</td>
<td class='table_cell text-right cell-padded'>".number_format($totale_qta, 3, ',', '.')."&nbsp;kg</td>
<td class='table_cell text-right cell-padded'>".'&nbsp;'."</td>
<td class='table_cell text-right cell-padded'>".number_format($totale_ven, 2, ',', '.')." &euro;</td>
<td class='table_cell cell-padded'>".'&nbsp;'.'</td>
</tr>
</table>';
}
echo "
<br/>
<table cellspacing='0' style='table-layout:fixed;'>
<col width='150'><col width='250'>
<tr>
<th bgcolor='#ffffff' class='full_cell1 cell-padded' width='150'>Targa: ".$rs[$r]['targa']."</th>
<th bgcolor='#ffffff' class='full_cell cell-padded' width='250'>Automezzo: ".$rs[$r]['nome'].'</th>
</tr>
</table>';
echo "
<table class='table table-bordered' cellspacing='0' style='table-layout:fixed;'>
<col width='35'><col width='275'><col width='50'><col width='70'><col width='45'><col width='65'><col width='65'>
<tr>
<th bgcolor='#dddddd' class='full_cell1 cell-padded' width='10%'>Codice</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' >Descrizione</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='20%'>Sub.Cat.</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='10%'>Quantit&agrave;</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='10%'>P. Ven.</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='10%'>Totale</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='10%'>Utente</th>
</tr>";
$targa = $rs[$r]['targa'];
$totale_qta = 0.000;
$totale_ven = 0.00;
}
echo '
<tr>';
$qta = number_format($rs[$r]['qta'], 3, ',', '.').'&nbsp;'.$rs[$r]['um'];
$prz_vendita = number_format($rs[$r]['prezzo_vendita'], 2);
$prz_vendita += ($prz_vendita / 100) * $rs[$r]['iva'];
$totv = number_format($prz_vendita, 2) * $rs[$r]['qta'];
echo "
<td class='first_cell cell-padded'>".$rs[$r]['codice']."</td>
<td class='table_cell cell-padded'>".$rs[$r]['descrizione']."</td>
<td class='table_cell cell-padded'>".$rs[$r]['subcategoria']."</td>
<td class='table_cell text-right cell-padded'>".$qta."</td>
<td class='table_cell text-right cell-padded'>".number_format($prz_vendita, 2, ',', '.')." &euro;</td>
<td class='table_cell text-right cell-padded'>".number_format($totv, 2, ',', '.')." &euro;</td>
<td class='table_cell cell-padded'>".ucfirst($rs[$r]['username']).'</td>
</tr>';
$totale_ven = $totale_ven + $totv;
if ($rs[$r]['um'] == 'kg') {
$totale_qta = $totale_qta + $rs[$r]['qta'];
}
}
echo '
</table>';
if ($targa != '') {
echo "
<table cellspacing='0' style='table-layout:fixed;'>
<tr>
<td class='first_cell cell-padded'>".'&nbsp;'."</td>
<td class='table_cell cell-padded'>".'&nbsp;'."</td>
<td class='table_cell cell-padded'>".'&nbsp;'."</td>
<td class='table_cell text-right cell-padded'>".number_format($totale_qta, 3, ',', '.')."&nbsp;kg</td>
<td class='table_cell text-right cell-padded'>".'&nbsp;'."</td>
<td class='table_cell text-right cell-padded'>".number_format($totale_ven, 2, ',', '.')." &euro;</td>
<td class='table_cell cell-padded'>".'&nbsp;'.'</td>
</tr>
</table>';
}

View File

@ -0,0 +1,39 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*
* Footer di default.
* I contenuti di questo file vengono utilizzati per generare il footer delle stampe nel caso non esista un file footer.php all'interno della stampa.
*
* Per modificare il footer della stampa basta aggiungere un file footer.php all'interno della cartella della stampa con i contenuti da mostrare (vedasi templates/fatture/footer.php).
*
* La personalizzazione specifica del footer deve comunque seguire lo standard della cartella custom: anche se il file footer.php non esiste nella stampa originaria, se si vuole personalizzare il footer bisogna crearlo all'interno della cartella custom.
*/
echo '
<table style="width:200mm; font-size:7pt; color:#999;">
<tr>
<td style="width:100mm; text-align:right;">
'.tr('Pagina _PAGE_ di _TOTAL_', [
'_PAGE_' => '{PAGENO}',
'_TOTAL_' => '{nb}',
]).'
</td>
</tr>
</table>';

View File

@ -0,0 +1,60 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
include_once __DIR__.'/../../core.php';
$search_targa = get('search_targa');
$search_nome = get('search_nome');
$dt_carico = get('data_carico');
$data_carico = strtotime(str_replace('/', '-', $dt_carico));
$startTM = date('Y-m-d', $data_carico).' 00:00:00';
$endTM = date('Y-m-d', $data_carico).' 23:59:59';
$query = "
SELECT
mg_movimenti.data,
an_sedi.targa,
an_sedi.nome,
mg_articoli.codice,
mg_articoli.prezzo_vendita,
co_iva.percentuale AS 'iva',
(SELECT mg_categorie.nome FROM mg_categorie WHERE mg_categorie.id=mg_articoli.id_sottocategoria) AS subcategoria,
(SELECT mg_articoli.descrizione FROM mg_articoli WHERE mg_articoli.id=mg_movimenti.idarticolo) AS 'descrizione',
IF( mg_movimenti.movimento LIKE '%Scarico%', mg_movimenti.qta*(-1), mg_movimenti.qta) AS qta,
mg_movimenti.idutente,
zz_users.username,
mg_articoli.um,
zz_groups.nome as 'gruppo'
FROM
mg_movimenti
INNER JOIN mg_articoli ON mg_movimenti.idarticolo=mg_articoli.id
INNER JOIN co_iva ON mg_articoli.idiva_vendita = co_iva.id
INNER JOIN zz_users ON mg_movimenti.idutente=zz_users.id
INNER JOIN zz_groups ON zz_users.idgruppo=zz_groups.id
INNER JOIN an_sedi ON mg_movimenti.idsede=an_sedi.id
WHERE
(mg_movimenti.idsede > 0) AND (mg_movimenti.idintervento IS NULL) AND
((mg_movimenti.data BETWEEN ".prepare($startTM).' AND '.prepare($endTM).") AND (zz_groups.nome IN ('Titolari', 'Amministratori')))";
$query .= ' AND (an_sedi.targa LIKE '.prepare('%'.$search_targa.'%').') AND (an_sedi.nome LIKE '.prepare('%'.$search_nome.'%').') ';
$query .= ' ORDER BY an_sedi.targa, mg_articoli.descrizione';
$rs = $dbo->fetchArray($query);
$totrows = sizeof($rs);
$azienda = $dbo->fetchOne('SELECT * FROM an_anagrafiche WHERE idanagrafica='.prepare(setting('Azienda predefinita')));

View File

@ -0,0 +1,51 @@
<?php
include_once __DIR__.'/../../core.php';
echo '<br>';
$targa = '';
for ($r = 0; $r < sizeof($rs); ++$r) {
if ($targa != $rs[$r]['targa']) {
if ($targa != '') {
echo '
</table>
<br/>';
}
echo "
<table cellspacing='0' style='table-layout:fixed;'>
<col width='150'><col width='250'>
<tr>
<th bgcolor='#ffffff' class='full_cell1 cell-padded' width='150'>Targa: ".$rs[$r]['targa']."</th>
<th bgcolor='#ffffff' class='full_cell cell-padded' width='250'>Automezzo: ".$rs[$r]['nome']."</th>
</tr>
</table>
<table class='table table-bordered' cellspacing='0' style='table-layout:fixed;'>
<col width='50'><col width='300'><col width='50'><col width='50'><col width='50'>
<tr>
<th bgcolor='#dddddd' class='full_cell1 cell-padded' width='10%'>Codice</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' >Descrizione</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='20%'>Sub.Cat.</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='15%'>Q.t&agrave;</th>
<th bgcolor='#dddddd' class='full_cell cell-padded' width='5%'></th>
</tr>";
$targa = $rs[$r]['targa'];
}
echo '
<tr>';
$qta = number_format($rs[$r]['qta'], 3, ',', '.').'&nbsp;'.$rs[$r]['um'];
echo "
<td class='first_cell cell-padded'>".$rs[$r]['codice']."</td>
<td class='table_cell cell-padded'>".$rs[$r]['descrizione']."</td>
<td class='table_cell cell-padded'>".$rs[$r]['subcategoria']."</td>
<td class='table_cell text-right cell-padded'>".$qta."</td>
<td class='table_cell cell-padded'></td>
</tr>";
}
if ($targa != '') {
echo '
</table>';
}

View File

@ -0,0 +1,39 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/*
* Footer di default.
* I contenuti di questo file vengono utilizzati per generare il footer delle stampe nel caso non esista un file footer.php all'interno della stampa.
*
* Per modificare il footer della stampa basta aggiungere un file footer.php all'interno della cartella della stampa con i contenuti da mostrare (vedasi templates/fatture/footer.php).
*
* La personalizzazione specifica del footer deve comunque seguire lo standard della cartella custom: anche se il file footer.php non esiste nella stampa originaria, se si vuole personalizzare il footer bisogna crearlo all'interno della cartella custom.
*/
echo '
<table style="width:200mm; font-size:7pt; color:#999;">
<tr>
<td style="width:100mm; text-align:right;">
'.tr('Pagina _PAGE_ di _TOTAL_', [
'_PAGE_' => '{PAGENO}',
'_TOTAL_' => '{nb}',
]).'
</td>
</tr>
</table>';

View File

@ -0,0 +1,54 @@
<?php
/*
* OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
* Copyright (C) DevCode s.r.l.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
include_once __DIR__.'/../../core.php';
$azienda = $dbo->fetchOne('SELECT * FROM an_anagrafiche WHERE idanagrafica='.prepare(setting('Azienda predefinita')));
$where = [];
$search_targa = get('search_targa');
$search_nome = get('search_nome');
$where[] = 'movimenti.qta > 0';
$where[] = 'movimenti.qta > 0';
if ($search_targa) {
$where[] = 'an_sedi.targa like '.prepare('%'.$search_targa.'%');
}
if ($search_nome) {
$where[] = 'an_sedi.nome like '.prepare('%'.$search_nome.'%');
}
//Ciclo tra gli articoli selezionati
$query = '
SELECT
an_sedi.targa, an_sedi.nome,
mg_articoli.codice, mg_articoli.descrizione,
(SELECT mg_categorie.nome FROM mg_categorie WHERE mg_categorie.id=mg_articoli.id_sottocategoria) AS subcategoria,
movimenti.qta,
mg_articoli.um
FROM an_sedi
INNER JOIN (SELECT SUM(mg_movimenti.qta) AS qta, idarticolo, idsede FROM mg_movimenti GROUP BY idsede,idarticolo) AS movimenti ON movimenti.idsede = an_sedi.id
INNER JOIN mg_articoli ON movimenti.idarticolo = mg_articoli.id
WHERE
'.implode(' AND ', $where).'
ORDER BY
an_sedi.targa, an_sedi.descrizione';
$rs = $dbo->fetchArray($query);
$totrows = sizeof($rs);

View File

@ -39,4 +39,55 @@ ALTER TABLE `zz_files` ADD INDEX(`id_record`);
ALTER TABLE `co_scadenziario` ADD `id_pagamento` INT NOT NULL;
ALTER TABLE `co_scadenziario` ADD `id_banca_azienda` INT NULL;
ALTER TABLE `co_scadenziario` ADD `id_banca_controparte` INT NULL;
ALTER TABLE `co_scadenziario` ADD `id_banca_controparte` INT NULL;
-- Aggiunta nuovi campi in sedi per gestione automezzi
ALTER TABLE `an_sedi`
ADD `nome` VARCHAR(225) NULL DEFAULT NULL ,
ADD `descrizione` VARCHAR(225) NULL DEFAULT NULL AFTER `nome` ,
ADD `targa` VARCHAR(225) NULL DEFAULT NULL AFTER `descrizione` ,
ADD `is_automezzo` TINYINT NOT NULL DEFAULT '0' AFTER `targa` ;
-- Creazione modulo Automezzi
INSERT INTO `zz_modules` (`id`, `name`, `title`, `directory`, `options`, `options2`, `icon`, `version`, `compatibility`, `order`, `parent`, `default`, `enabled`, `use_notes`, `use_checklists`) VALUES (NULL, 'Automezzi', 'Automezzi', 'automezzi', 'SELECT |select| FROM an_sedi INNER JOIN zz_settings ON (zz_settings.valore=an_sedi.idanagrafica AND zz_settings.nome=\'Azienda predefinita\' ) WHERE 1=1 AND an_sedi.is_automezzo=1 HAVING 2=2 ORDER BY nomesede ASC', '', 'fa fa-angle-right', '1.0', '2.4.16', '100', (SELECT `t`.`id` FROM `zz_modules` AS `t` WHERE `t`.`name` = 'Magazzino'), '0', '1', '0', '0');
--Viste modulo automezzi
INSERT INTO `zz_views` (`id_module`, `name`, `query`, `order`, `search`, `slow`, `format`, `search_inside`, `order_by`, `visible`, `summable`, `default`) VALUES
((SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), 'id', 'an_sedi.id', 0, 1, 0, 0, '', '', 0, 0, 0),
((SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), 'Targa', 'an_sedi.targa', 2, 1, 0, 0, '', '', 1, 0, 0),
((SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), 'Nome', 'an_sedi.nome', 3, 1, 0, 0, '', '', 1, 0, 0),
((SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), 'Descrizione', 'an_sedi.descrizione', 4, 1, 0, 0, '', '', 1, 0, 0);
-- Tabella per associazione automezzi-tecnici
CREATE TABLE `an_sedi_tecnici` (
`id` INT NOT NULL AUTO_INCREMENT ,
`idsede` INT NOT NULL ,
`idtecnico` INT NOT NULL ,
`data_inizio` DATE NULL DEFAULT NULL,
`data_fine` DATE NULL DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`updated_at` TIMESTAMP on UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY (`id`)) ENGINE = InnoDB;
-- Aggiunta indici
ALTER TABLE `an_sedi_tecnici`
ADD INDEX(`idsede`),
ADD INDEX(`idtecnico`);
ALTER TABLE `an_sedi_tecnici` ADD CONSTRAINT `an_sedi_tecnici_ibfk_1` FOREIGN KEY (`idsede`) REFERENCES `an_sedi`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `an_sedi_tecnici` ADD CONSTRAINT `an_sedi_tecnici_ibfk_2` FOREIGN KEY (`idtecnico`) REFERENCES `an_anagrafiche`(`idanagrafica`) ON DELETE CASCADE ON UPDATE NO ACTION;
-- Aggiunta stampe automezzi
INSERT INTO `zz_prints` (`id`, `id_module`, `is_record`, `name`, `title`, `filename`, `directory`, `previous`, `options`, `icon`, `version`, `compatibility`, `order`, `predefined`, `default`, `enabled`) VALUES
(NULL, (SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), '0', 'Giacenza automezzi', 'Giacenza automezzi', 'giacenza automezzo', 'automezzi_inventario', '', '', '', '', '', '1', '0', '0', '1'),
(NULL, (SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), '0', 'Giacenza odierna automezzi', 'Giacenza odierna automezzi', 'giacenza automezzo', 'automezzi_carico', '', '', '', '', '', '1', '0', '0', '1');
-- Widget modulo automezzi
INSERT INTO `zz_widgets` (`id`, `name`, `type`, `id_module`, `location`, `class`, `query`, `bgcolor`, `icon`, `print_link`, `more_link`, `more_link_type`, `php_include`, `text`, `enabled`, `order`, `help`) VALUES
(NULL, 'Stampa carico odierno', 'print', (SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), 'controller_top', 'col-md-4', '', '#37a02d', 'fa fa-print', '', 'var data_carico = prompt(\'Data del carico da stampare?\', moment(new Date()).format(\'DD/MM/YYYY\'));\r\nif ( data_carico != null){ \r\nwindow.open(\'pdfgen.php?id_print=54&search_targa=\'+$(\'#th_Targa input\').val()+\'&search_nome=\'+$(\'#th_Nome input\').val()+\'&data_carico=\'+data_carico); \r\n}', 'javascript', '', 'Stampa carico odierno', '1', '2', NULL),
(NULL, 'Stampa giacenza', 'print', (SELECT `id` FROM `zz_modules` WHERE name='Automezzi'), 'controller_top', 'col-md-4', '', '#45a9f1', 'fa fa-truck', '', 'if( confirm(\'Stampare la giacenza attuale sugli automezzi?\') ){ window.open(\'pdfgen.php?id_print=53&search_targa=\'+$(\'#th_Targa input\').val()+\'&search_nome=\'+$(\'#th_Nome input\').val()); }', 'javascript', '', 'Stampa giacenza', '1', '1', NULL);
-- Aggiunta flag rappresentante fiscale per sede
ALTER TABLE `an_sedi` ADD `is_rappresentante_fiscale` BOOLEAN NULL DEFAULT FALSE;