Gestione dinamica delle quantità per gli articoli

This commit is contained in:
Dasc3er 2020-08-27 09:15:30 +02:00
parent 97bd2d20a8
commit 3ca0b487a1
5 changed files with 209 additions and 72 deletions

View File

@ -28,7 +28,15 @@ if (empty($result['idarticolo'])) {
echo '
<p><strong>'.tr('Articolo').':</strong> '.$articolo['codice'].' - '.$articolo['descrizione'].'.</p>
<input type="hidden" name="idarticolo" id="idarticolo" value="'.$articolo['id'].'">';
<input type="hidden" name="idarticolo" id="idarticolo" value="'.$articolo['id'].'">
<script>
$(document).ready(function (){
ottieniPrezziArticolo("'.$articolo['id'].'").then(function (){
verificaPrezzoArticolo();
});
});
</script>';
}
echo '
@ -78,83 +86,161 @@ if ($module['name'] != 'Contratti' && $module['name'] != 'Preventivi') {
echo '
<script>
var direzione = "'.$options['dir'].'";
$(document).ready(function () {
$("#idarticolo").on("change", function() {
// Autoimpostazione dei valori relativi
if ($(this).val()) {
$data = $(this).selectData();
if (direzione === "uscita") {
aggiorna_qta_minima();
$("#qta").keyup(aggiorna_qta_minima);
}
});
$("#prezzo_unitario").val($data.prezzo_'.($options['dir'] == 'entrata' ? 'vendita' : 'acquisto').');
$("#costo_unitario").val($data.prezzo_acquisto);
$("#descrizione_riga").val($data.descrizione);';
if ($options['dir'] == 'entrata') {
echo '
if($data.idiva_vendita) {
$("#idiva").selectSetNew($data.idiva_vendita, $data.iva_vendita);
}';
} else {
echo '
$("#id_dettaglio_fornitore").val($data.id_dettaglio_fornitore);
$("#qta_minima").val($data.qta_minima);
aggiorna_qta_minima();';
}
echo '
var id_conto = $data.idconto_'.($options['dir'] == 'entrata' ? 'vendita' : 'acquisto').';
if(id_conto) {
$("#idconto").selectSetNew(id_conto, $data.idconto_'.($options['dir'] == 'entrata' ? 'vendita' : 'acquisto').'_title);
}
$("#um").selectSetNew($data.um, $data.um);
// Aggiornamento automatico di guadagno e margine
aggiorna_guadagno();
}';
if ($module['name'] != 'Contratti' && $module['name'] != 'Preventivi') {
echo '
// Operazioni sui prezzi in fondo alla pagina
$("#prezzi_articolo button").attr("disabled", !$(this).val());
$("#idarticolo").on("change", function() {
// Operazioni sui prezzi in fondo alla pagina
let prezzi_precedenti = $("#prezzi_articolo button");
if (prezzi_precedenti.length) {
prezzi_precedenti.attr("disabled", !$(this).val());
if ($(this).val()) {
$("#prezzi_articolo button").removeClass("disabled");
prezzi_precedenti.removeClass("disabled");
} else {
$("#prezzi_articolo button").addClass("disabled");
prezzi_precedenti.addClass("disabled");
}
$("#prezzi").html("");
$("#prezzivendita").html("");
$("#prezziacquisto").html("");';
}
$("#prezziacquisto").html("");
}
echo '
});';
if ($options['dir'] == 'uscita') {
echo '
aggiorna_qta_minima();
$("#qta").keyup(aggiorna_qta_minima);';
}
echo '
});';
if ($options['dir'] == 'uscita') {
echo '
// Funzione per l\'aggiornamento in tempo reale del guadagno
function aggiorna_qta_minima() {
var qta_minima = parseFloat($("#qta_minima").val());
var qta = $("#qta").val().toEnglish();
if (qta_minima == 0) {
if (!$(this).val()) {
return;
}
var parent = $("#qta").closest("div").parent();
var div = parent.find("div[id*=\"errors\"]");
// Autoimpostazione dei campi relativi all\'articolo
let $data = $(this).selectData();
ottieniPrezziArticolo($data.id).then(function() {
if ($("#prezzo_unitario").val().toEnglish() === 0){
aggiornaPrezzoArticolo();
} else {
verificaPrezzoArticolo();
}
})
$("#costo_unitario").val($data.prezzo_acquisto);
$("#descrizione_riga").val($data.descrizione);
if (direzione === "entrata") {
if($data.idiva_vendita) {
$("#idiva").selectSetNew($data.idiva_vendita, $data.iva_vendita);
}
}
else {
$("#id_dettaglio_fornitore").val($data.id_dettaglio_fornitore);
$("#qta_minima").val($data.qta_minima);
aggiorna_qta_minima();
}
let id_conto = $data.idconto_'.($options['dir'] == 'entrata' ? 'vendita' : 'acquisto').';
let id_conto_title = $data.idconto_'.($options['dir'] == 'entrata' ? 'vendita' : 'acquisto').'_title;
if(id_conto) {
$("#idconto").selectSetNew(id_conto, id_conto_title);
}
$("#um").selectSetNew($data.um, $data.um);
// Aggiornamento automatico di guadagno e margine
if (direzione === "entrata") {
aggiorna_guadagno();
}
});
$("#qta").on("change", function() {
verificaPrezzoArticolo();
});
/**
* Restituisce il prezzo registrato per una specifica quantità dell\'articolo.
*/
function getPrezzoPerQuantita(qta) {
const data = $("#prezzo_unitario").data("prezzi");
if (!data) return 0;
let prezzo_predefinito = null;
let prezzo_selezionato = null;
for (const prezzo of data) {
if (prezzo.minimo == null && prezzo.massimo == null) {
prezzo_predefinito = prezzo.prezzo_unitario;
continue;
}
if (qta >= prezzo.minimo && qta <= prezzo.massimo) {
prezzo_selezionato = prezzo.prezzo_unitario;
}
}
if (prezzo_selezionato == null) {
prezzo_selezionato = prezzo_predefinito;
}
return parseFloat(prezzo_selezionato);
}
/**
* Funzione per registrare localmente i prezzi definiti per l\'articolo in relazione ad una specifica anagrafica.
*/
function ottieniPrezziArticolo(id_articolo) {
return $.get(globals.rootdir + "/ajax_complete.php?module=Articoli&op=prezzi_articolo&id_anagrafica='.$options['idanagrafica'].'&id_articolo=" + id_articolo + "&dir=" + direzione, function(response) {
const data = JSON.parse(response);
$("#prezzo_unitario").data("prezzi", data);
});
}
/**
* Funzione per verificare se il prezzo unitario corrisponde a quello registrato per l\'articolo, e proporre in automatico una correzione.
*/
function verificaPrezzoArticolo() {
let qta = $("#qta").val().toEnglish();
let prezzo_previsto = getPrezzoPerQuantita(qta);
let prezzo_unitario_input = $("#prezzo_unitario");
let prezzo_unitario = prezzo_unitario_input.val().toEnglish();
let div = prezzo_unitario_input.closest("div").parent().find("div[id*=errors]");
if (prezzo_previsto === prezzo_unitario) {
div.css("padding-top", "0");
div.html("");
return;
}
div.css("padding-top", "5px");
div.html(`<small>'.tr('Prezzo registrato').': ` + prezzo_previsto.toLocale() + globals.currency + `<button type="button" class="btn btn-xs btn-info pull-right" onclick="aggiornaPrezzoArticolo()"><i class="fa fa-refresh"></i> '.tr('Aggiorna').'</button></small>`);
}
/**
* Funzione per aggiornare il prezzo unitario sulla base dei valori automatici.
*/
function aggiornaPrezzoArticolo() {
let qta = $("#qta").val().toEnglish();
let prezzo_previsto = getPrezzoPerQuantita(qta);
$("#prezzo_unitario").val(prezzo_previsto);
}
/**
* Funzione per l\'aggiornamento dinamico della quantità minima per l\'articolo.
*/
function aggiorna_qta_minima() {
let qta_minima = parseFloat($("#qta_minima").val());
let qta = $("#qta").val().toEnglish();
if (qta_minima === 0) {
return;
}
let parent = $("#qta").closest("div").parent();
let div = parent.find("div[id*=errors]");
div.html("<small>'.tr('Quantità minima').': " + qta_minima.toLocale() + "</small>");
if (qta < qta_minima) {
@ -164,7 +250,5 @@ function aggiorna_qta_minima() {
parent.removeClass("has-error");
div.removeClass("text-danger").addClass("text-success");
}
}';
}
echo '
</script>';

View File

@ -4,7 +4,7 @@ include_once __DIR__.'/../../../core.php';
switch ($resource) {
case 'clienti':
$query = "SELECT an_anagrafiche.idanagrafica AS id, CONCAT(ragione_sociale, IF(citta IS NULL OR citta = '', '', CONCAT(' (', citta, ')')), IF(deleted_at IS NULL, '', ' (".tr('eliminata').")')) AS descrizione, idtipointervento, in_tipiintervento.descrizione AS idtipointervento_descrizione, an_anagrafiche.idzona 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 LEFT JOIN in_tipiintervento ON an_anagrafiche.idtipointervento_default=in_tipiintervento.idtipointervento |where| ORDER BY ragione_sociale";
$query = "SELECT an_anagrafiche.idanagrafica AS id, CONCAT(ragione_sociale, IF(citta IS NULL OR citta = '', '', CONCAT(' (', citta, ')')), IF(deleted_at IS NULL, '', ' (".tr('eliminata').")')) AS descrizione, idtipointervento_default AS idtipointervento, in_tipiintervento.descrizione AS idtipointervento_descrizione, an_anagrafiche.idzona 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 LEFT JOIN in_tipiintervento ON an_anagrafiche.idtipointervento_default=in_tipiintervento.idtipointervento |where| ORDER BY ragione_sociale";
foreach ($elements as $element) {
$filter[] = 'an_anagrafiche.idanagrafica='.prepare($element);
@ -24,7 +24,7 @@ switch ($resource) {
break;
case 'fornitori':
$query = "SELECT an_anagrafiche.idanagrafica AS id, CONCAT(ragione_sociale, IF(citta IS NULL OR citta = '', '', CONCAT(' (', citta, ')')), IF(deleted_at IS NULL, '', ' (".tr('eliminata').")')) AS descrizione, idtipointervento 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| ORDER BY ragione_sociale";
$query = "SELECT an_anagrafiche.idanagrafica AS id, CONCAT(ragione_sociale, IF(citta IS NULL OR citta = '', '', CONCAT(' (', citta, ')')), IF(deleted_at IS NULL, '', ' (".tr('eliminata').")')) AS descrizione, idtipointervento_default AS idtipointervento 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| ORDER BY ragione_sociale";
foreach ($elements as $element) {
$filter[] = 'an_anagrafiche.idanagrafica='.prepare($element);
@ -44,7 +44,7 @@ switch ($resource) {
break;
case 'vettori':
$query = "SELECT an_anagrafiche.idanagrafica AS id, CONCAT(ragione_sociale, IF(citta IS NULL OR citta = '', '', CONCAT(' (', citta, ')')), IF(deleted_at IS NULL, '', ' (".tr('eliminata').")')) AS descrizione, idtipointervento 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| ORDER BY ragione_sociale";
$query = "SELECT an_anagrafiche.idanagrafica AS id, CONCAT(ragione_sociale, IF(citta IS NULL OR citta = '', '', CONCAT(' (', citta, ')')), IF(deleted_at IS NULL, '', ' (".tr('eliminata').")')) AS descrizione, idtipointervento_default AS idtipointervento 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| ORDER BY ragione_sociale";
foreach ($elements as $element) {
$filter[] = 'an_anagrafiche.idanagrafica='.prepare($element);

View File

@ -92,5 +92,58 @@ switch ($resource) {
echo '<br/>'.tr('Nessun acquisto trovato di questo articolo')."...<br/>\n";
}
break;
/*
* Opzioni utilizzate:
* - id_articolo
* - id_anagrafica
*/
case 'prezzi_articolo':
$id_articolo = get('id_articolo');
$id_anagrafica = get('id_anagrafica');
$direzione = get('dir') == 'uscita' ? 'uscita' : 'entrata';
if (empty($id_articolo) || empty($id_anagrafica)) {
return;
}
$prezzi_ivati = setting('Utilizza prezzi di vendita comprensivi di IVA');
$query = 'SELECT minimo, massimo,
'.($prezzi_ivati ? 'prezzo_unitario_ivato' : 'prezzo_unitario').' AS prezzo_unitario
FROM mg_prezzi_articoli
WHERE id_articolo = '.prepare($id_articolo).' AND dir = '.prepare($direzione).' |where|
ORDER BY minimo ASC, massimo DESC';
// Lettura dei prezzi relativi all'anagrafica
$query_anagrafica = replace($query, [
'|where|' => ' AND id_anagrafica = '.prepare($id_anagrafica),
]);
$results = $database->fetchArray($query_anagrafica);
// Lettura dei prezzi relativi all'articolo, senza anagrafica collegata
if (empty($results)) {
$query_predefinito = replace($query, [
'|where|' => '',
]);
$results = $database->fetchArray($query_predefinito);
}
// Lettura dei prezzi registrati direttamente sull'articolo, per compatibilità con il formato standard
if (empty($results)) {
$result = $database->fetchOne('SELECT prezzo_acquisto, '.($prezzi_ivati ? 'prezzo_vendita_ivato' : 'prezzo_vendita').' AS prezzo_vendita FROM mg_articoli WHERE id = '.prepare($id_articolo));
$results = [
[
'minimo' => null,
'massino' => null,
'prezzo_unitario' => $direzione == 'uscita' ? $result['prezzo_acquisto'] : $result['prezzo_vendita'],
],
];
}
echo json_encode($results);
break;
}

View File

@ -22,7 +22,7 @@ $id_anagrafica = filter('id_anagrafica');
</div>
<div class="col-md-4">
{[ "type": "select", "label": "<?php echo tr('Sede'); ?>", "name": "idsede", "value": "$idsede$", "ajax-source": "sedi", "select-options": <?php echo json_encode(["idanagrafica" => $id_anagrafica]); ?>, "placeholder": "Sede legale" ]}
{[ "type": "select", "label": "<?php echo tr('Sede'); ?>", "name": "idsede", "value": "$idsede$", "ajax-source": "sedi", "select-options": <?php echo json_encode(['idanagrafica' => $id_anagrafica]); ?>, "placeholder": "Sede legale" ]}
</div>
<div class="col-md-4">

View File

@ -64,7 +64,7 @@ if (!empty($record['immagine'])) {
<?php
echo '
<div class="col-md-4">
{[ "type": "select", "label": "'.tr('Sede').'", "name": "idsede", "value": "$idsede$", "required": "1", "ajax-source": "sedi", "select-options": '.json_encode(["idanagrafica" => $record['idanagrafica']]).', "placeholder": "'.tr('Sede legale').'" ]}
{[ "type": "select", "label": "'.tr('Sede').'", "name": "idsede", "value": "$idsede$", "required": "1", "ajax-source": "sedi", "select-options": '.json_encode(['idanagrafica' => $record['idanagrafica']]).', "placeholder": "'.tr('Sede legale').'" ]}
</div>';
?>
</div>