This commit is contained in:
MatteoPistorello 2021-07-20 14:55:22 +02:00
commit 47891b2854
10 changed files with 282 additions and 156 deletions

View File

@ -34,15 +34,21 @@ $final_module = Modules::get($name);
// IVA predefinita
$id_iva = $id_iva ?: setting('Iva predefinita');
$righe_totali = $documento->getRighe();
if ($final_module['name'] == 'Interventi') {
$righe = $documento->getRighe()->where('qta_rimanente', '>', 0)->where('is_descrizione', '=', 0);
$righe = $righe_totali->where('is_descrizione', '=', 0)
->where('qta_rimanente', '>', 0);
$righe_evase = $righe_totali->where('is_descrizione', '=', 0)
->where('qta_rimanente', '=', 0);
} elseif ($final_module['name'] == 'Ordini fornitore') {
$righe = $documento->getRighe();
$righe = $righe_totali;
$righe_evase = collect();
} else {
$righe = $documento->getRighe()->where('qta_rimanente', '>', 0);
$righe = $righe_totali->where('qta_rimanente', '>', 0);
$righe_evase = $righe_totali->where('qta_rimanente', '=', 0);
}
if (empty($righe)) {
if ($righe->isEmpty()) {
echo '
<p>'.tr('Non ci sono elementi da evadere').'...</p>';
@ -355,21 +361,56 @@ echo '
</table>
</div>';
echo '
<div class="alert alert-warning hidden" id="articoli_sottoscorta">
<table class="table table-condensed">
<thead>
<tr>
<th>'.tr('Articolo').'</th>
<th class="text-center tip" width="150" title="'.tr('Quantità richiesta').'">'.tr('Q.').'</th>
<th class="text-center tip" width="150" title="'.tr('Quantità disponibile nel magazzino del gestionale').'">'.tr('Q. magazzino').'</th>
<th class="text-center" width="150">'.tr('Scarto').'</th>
</tr>
</thead>
// Elenco righe evase completametne
if (!$righe_evase->isEmpty()) {
echo '
<div class="box box-info collapsable collapsed-box">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Righe evase completamente').'</h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i></button>
</div>
</div>
<tbody></tbody>
</table>
</div>';
<table class="box-body table table-striped table-hover table-condensed">
<thead>
<tr>
<th>'.tr('Descrizione').'</th>
<th width="10%" class="text-center">'.tr('Q.').'</th>
</tr>
</thead>
<tbody>';
foreach ($righe_evase as $riga) {
echo '
<tr>
<td>'.$riga->descrizione.'</td>
<td class="text-center">'.numberFormat($riga->qta, 'qta').' '.$riga->um.'</td>
</tr>';
}
echo '
</tbody>
</table>
</div>';
}
// Gestione articolo sottoscorta
echo '
<div class="alert alert-warning hidden" id="articoli_sottoscorta">
<table class="table table-condensed">
<thead>
<tr>
<th>'.tr('Articolo').'</th>
<th class="text-center tip" width="150" title="'.tr('Quantità richiesta').'">'.tr('Q.').'</th>
<th class="text-center tip" width="150" title="'.tr('Quantità disponibile nel magazzino del gestionale').'">'.tr('Q. magazzino').'</th>
<th class="text-center" width="150">'.tr('Scarto').'</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>';
echo '
@ -386,10 +427,7 @@ echo '
echo '
<script>$(document).ready(init)</script>';
echo '
<script type="text/javascript">
';
// Individuazione scorte
$articoli = $documento->articoli->groupBy('idarticolo');
$scorte = [];
foreach ($articoli as $elenco) {
@ -407,144 +445,144 @@ foreach ($articoli as $elenco) {
}
echo '
var scorte = '.json_encode($scorte).';
var abilita_scorte = '.intval(!$documento::$movimenta_magazzino && !empty($options['tipo_documento_finale']) && $options['tipo_documento_finale']::$movimenta_magazzino).';
<script type="text/javascript">
var scorte = '.json_encode($scorte).';
var permetti_documento_vuoto = '.intval(!empty($options['allow-empty'])).';
var abilita_scorte = '.intval(!$documento::$movimenta_magazzino && !empty($options['tipo_documento_finale']) && $options['tipo_documento_finale']::$movimenta_magazzino).';
function controllaMagazzino() {
if(!abilita_scorte) return;
function controllaMagazzino() {
if(!abilita_scorte) return;
let righe = $("#righe_documento_importato tr");
let righe = $("#righe_documento_importato tr");
// Lettura delle righe selezionate per l\'improtazione
let richieste = {};
for(const r of righe) {
let riga = $(r);
let id = $(riga).data("local_id");
let id_articolo = riga.find("[id^=id_articolo_]").text();
// Lettura delle righe selezionate per l\'improtazione
let richieste = {};
for(const r of righe) {
let riga = $(r);
let id = $(riga).data("local_id");
let id_articolo = riga.find("[id^=id_articolo_]").text();
if (!$("#checked_" + id).is(":checked") || !id_articolo) {
continue;
if (!$("#checked_" + id).is(":checked") || !id_articolo) {
continue;
}
let qta = parseFloat(riga.find("input[id^=qta_]").val());
richieste[id_articolo] = richieste[id_articolo] ? richieste[id_articolo] + qta : qta;
}
let qta = parseFloat(riga.find("input[id^=qta_]").val());
richieste[id_articolo] = richieste[id_articolo] ? richieste[id_articolo] + qta : qta;
}
let sottoscorta = $("#articoli_sottoscorta");
let body = sottoscorta.find("tbody");
body.html("");
let sottoscorta = $("#articoli_sottoscorta");
let body = sottoscorta.find("tbody");
body.html("");
for(const id_articolo in richieste) {
let qta_scorta = parseFloat(scorte[id_articolo]["qta"]);
let qta_richiesta = parseFloat(richieste[id_articolo]);
if ((qta_richiesta > qta_scorta) && (scorte[id_articolo]["servizio"] !== 1)) {
body.append(`<tr>
<td>` + scorte[id_articolo]["descrizione"] + `</td>
<td class="text-right">` + qta_richiesta.toLocale() + `</td>
<td class="text-right">` + qta_scorta.toLocale() + `</td>
<td class="text-right">` + (qta_richiesta - qta_scorta).toLocale() + `</td>
</tr>`);
}
}
for(const id_articolo in richieste) {
let qta_scorta = parseFloat(scorte[id_articolo]["qta"]);
let qta_richiesta = parseFloat(richieste[id_articolo]);
if ((qta_richiesta > qta_scorta) && (scorte[id_articolo]["servizio"] !== 1) ) {
body.append(`<tr>
<td>` + scorte[id_articolo]["descrizione"] + `</td>
<td class="text-right">` + qta_richiesta.toLocale() + `</td>
<td class="text-right">` + qta_scorta.toLocale() + `</td>
<td class="text-right">` + (qta_richiesta - qta_scorta).toLocale() + `</td>
</tr>`);
if (body.html()) {
sottoscorta.removeClass("hidden");
} else {
sottoscorta.addClass("hidden");
}
}
if (body.html()) {
sottoscorta.removeClass("hidden");
} else {
sottoscorta.addClass("hidden");
}
}
$("input[name=righe]").each(function() {
ricalcolaTotaleRiga($(this).val());
});
function ricalcolaTotaleRiga(r) {
let prezzo_unitario = $("#prezzo_unitario_" + r).val();
let sconto = $("#sconto_unitario_" + r).val();
let max_qta_input = $("#max_qta_" + r);
let qta_max = max_qta_input.val();
prezzo_unitario = parseFloat(prezzo_unitario);
sconto = parseFloat(sconto);
qta_max = parseFloat(qta_max);
let prezzo_scontato = prezzo_unitario - sconto;
let qta = ($("#qta_" + r).val()).toEnglish();
// Se inserisco una quantità da evadere maggiore di quella rimanente, la imposto al massimo possibile
if (qta > qta_max) {
qta = qta_max;
$("#qta_" + r).val(qta);
}
// Se tolgo la spunta della casella dell\'evasione devo azzerare i conteggi
if (isNaN(qta) || !$("#checked_" + r).is(":checked")) {
qta = 0;
}
let serial_select = $("#serial_" + r);
serial_select.selectClear();
serial_select.select2("destroy");
serial_select.data("maximum", qta);
start_superselect();
let subtotale = (prezzo_scontato * qta).toLocale();
$("#subtotale_" + r).html(subtotale + " " + globals.currency);
ricalcolaTotale();
}
function ricalcolaTotale() {
let totale = 0.00;
let totale_qta = 0;
$("input[id*=qta_]").each(function() {
let qta = ($(this).val()).toEnglish();
let r = $(this).attr("id").replace("qta_", "");
if (!$("#checked_" + r).is(":checked") || isNaN(qta)) {
qta = 0;
}
$("input[name=righe]").each(function() {
ricalcolaTotaleRiga($(this).val());
});
function ricalcolaTotaleRiga(r) {
let prezzo_unitario = $("#prezzo_unitario_" + r).val();
let sconto = $("#sconto_unitario_" + r).val();
let max_qta_input = $("#max_qta_" + r);
let qta_max = max_qta_input.val();
prezzo_unitario = parseFloat(prezzo_unitario);
sconto = parseFloat(sconto);
qta_max = parseFloat(qta_max);
let prezzo_scontato = prezzo_unitario - sconto;
if(prezzo_scontato) {
totale += prezzo_scontato * qta;
let qta = ($("#qta_" + r).val()).toEnglish();
// Se inserisco una quantità da evadere maggiore di quella rimanente, la imposto al massimo possibile
if (qta > qta_max) {
qta = qta_max;
$("#qta_" + r).val(qta);
}
totale_qta += qta;
});
// Se tolgo la spunta della casella dell\'evasione devo azzerare i conteggi
if (isNaN(qta) || !$("#checked_" + r).is(":checked")) {
qta = 0;
}
$("#totale").html((totale.toLocale()) + " " + globals.currency);';
let serial_select = $("#serial_" + r);
serial_select.selectClear();
serial_select.select2("destroy");
serial_select.data("maximum", qta);
start_superselect();
if (empty($options['allow-empty'])) {
echo '
if (totale_qta > 0) {
$("#submit_btn").show();
} else {
$("#submit_btn").hide();
}';
}
let subtotale = (prezzo_scontato * qta).toLocale();
echo '
controllaMagazzino();
}
$("#subtotale_" + r).html(subtotale + " " + globals.currency);
ricalcolaTotale();
ricalcolaTotale();
}
function ricalcolaTotale() {
let totale = 0.00;
let totale_qta = 0;
$("input[id*=qta_]").each(function() {
let qta = ($(this).val()).toEnglish();
let r = $(this).attr("id").replace("qta_", "");
if (!$("#checked_" + r).is(":checked") || isNaN(qta)) {
qta = 0;
}
let prezzo_unitario = $("#prezzo_unitario_" + r).val();
let sconto = $("#sconto_unitario_" + r).val();
prezzo_unitario = parseFloat(prezzo_unitario);
sconto = parseFloat(sconto);
let prezzo_scontato = prezzo_unitario - sconto;
if(prezzo_scontato) {
totale += prezzo_scontato * qta;
}
totale_qta += qta;
});
$("#totale").html((totale.toLocale()) + " " + globals.currency);
if (!permetti_documento_vuoto) {
if (totale_qta > 0) {
$("#submit_btn").show();
} else {
$("#submit_btn").hide();
}
}
controllaMagazzino();
}
ricalcolaTotale();
$(document).ready(function(){
if(input("id_ritenuta_acconto").get()){
if(input("id_ritenuta_acconto").get()) {
$("#calcolo_ritenuta_acconto").prop("required", true);
} else{
$("#calcolo_ritenuta_acconto").prop("required", false);
@ -552,9 +590,8 @@ ricalcolaTotale();
}
$("#id_ritenuta_acconto").on("change", function(){
if(input("id_ritenuta_acconto").get()){
if(input("id_ritenuta_acconto").get()) {
$("#calcolo_ritenuta_acconto").prop("required", true);
} else{
$("#calcolo_ritenuta_acconto").prop("required", false);
input("calcolo_ritenuta_acconto").set("");

View File

@ -19,8 +19,6 @@
include_once __DIR__.'/../../core.php';
use Modules\Articoli\Articolo;
/**
* Funzione per aggiornare le sedi nei movimenti di magazzino.
*/

View File

@ -19,6 +19,7 @@
include_once __DIR__.'/../../core.php';
use Models\Module;
use Modules\Anagrafiche\Anagrafica;
use Modules\Articoli\Articolo as ArticoloOriginale;
use Modules\DDT\Components\Articolo;
@ -26,6 +27,7 @@ use Modules\DDT\Components\Descrizione;
use Modules\DDT\Components\Riga;
use Modules\DDT\Components\Sconto;
use Modules\DDT\DDT;
use Modules\DDT\Stato;
use Modules\DDT\Tipo;
$module = Modules::get($id_module);
@ -36,7 +38,7 @@ if ($module['name'] == 'Ddt di vendita') {
$dir = 'uscita';
}
switch (post('op')) {
switch (filter('op')) {
case 'add':
$idanagrafica = post('idanagrafica');
$data = post('data');
@ -421,14 +423,58 @@ switch (post('op')) {
break;
case 'update_position':
$order = explode(',', post('order', true));
case 'update_position':
$order = explode(',', post('order', true));
foreach ($order as $i => $id_riga) {
$dbo->query('UPDATE `dt_righe_ddt` SET `order` = '.prepare($i + 1).' WHERE id='.prepare($id_riga));
}
foreach ($order as $i => $id_riga) {
$dbo->query('UPDATE `dt_righe_ddt` SET `order` = '.prepare($i + 1).' WHERE id='.prepare($id_riga));
}
break;
break;
/*
* Gestione della generazione di DDT in direzione opposta a quella corrente, per completare il riferimento di trasporto interno tra sedi distinte dell'anagrafica Azienda.
*/
case 'completa_trasporto':
$tipo = Tipo::where('dir', '!=', $ddt->direzione)->first();
$stato = Stato::where('descrizione', '=', 'Evaso')->first();
// Duplicazione DDT
$copia = $ddt->replicate();
$copia->tipo()->associate($tipo);
$copia->stato()->associate($stato);
$copia->id_ddt_trasporto_interno = $ddt->id;
// Inversione sedi
$copia->idsede_partenza = $ddt->idsede_destinazione;
$copia->idsede_destinazione = $ddt->idsede_partenza;
$copia->save();
// Copia righe
$righe = $ddt->getRighe();
foreach ($righe as $riga) {
$copia_riga = $riga->replicate();
// Aggiornamento riferimenti
$copia_riga->idddt = $copia->id;
$copia_riga->original_id = null;
$copia_riga->original_type = null;
$copia_riga->save();
// Movimentazione forzata in direzione del documento
$copia_riga->movimenta($riga->qta);
}
// Salvataggio riferimento
$ddt->id_ddt_trasporto_interno = $copia->id;
$ddt->save();
$id_record = $copia->id;
$id_module = $ddt->direzione == 'entrata' ? Module::pool('Ddt di acquisto')->id : Module::pool('Ddt di vendita')->id;
break;
}
// Aggiornamento stato degli ordini presenti in questa fattura in base alle quantità totali evase

View File

@ -17,14 +17,54 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Models\Module;
include_once __DIR__.'/../../core.php';
$stati = $dbo->fetchArray('SELECT descrizione FROM `dt_statiddt` WHERE `is_fatturabile` = 1');
// Informazioni sui movimenti interni
if (!empty($ddt->id_ddt_trasporto_interno)) {
$id_module_collegamento = $ddt->direzione == 'entrata' ? Module::pool('Ddt di acquisto')->id : Module::pool('Ddt di vendita')->id;
echo '
<div class="tip" data-toggle="tooltip" title="'.tr("Questo ddt è impostato sull'anagrafica Azienda, e pertanto rappresenta un trasporto interno di merce: il movimento tra sedi distinte è necessario completato tramite un DDT in direzione opposta").'.">
<a class="btn btn-info" href="'.base_url().'/editor.php?id_module='.$id_module_collegamento.'&id_record='.$ddt->id_ddt_trasporto_interno.'">
<i class="fa fa-truck"></i> '.tr('DDT di completamento trasporto').'
</a>
</div>';
} elseif ($azienda->id == $ddt->anagrafica->id) {
echo '
<div class="tip" data-toggle="tooltip" title="'.tr("Questo ddt è impostato sull'anagrafica Azienda, e pertanto rappresenta un trasporto interno di merce: per completare il movimento tra sedi distinte, è necessario generare un DDT in direzione opposta tramite questo pulsante").'.">
<button class="btn btn-warning '.($ddt->isImportabile() ? '' : 'disabled').'" onclick="completaTrasporto()">
<i class="fa fa-truck"></i> '.tr('Completa trasporto ').'
</button>
</div>
<script>
function completaTrasporto() {
swal({
title: "'.tr('Completare il trasporto?').'",
text: "'.tr('Sei sicuro di voler completare il trasporto interno tramite un DDT in direzione opposta?').'",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn btn-lg btn-success",
confirmButtonText: "'.tr('Completa').'",
}).then(
function() {
location.href = globals.rootdir + "/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=completa_trasporto&backto=record-edit";
},
function() {}
);
}
</script>';
}
// Informazioni sull'importabilità del DDT
$stati = $database->fetchArray('SELECT descrizione FROM `dt_statiddt` WHERE `is_fatturabile` = 1');
foreach ($stati as $stato) {
$stati_importabili[] = $stato['descrizione'];
}
$causali = $dbo->fetchArray('SELECT descrizione FROM `dt_causalet` WHERE `is_importabile` = 1');
$causali = $database->fetchArray('SELECT descrizione FROM `dt_causalet` WHERE `is_importabile` = 1');
foreach ($causali as $causale) {
$causali_importabili[] = $causale['descrizione'];
}

View File

@ -19,8 +19,11 @@
include_once __DIR__.'/../../core.php';
use Modules\Anagrafiche\Anagrafica;
use Modules\DDT\DDT;
$azienda = Anagrafica::find(setting('Azienda predefinita'));
if ($module['name'] == 'Ddt di vendita') {
$dir = 'entrata';
} else {

View File

@ -150,23 +150,22 @@ echo '
</form>
<?php
if( !empty($newsletters)){
if (!empty($newsletters)) {
echo '
<div class="alert alert-danger">
'.tr('Questo template non può essere rimosso dal sistema perchè collegato alle seguenti newsletter:').'
<ul>';
foreach($newsletters as $newsletter){
echo '
foreach ($newsletters as $newsletter) {
echo '
<li>'.Modules::link('Newsletter', $newsletter->id, $newsletter->name, null, '').'</li>';
}
}
echo '
</ul>
</div>';
}elseif (!$record['predefined']) {
?>
} elseif (!$record['predefined']) {
?>
<a class="btn btn-danger ask" data-backto="record-list">
<i class="fa fa-trash"></i> <?php echo tr('Elimina'); ?>
</a>

View File

@ -25,5 +25,5 @@ if (isset($id_record)) {
$record = $dbo->fetchOne('SELECT * FROM em_templates WHERE id='.prepare($id_record).' AND deleted_at IS NULL');
//Controllo se ci sono newletter collegate a questo template
$newsletters = Newsletter::where('id_template',$id_record)->get();
$newsletters = Newsletter::where('id_template', $id_record)->get();
}

View File

@ -23,7 +23,7 @@ use Modules\Emails\Template;
include_once __DIR__.'/../../core.php';
//Controllo se il template è ancora attivo
if( empty($template) ){
if (empty($template)) {
echo '
<div class=" alert alert-danger">'.tr('ATTENZIONE! Questa newsletter risulta collegata ad un template non più presente a sistema').'</div>';
}

View File

@ -17,8 +17,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use Modules\Newsletter\Newsletter;
use Modules\Emails\Template;
use Modules\Newsletter\Newsletter;
include_once __DIR__.'/../../core.php';

View File

@ -135,3 +135,6 @@ INSERT INTO `zz_api_resources` (`id`, `version`, `type`, `resource`, `class`, `e
(NULL, 'app-v1', 'retrieve', 'controllo-clienti', 'API\\App\\v1\\ControlloClienti', '1'),
(NULL, 'app-v1', 'retrieve', 'segnalazione-bug', 'API\\App\\v1\\SegnalazioneBug', '1'),
(NULL, 'app-v1', 'create', 'segnalazione-bug', 'API\\App\\v1\\SegnalazioneBug', '1');
-- Aggiunto collegamento tra DDT in direzioni opposte per gestione movimentazioni interne tra sedi
ALTER TABLE `dt_ddt` ADD `id_ddt_trasporto_interno` INT(11) NULL, ADD FOREIGN KEY (`id_ddt_trasporto_interno`) REFERENCES `dt_ddt`(`id`) ON DELETE CASCADE;