1
0
mirror of https://github.com/devcode-it/openstamanager.git synced 2025-01-30 15:35:09 +01:00

Miglioramento gestione ricevute FE

This commit is contained in:
Thomas Zilio 2019-07-10 15:02:09 +02:00
parent 4755eac00f
commit 5eb283af5c
14 changed files with 393 additions and 89 deletions

View File

@ -250,7 +250,7 @@ $(document).ready(function () {
// Entra nel tab indicato al caricamento della pagina // Entra nel tab indicato al caricamento della pagina
var hash = window.location.hash ? window.location.hash : getUrlVars().hash; var hash = window.location.hash ? window.location.hash : getUrlVars().hash;
if (hash && hash != '#tab_0') { if (hash && hash != '#tab_0') {
$('ul.nav-tabs a[href="' + hash + '"]').tab('show'); $('ul.nav-tabs a[href="' + hash + '"]').tab('show').trigger('shown.bs.tab');
} }
// Nel caso la navigazione sia da mobile, disabilito il ritorno al punto precedente // Nel caso la navigazione sia da mobile, disabilito il ritorno al punto precedente

View File

@ -93,7 +93,7 @@ if ($dir == 'entrata') {
{[ "type": "text", "label": "<?php echo $label; ?>", "name": "numero_esterno", "class": "text-center", "value": "$numero_esterno$" ]} {[ "type": "text", "label": "<?php echo $label; ?>", "name": "numero_esterno", "class": "text-center", "value": "$numero_esterno$" ]}
</div> </div>
<div class="col-md-<?php echo ($dir=='entrata') ? '3' : '2'; ?>"> <div class="col-md-<?php echo ($dir == 'entrata') ? '3' : '2'; ?>">
{[ "type": "date", "label": "<?php echo tr('Data emissione'); ?>", "name": "data", "required": 1, "value": "$data$" ]} {[ "type": "date", "label": "<?php echo tr('Data emissione'); ?>", "name": "data", "required": 1, "value": "$data$" ]}
</div> </div>

View File

@ -262,8 +262,8 @@ if ($generated) {
event.preventDefault(); event.preventDefault();
swal({ swal({
title: "Sei sicuro di rigenerare la fattura?", title: "'.tr('Sei sicuro di rigenerare la fattura?').'",
text: "Attenzione: sarà generato un nuovo progressivo invio.", html: "<p>'.tr('Attenzione: sarà generato un nuovo progressivo invio').'.</p><p class=\"text-danger\">'.tr('Se stai attendendo una ricevuta dal sistema SdI, rigenerando la fattura elettronica non sarà possibile corrispondere la ricevuta una volta emessa').'.</p>",
type: "warning", type: "warning",
showCancelButton: true, showCancelButton: true,
confirmButtonColor: "#30d64b", confirmButtonColor: "#30d64b",

View File

@ -1202,7 +1202,7 @@ class FatturaElettronica
$name = 'Stampa allegata'; $name = 'Stampa allegata';
$is_presente = database()->fetchNum('SELECT id FROM zz_files WHERE id_module = '.prepare($id_module).' AND id_record = '.prepare($documento['id']).' AND name = '.prepare($name)); $is_presente = database()->fetchNum('SELECT id FROM zz_files WHERE id_module = '.prepare($id_module).' AND id_record = '.prepare($documento['id']).' AND name = '.prepare($name));
if(empty($is_presente)) { if (empty($is_presente)) {
Uploads::register(array_merge([ Uploads::register(array_merge([
'name' => $name, 'name' => $name,
'original' => basename($info['path']), 'original' => basename($info['path']),

View File

@ -10,20 +10,11 @@ switch (filter('op')) {
$content = file_get_contents($_FILES['blob']['tmp_name']); $content = file_get_contents($_FILES['blob']['tmp_name']);
$file = FatturaElettronica::store($_FILES['blob']['name'], $content); $file = FatturaElettronica::store($_FILES['blob']['name'], $content);
if (FatturaElettronica::isValid($file)) { $name = $file;
echo json_encode([
'filename' => $file,
]);
} else {
echo json_encode([
'already' => 1,
]);
}
break;
// no break
case 'prepare': case 'prepare':
$name = get('name'); $name = $name ?: get('name');
$file = Interaction::getImportXML($name); $file = Interaction::getImportXML($name);
if (FatturaElettronica::isValid($file)) { if (FatturaElettronica::isValid($file)) {
@ -94,7 +85,7 @@ switch (filter('op')) {
// Processo il file ricevuto // Processo il file ricevuto
if (Interaction::isEnabled()) { if (Interaction::isEnabled()) {
$process_result = Interaction::processXML($name); $process_result = Interaction::processXML($name);
if (!empty($process_resul)) { if (!empty($process_result)) {
flash()->error($process_result); flash()->error($process_result);
} }
} }

View File

@ -40,10 +40,59 @@ switch (filter('op')) {
break; break;
case 'list': case 'save':
$list = Interaction::getReceiptList(); $content = file_get_contents($_FILES['blob']['tmp_name']);
$file = Ricevuta::store($_FILES['blob']['name'], $content);
echo json_encode($list); $name = $file;
// no break
case 'prepare':
$name = $name ?: get('name');
Interaction::getReceipt($name);
$fattura = null;
try {
$receipt = new Ricevuta($name, $content);
$receipt->save();
$fattura = $receipt->getFattura()->numero_esterno;
$receipt->delete();
Interaction::processReceipt($name);
} catch (UnexpectedValueException $e) {
}
echo json_encode([
'file' => $name,
'fattura' => $fattura,
]);
break;
case 'list':
include __DIR__.'/rows.php';
break;
case 'delete':
$directory = Ricevuta::getImportDirectory();
delete($directory.'/'.get('name'));
break;
case 'process':
$name = get('name');
// Processo il file ricevuto
if (Interaction::isEnabled()) {
$process_result = Interaction::processReceipt($name);
if (!empty($process_result)) {
flash()->error($process_result);
}
}
break; break;
} }

View File

@ -4,78 +4,147 @@ include_once __DIR__.'/../../core.php';
use Plugins\ReceiptFE\Interaction; use Plugins\ReceiptFE\Interaction;
if (!Interaction::isEnabled()) {
echo '
<p>'.tr('Il sistema di rilevazione automatico è attualmente disabilitato').'. '.tr('Per maggiori informazioni contatta gli sviluppatori ufficiali').'.</p>';
return;
}
echo ' echo '
<p>'.tr('Le ricevute delle Fatture Elettroniche permettono di individuare se una determinata fattura tramessa è stata accettata dal Sistema Di Interscambio').'.</p> <p>'.tr('Le ricevute delle Fatture Elettroniche permettono di individuare se una determinata fattura tramessa è stata accettata dal Sistema Di Interscambio').'.</p>
<p>'.tr('Tramite il pulsante _BTN_ è possibile procedere al recupero delle ricevute, aggiornando automaticamente lo stato delle relative fatture e allegandole ad esse', [ <p>'.tr('Tramite il pulsante _BTN_ è possibile procedere al recupero delle ricevute, aggiornando automaticamente lo stato delle relative fatture e allegandole ad esse', [
'_BTN_' => '<b>Ricerca</b>', '_BTN_' => '<b>'.tr('Ricerca ricevute').'</b>',
]).'.</p> ]).'.</p>
<br>'; <br>
<div class="box box-success">
<div class="box-header with-border">
<h3 class="box-title">
'.tr('Carica un XML').'
<span class="tip" title="'.tr('Formati supportati: XML e P7M').'.">
<i class="fa fa-question-circle-o"></i>
</span>
</h3>
</div>
<div class="box-body" id="upload">
<div class="row">
<div class="col-md-9">
{[ "type": "file", "name": "blob", "required": 1 ]}
</div>
<div class="col-md-3">
<button type="button" class="btn btn-primary pull-right" onclick="upload(this)">
<i class="fa fa-upload"></i> '.tr('Carica ricevuta').'
</button>
</div>
</div>
</div>
</div>';
echo ' echo '
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">
'.tr('Ricevute da importare').'</span>
</h3>';
<div class="text-center"> // Ricerca automatica
<button type="button" class="btn btn-primary btn-lg" onclick="search(this)"> if (Interaction::isEnabled()) {
<i class="fa fa-refresh"></i> '.tr('Ricerca').'... echo '
<div class="pull-right">
<button type="button" class="btn btn-warning" onclick="importAll(this)">
<i class="fa fa-download"></i> '.tr('Importa tutte le ricevute').'
</button> </button>
<button type="button" class="btn btn-primary" onclick="search(this)">
<i class="fa fa-refresh"></i> '.tr('Ricerca ricevute').'
</button>
</div>';
}
echo '
</div>
<div class="box-body" id="list">';
if (Interaction::isEnabled()) {
echo '
<p>'.tr('Per vedere le ricevute da importare utilizza il pulsante _BUTTON_', [
'_BUTTON_' => '<b>"'.tr('Ricerca ricevute').'"</b>',
]).'.</p>';
} else {
include $structure->filepath('list.php');
}
echo '
</div>
</div>'; </div>';
echo ' echo '
<script> <script>
function search(btn) { function search(button) {
var restore = buttonLoading(button);
$("#list").load("'.$structure->fileurl('list.php').'?id_module='.$id_module.'&id_plugin='.$id_plugin.'", function() {
buttonRestore(button, restore);
});
}
function upload(btn) {
if ($("#blob").val()) {
var restore = buttonLoading(btn); var restore = buttonLoading(btn);
$.ajax({ $("#upload").ajaxSubmit({
url: globals.rootdir + "/actions.php", url: globals.rootdir + "/actions.php",
data: { data: {
op: "list", op: "save",
id_module: "'.$id_module.'", id_module: "'.$id_module.'",
id_plugin: "'.$id_plugin.'", id_plugin: "'.$id_plugin.'",
}, },
type: "post", type: "post",
success: function(data){ success: function(data){
data = JSON.parse(data); importMessage(data);
count = data.length;
buttonRestore(btn, restore); buttonRestore(btn, restore);
},
error: function(xhr) {
alert("'.tr('Errore').': " + xhr.responseJSON.error.message);
if(count == 0){ buttonRestore(btn, restore);
swal({ }
title: "'.tr('Non ci sono ricevute da importare').'",
showCancelButton: false,
confirmButtonText: "'.tr('OK').'",
type: "info",
}); });
} else { } else {
swal({ swal({
title: "'.tr('Ricevute da importare: _COUNT_', [ title: "'.tr('Selezionare un file!').'",
'_COUNT_' => '" + count + "', type: "error",
]).'", })
html: "'.tr('Importando le ricevute, verranno aggiornati gli stati di invio fatture elettroniche. Continuare?').'", }
}
function importMessage(data) {
data = JSON.parse(data);
var ricevuta = "<br>'.tr('Ricevuta').': " + data.file;
if(data.fattura) {
swal({
title: "'.tr('Importazione completata!').'",
html: "'.tr('Fattura aggiornata correttamente').':" + data.fattura + ricevuta,
type: "success",
});
} else {
swal({
title: "'.tr('Importazione fallita!').'",
html: "<i>'.tr('Fattura relativa alla ricevuta non rilevata. Controlla che esista una fattura di vendita corrispondente caricata a gestionale.').'</i>" + ricevuta,
type: "error",
});
}
}
function importAll(btn) {
swal({
title: "'.tr('Importare tutte le ricevute?').'",
html: "'.tr('Importando le ricevute, verranno aggiornati gli stati di invio delle fatture elettroniche. Continuare?').'",
showCancelButton: true, showCancelButton: true,
confirmButtonText: "'.tr('Procedi').'", confirmButtonText: "'.tr('Procedi').'",
type: "info", type: "info",
}).then(function (result) { }).then(function (result) {
importAll(btn);
});
}
},
error: function(data) {
alert("'.tr('Errore').': " + data);
buttonRestore(btn, restore);
}
});
}
function importAll(btn) {
var restore = buttonLoading(btn); var restore = buttonLoading(btn);
$.ajax({ $.ajax({
@ -96,7 +165,7 @@ echo '
if(element.fattura) { if(element.fattura) {
text += element.fattura; text += element.fattura;
} else { } else {
text += "<i>'.tr('Ricevuta non ottenuta correttamente. Controlla che esista una fattura di vendita corrispondente caricata a gestionale.').'</i>"; text += "<i>'.tr('Fattura relativa alla ricevuta non rilevata. Controlla che esista una fattura di vendita corrispondente caricata a gestionale.').'</i>";
} }
text += " (" + element.file + ")"; text += " (" + element.file + ")";
@ -107,7 +176,7 @@ echo '
html += "<br><small>'.tr("Se si sono verificati degli errori durante la procedura e il problema continua a verificarsi, contatta l'assistenza ufficiale").'</small>"; html += "<br><small>'.tr("Se si sono verificati degli errori durante la procedura e il problema continua a verificarsi, contatta l'assistenza ufficiale").'</small>";
swal({ swal({
title: "'.tr('Importazione completata!').'", title: "'.tr('Operazione completata!').'",
html: html, html: html,
type: "info", type: "info",
}) })
@ -120,5 +189,6 @@ echo '
buttonRestore(btn, restore); buttonRestore(btn, restore);
} }
}); });
} });
}
</script>'; </script>';

145
plugins/receiptFE/list.php Normal file
View File

@ -0,0 +1,145 @@
<?php
include_once __DIR__.'/../../core.php';
use Plugins\ReceiptFE\Interaction;
use Plugins\ReceiptFE\ReceiptHook;
use Plugins\ReceiptFE\Ricevuta;
$list = Interaction::getReceiptList();
// Aggiornamento cache hook
ReceiptHook::update($list);
$directory = Ricevuta::getImportDirectory();
if (!empty($list)) {
echo '
<table class="table table-striped table-hover table-condensed table-bordered datatables">
<thead>
<tr>
<th width="80%">'.tr('Nome').'</th>
<th width="20%" class="text-center">#</th>
</tr>
</thead>
<tbody>';
foreach ($list as $element) {
echo '
<tr>
<td>'.$element.'</td>
<td class="text-center">';
if (file_exists($directory.'/'.$element)) {
echo '
<button type="button" class="btn btn-danger" onclick="delete_fe(this, \''.$element.'\')">
<i class="fa fa-trash"></i>
</button>';
} else {
echo '
<button type="button" class="btn btn-info" onclick="process_fe(this, \''.$element.'\')">
<i class="fa fa-upload"></i>
</button>';
}
echo '
<button type="button" class="btn btn-warning" '.((!extension_loaded('openssl') and substr(strtolower($element), -4) == '.p7m') ? 'disabled' : '').' onclick="download(this, \''.$element.'\')">
<i class="fa fa-download"></i> '.tr('Importa').'
</button>
</td>
</tr>';
}
echo '
</tbody>
</table>';
} else {
echo '
<p>'.tr('Nessuna ricevuta da importare').'.</p>';
}
echo '
<script>
function download(button, file) {
var restore = buttonLoading(button);
$.ajax({
url: globals.rootdir + "/actions.php",
type: "get",
data: {
id_module: globals.id_module,
id_plugin: '.$id_plugin.',
op: "prepare",
name: file,
},
success: function(data) {
importMessage(data);
buttonRestore(button, restore);
},
error: function(xhr) {
alert("'.tr('Errore').': " + xhr.responseJSON.error.message);
buttonRestore(button, restore);
}
});
}
function delete_fe(button, file) {
swal({
title: "'.tr('Rimuovere la ricevuta salvata localmente?').'",
html: "'.tr('Sarà possibile inserirla nuovamente nel gestionale attraverso il caricamento').'",
type: "error",
showCancelButton: true,
confirmButtonText: "'.tr('Sì').'"
}).then(function (result) {
var restore = buttonLoading(button);
$.ajax({
url: globals.rootdir + "/actions.php",
type: "get",
data: {
id_module: globals.id_module,
id_plugin: '.$id_plugin.',
op: "delete",
name: file,
},
success: function(data) {
$("#list").load("'.$structure->fileurl('list.php').'?id_module='.$id_module.'&id_plugin='.$id_plugin.'", function() {
buttonRestore(button, restore);
});
}
});
});
}
function process_fe(button, file) {
swal({
title: "'.tr('Segnare la ricevuta come processata?').'",
html: "'.tr("Non sarà possibile individuarla nuovamente in modo automatico: l'unico modo per recuperarla sarà contattare l'assistenza").'",
type: "info",
showCancelButton: true,
confirmButtonText: "'.tr('Sì').'"
}).then(function (result) {
var restore = buttonLoading(button);
$.ajax({
url: globals.rootdir + "/actions.php",
type: "get",
data: {
id_module: globals.id_module,
id_plugin: '.$id_plugin.',
op: "process",
name: file,
},
success: function(data) {
$("#list").load("'.$structure->fileurl('list.php').'?id_module='.$id_module.'&id_plugin='.$id_plugin.'", function() {
buttonRestore(button, restore);
});
}
});
});
}
start_local_datatables();
</script>';

View File

@ -13,10 +13,30 @@ class Interaction extends Connection
{ {
public static function getReceiptList() public static function getReceiptList()
{ {
$directory = Ricevuta::getImportDirectory();
$list = [];
$files = glob($directory.'/*.xml*');
foreach ($files as $file) {
$list[] = basename($file);
}
// Ricerca da remoto
if (self::isEnabled()) {
$response = static::request('POST', 'notifiche_da_importare'); $response = static::request('POST', 'notifiche_da_importare');
$body = static::responseBody($response); $body = static::responseBody($response);
return $body['results']; if ($body['status'] == '200') {
$files = $body['results'];
foreach ($files as $file) {
$list[] = basename($file);
}
}
}
return array_clean($list);
} }
public static function getReceipt($name) public static function getReceipt($name)

View File

@ -22,9 +22,9 @@ $data_max = strtotime($prezzo_max['data']);
if ($data_min == $data_max) { if ($data_min == $data_max) {
$andamento = tr('N.D.'); $andamento = tr('N.D.');
} elseif ($data_min < $data_max) { } elseif ($data_min < $data_max) {
$andamento = tr('in aumento'); $andamento = tr('In aumento');
} else { } else {
$andamento = tr('in diminuzione'); $andamento = tr('In diminuzione');
} }
echo ' echo '

View File

@ -49,6 +49,31 @@ echo '
</div> </div>
</div> </div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Prezzo medio vendita').'</h3>
</div>
<div class="panel-body">
<table class="table table-striped table-condensed table-bordered">
<thead>
<tr>
<th>'.tr('Perido').'</th>
<th>'.tr('Prezzo minimo').'</th>
<th>'.tr('Prezzio medio').'</th>
<th>'.tr('Prezzo massimo').'</th>
<th>'.tr('Oscillazione').'</th>
<th>'.tr('Oscillazione in %').'</th>
<th>'.tr('Andamento prezzo').'</th>
</tr>
</thead>
<tbody id="prezzi_vendita">
</tbody>
</table>
</div>
</div>
<script> <script>
$(document).ready(function() { $(document).ready(function() {
add_period(); add_period();
@ -56,6 +81,7 @@ $(document).ready(function() {
function change_period(calendar, start, end) { function change_period(calendar, start, end) {
add_prezzo("#prezzi_acquisto", calendar, "uscita", start, end); add_prezzo("#prezzi_acquisto", calendar, "uscita", start, end);
add_prezzo("#prezzi_vendita", calendar, "entrata", start, end);
} }
function add_prezzo(id, calendar, direzione, start, end) { function add_prezzo(id, calendar, direzione, start, end) {

View File

@ -29,7 +29,8 @@ class Module extends Model
'options2', 'options2',
]; ];
public function replacePlaceholders($id_record, $value){ public function replacePlaceholders($id_record, $value)
{
$replaces = $this->getPlaceholders($id_record); $replaces = $this->getPlaceholders($id_record);
$value = str_replace(array_keys($replaces), array_values($replaces), $value); $value = str_replace(array_keys($replaces), array_values($replaces), $value);
@ -37,8 +38,9 @@ class Module extends Model
return $value; return $value;
} }
public function getPlaceholders($id_record) { public function getPlaceholders($id_record)
if(!isset($variables[$id_record])) { {
if (!isset($variables[$id_record])) {
$dbo = $database = database(); $dbo = $database = database();
// Lettura delle variabili nei singoli moduli // Lettura delle variabili nei singoli moduli
@ -47,7 +49,7 @@ class Module extends Model
// Sostituzione delle variabili di base // Sostituzione delle variabili di base
$replaces = []; $replaces = [];
foreach ($variables as $key => $value) { foreach ($variables as $key => $value) {
$replaces['{' . $key . '}'] = $value; $replaces['{'.$key.'}'] = $value;
} }
$this->variables[$id_record] = $replaces; $this->variables[$id_record] = $replaces;

View File

@ -3,10 +3,10 @@
namespace Notifications; namespace Notifications;
use Mail; use Mail;
use Modules;
use PHPMailer\PHPMailer\Exception as PHPMailerException; use PHPMailer\PHPMailer\Exception as PHPMailerException;
use Prints; use Prints;
use Uploads; use Uploads;
use Modules;
class EmailNotification extends Notification class EmailNotification extends Notification
{ {
@ -161,7 +161,7 @@ class EmailNotification extends Notification
} }
// Utilizzo di una cartella particolare per il salvataggio temporaneo degli allegati // Utilizzo di una cartella particolare per il salvataggio temporaneo degli allegati
$path = DOCROOT.'/files/notifications/';; $path = DOCROOT.'/files/notifications/';
$info = Prints::render($print['id'], $id_record, $path); $info = Prints::render($print['id'], $id_record, $path);
$name = $name ?: $info['name']; $name = $name ?: $info['name'];

View File

@ -357,14 +357,15 @@ class Prints
return $file; return $file;
} }
protected static function getFile($record, $id_record, $directory, $original_replaces) { protected static function getFile($record, $id_record, $directory, $original_replaces)
{
$module = Modules::get($record['id_module']); $module = Modules::get($record['id_module']);
$name = $record['filename'].'.pdf'; $name = $record['filename'].'.pdf';
$name = $module->replacePlaceholders($id_record, $name); $name = $module->replacePlaceholders($id_record, $name);
$replaces = []; $replaces = [];
foreach ($original_replaces as $key=>$value){ foreach ($original_replaces as $key => $value) {
$key = substr($key, 1, -1); $key = substr($key, 1, -1);
$replaces['{'.$key.'}'] = $value; $replaces['{'.$key.'}'] = $value;