mirror of
https://github.com/devcode-it/openstamanager.git
synced 2025-02-01 16:36:45 +01:00
Introduzione sistema per le ricevute
This commit is contained in:
parent
4f0091e7a2
commit
868dbb075a
@ -8,4 +8,5 @@ return [
|
||||
'modules/interventi' => 'Modules\Interventi',
|
||||
'plugins/exportFE' => 'Plugins\ExportFE',
|
||||
'plugins/importFE' => 'Plugins\ImportFE',
|
||||
'plugins/receiptFE' => 'Plugins\ReceiptFE',
|
||||
];
|
||||
|
@ -39,9 +39,9 @@ if (!function_exists('array_clean')) {
|
||||
*/
|
||||
function array_clean($array)
|
||||
{
|
||||
return array_values(array_filter($array, function ($value) {
|
||||
return array_unique(array_values(array_filter($array, function ($value) {
|
||||
return !empty($value);
|
||||
}));
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,6 +95,7 @@ switch (post('op')) {
|
||||
'rivalsainps' => 0,
|
||||
'ritenutaacconto' => 0,
|
||||
'iva_rivalsainps' => 0,
|
||||
'codice_stato_fe' => post('codice_stato_fe'),
|
||||
], $data), ['id' => $id_record]);
|
||||
|
||||
$query = 'SELECT descrizione FROM co_statidocumento WHERE id='.prepare($idstatodocumento);
|
||||
|
@ -99,6 +99,10 @@ if (empty($record['is_fiscale'])) {
|
||||
<!-- TODO: Rimuovere possibilità di selezionare lo stato pagato obbligando l'utente ad aggiungere il movimento in prima nota -->
|
||||
{[ "type": "select", "label": "<?php echo tr('Stato'); ?>", "name": "idstatodocumento", "required": 1, "values": "query=<?php echo $query; ?>", "value": "$idstatodocumento$", "class": "unblockable", "extra": " onchange = \"if ($('#idstatodocumento option:selected').text()=='Pagato' || $('#idstatodocumento option:selected').text()=='Parzialmente pagato' ){if( confirm('<?php echo tr('Sicuro di voler impostare manualmente la fattura come pagata senza aggiungere il movimento in prima nota?'); ?>') ){ return true; }else{ $('#idstatodocumento').selectSet(<?php echo $record['idstatodocumento']; ?>); }}\" " ]}
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
{[ "type": "select", "label": "<?php echo tr('Stato FE'); ?>", "name": "codice_stato_fe", "required": 0, "values": "query=SELECT codice as id, descrizione as text FROM fe_stati_documento", "value": "$codice_stato_fe$", "disabled": <?php echo intval(Plugins\ExportFE\Connection::isEnabled()) ?> ]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
@ -193,7 +197,7 @@ if (!empty($record['is_fiscale'])) {
|
||||
|
||||
if (($n2 <= 0 && $record['stato'] == 'Emessa') || $differenza != 0) {
|
||||
?>
|
||||
<a class="btn btn-sm btn-primary <?php echo ((!empty(Modules::get('Prima nota'))) ? '' : 'disabled'); ?>" href="javascript:;" onclick="launch_modal( 'Aggiungi prima nota', '<?php echo $rootdir; ?>/add.php?id_module=<?php echo Modules::get('Prima nota')['id']; ?>&iddocumento=<?php echo $id_record; ?>&dir=<?php echo $dir; ?>', 1 );"><i class="fa fa-euro"></i> <?php echo tr('Aggiungi prima nota'); ?>...</a><br><br>
|
||||
<a class="btn btn-sm btn-primary <?php echo((!empty(Modules::get('Prima nota'))) ? '' : 'disabled'); ?>" href="javascript:;" onclick="launch_modal( 'Aggiungi prima nota', '<?php echo $rootdir; ?>/add.php?id_module=<?php echo Modules::get('Prima nota')['id']; ?>&iddocumento=<?php echo $id_record; ?>&dir=<?php echo $dir; ?>', 1 );"><i class="fa fa-euro"></i> <?php echo tr('Aggiungi prima nota'); ?>...</a><br><br>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
@ -28,9 +28,11 @@ switch (filter('op')) {
|
||||
$result = Interaction::sendXML($id_record);
|
||||
|
||||
// Aggiornamento dello stato
|
||||
database()->update('co_documenti', [
|
||||
'codice_stato_fe' => 'WAIT',
|
||||
], ['id' => $id_record]);
|
||||
if ($result) {
|
||||
database()->update('co_documenti', [
|
||||
'codice_stato_fe' => 'WAIT',
|
||||
], ['id' => $id_record]);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'sent' => $result,
|
||||
|
71
plugins/exportFE/src/Connection.php
Normal file
71
plugins/exportFE/src/Connection.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Plugins\ExportFE;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
/**
|
||||
* Classe per l'interazione con API esterne.
|
||||
*
|
||||
* @since 2.4.3
|
||||
*/
|
||||
class Connection
|
||||
{
|
||||
protected static $client = null;
|
||||
|
||||
/**
|
||||
* Restituisce l'oggetto per la connessione all'API del progetto.
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
protected static function getClient()
|
||||
{
|
||||
if (!isset(self::$client)) {
|
||||
self::$client = new Client([
|
||||
'base_uri' => 'https://services.osmcloud.it/v1/',
|
||||
'verify' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
return self::$client;
|
||||
}
|
||||
|
||||
public static function isEnabled()
|
||||
{
|
||||
return !empty(setting('OSMCloud Services API Token'));
|
||||
}
|
||||
|
||||
protected function request($type, $resource, $data = [], $options = [])
|
||||
{
|
||||
$client = static::getClient();
|
||||
|
||||
$json = array_merge($data, [
|
||||
'token' => setting('OSMCloud Services API Token'),
|
||||
'resource' => $resource,
|
||||
]);
|
||||
|
||||
if (!empty($options['multipart'])) {
|
||||
foreach ($json as $key => $value) {
|
||||
$options['multipart'][] = [
|
||||
'name' => $key,
|
||||
'contents' => $value,
|
||||
];
|
||||
}
|
||||
} else {
|
||||
$options['json'] = $json;
|
||||
}
|
||||
|
||||
$options = array_merge($options, [
|
||||
'http_errors' => false,
|
||||
]);
|
||||
|
||||
return $client->request($type, '', $options);
|
||||
}
|
||||
|
||||
protected function responseBody($response)
|
||||
{
|
||||
$body = $response->getBody();
|
||||
|
||||
return json_decode($body, true) ?: [];
|
||||
}
|
||||
}
|
@ -9,75 +9,32 @@ use GuzzleHttp\Client;
|
||||
*
|
||||
* @since 2.4.3
|
||||
*/
|
||||
class Interaction
|
||||
class Interaction extends Connection
|
||||
{
|
||||
protected static $client = null;
|
||||
|
||||
/**
|
||||
* Restituisce l'oggetto per la connessione all'API del progetto.
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
protected static function getClient()
|
||||
{
|
||||
if (!isset(self::$client)) {
|
||||
self::$client = new Client([
|
||||
'base_uri' => 'https://services.osmcloud.it/v1/',
|
||||
'verify' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
return self::$client;
|
||||
}
|
||||
|
||||
public static function isEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function request($type, $resource, $data = [], $options = [])
|
||||
{
|
||||
$client = static::getClient();
|
||||
|
||||
$json = array_merge($data, [
|
||||
'token' => setting('OSMCloud Services API Token'),
|
||||
'resource' => $resource,
|
||||
]);
|
||||
|
||||
$options = array_merge($options, [
|
||||
'json' => $json,
|
||||
'http_errors' => false,
|
||||
]);
|
||||
|
||||
return $client->request($type, '', $options);
|
||||
}
|
||||
|
||||
public static function sendXML($id_record)
|
||||
{
|
||||
try {
|
||||
$fattura = new FatturaElettronica($id_record);
|
||||
$file = DOCROOT.'/'.FatturaElettronica::getDirectory().'/'.$fattura->getFilename();
|
||||
|
||||
$response = static::request('POST', 'send', [
|
||||
'name' => $fattura->getFilename(),
|
||||
], [
|
||||
$response = static::request('POST', 'send_xml', [], [
|
||||
'multipart' => [
|
||||
[
|
||||
'name' => 'xml',
|
||||
'contents' => fopen($file, 'r')
|
||||
'filename' => $fattura->getFilename(),
|
||||
'contents' => file_get_contents($file)
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
$body = $response->getBody();
|
||||
$body = static::responseBody($response);
|
||||
|
||||
if (!empty($body)) {
|
||||
if (!empty($body['sent'])) {
|
||||
return true;
|
||||
}
|
||||
} catch (UnexpectedValueException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -3,63 +3,23 @@
|
||||
namespace Plugins\ImportFE;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Plugins\ExportFE\Connection;
|
||||
|
||||
/**
|
||||
* Classe per l'interazione con API esterne.
|
||||
*
|
||||
* @since 2.4.3
|
||||
*/
|
||||
class Interaction
|
||||
class Interaction extends Connection
|
||||
{
|
||||
protected static $client = null;
|
||||
|
||||
/**
|
||||
* Restituisce l'oggetto per la connessione all'API del progetto.
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
protected static function getClient()
|
||||
{
|
||||
if (!isset(self::$client)) {
|
||||
self::$client = new Client([
|
||||
'base_uri' => 'https://services.osmcloud.it/v1/',
|
||||
'verify' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
return self::$client;
|
||||
}
|
||||
|
||||
public static function isEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function request($type, $resource, $data = [], $options = [])
|
||||
{
|
||||
$client = static::getClient();
|
||||
|
||||
$json = array_merge($data, [
|
||||
'token' => setting('OSMCloud Services API Token'),
|
||||
'resource' => $resource,
|
||||
]);
|
||||
|
||||
$options = array_merge($options, [
|
||||
'json' => $json,
|
||||
'http_errors' => false,
|
||||
]);
|
||||
|
||||
return $client->request($type, '', $options);
|
||||
}
|
||||
|
||||
public static function listToImport()
|
||||
{
|
||||
$directory = FatturaElettronica::getImportDirectory();
|
||||
|
||||
$response = static::request('GET', 'get_fatture_da_importare');
|
||||
$body = $response->getBody();
|
||||
$response = static::request('POST', 'get_fatture_da_importare');
|
||||
$body = static::responseBody($response);
|
||||
|
||||
$list = json_decode($body, true) ?: [];
|
||||
$list = $body['results'];
|
||||
|
||||
$files = glob($directory.'/*.xml');
|
||||
foreach ($files as $file) {
|
||||
@ -75,13 +35,12 @@ class Interaction
|
||||
$file = $directory.'/'.$name;
|
||||
|
||||
if (!file_exists($file)) {
|
||||
$response = static::request('GET', 'get_fattura_da_importare', [
|
||||
$response = static::request('POST', 'get_fattura_da_importare', [
|
||||
'name' => $name,
|
||||
]);
|
||||
$body = static::responseBody($response);
|
||||
|
||||
$body = $response->getBody();
|
||||
|
||||
FatturaElettronica::store($name, $body);
|
||||
FatturaElettronica::store($name, $body['content']);
|
||||
}
|
||||
|
||||
return $name;
|
||||
|
59
plugins/receiptFE/actions.php
Normal file
59
plugins/receiptFE/actions.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
use Plugins\ReceiptFE\Ricevuta;
|
||||
use Plugins\ReceiptFE\Interaction;
|
||||
|
||||
switch (filter('op')) {
|
||||
case 'save':
|
||||
$content = file_get_contents($_FILES['blob']['tmp_name']);
|
||||
$file = FatturaElettronica::store($_FILES['blob']['name'], $content);
|
||||
|
||||
if (FatturaElettronica::isValid($file)) {
|
||||
echo json_encode([
|
||||
'filename' => $file,
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'already' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'import':
|
||||
$list = Interaction::getReceiptList();
|
||||
|
||||
$results = [];
|
||||
foreach ($list as $name) {
|
||||
$file = Interaction::getReceipt($name);
|
||||
|
||||
$result = [];
|
||||
if (!empty($file)) {
|
||||
try {
|
||||
$receipt = new Ricevuta($file['content']);
|
||||
|
||||
$result = [
|
||||
'fattura' => $receipt->getFattura()->numero_esterno,
|
||||
];
|
||||
} catch (UnexpectedValueException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$results[] = array_merge([
|
||||
'file' => $name,
|
||||
], $result);
|
||||
}
|
||||
|
||||
echo json_encode($results);
|
||||
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
$list = Interaction::getReceiptList();
|
||||
|
||||
echo json_encode($list);
|
||||
|
||||
break;
|
||||
}
|
119
plugins/receiptFE/edit.php
Normal file
119
plugins/receiptFE/edit.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
include_once __DIR__.'/../../core.php';
|
||||
|
||||
use Plugins\ReceiptFE\Interaction;
|
||||
|
||||
if (!Interaction::isEnabled()) {
|
||||
echo '
|
||||
<p>'.tr('Il sistema di rilevazione automatico è attualmente disabilitato').'.</p>
|
||||
<p>'.tr('Per maggiori informazioni contatta gli sviluppatori ufficiali').'.</p>';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
echo '
|
||||
<p>'.tr("Le ricevute delle Fatture Elettroniche permettono di individuare se una determinata fattura rilasciata è $requesta accettata dal Sistema Di Interscambio e dal cliente relativo").'.</p>
|
||||
|
||||
<p>'.tr("Tramite il pulsante _BTN_ è possibile procedere all controllo automatico di queste ricevute, che aggiorneranno di conseguenza lo $requesto dei documenti relativi e verranno allegate ad essi", [
|
||||
'_BTN_' => '<b>Ricerca</b>',
|
||||
]).'.</p>
|
||||
<br>';
|
||||
|
||||
echo '
|
||||
|
||||
<div class="text-center">
|
||||
<button type="button" class="btn btn-primary btn-lg" onclick="search(this)">
|
||||
<i class="fa fa-refresh"></i> '.tr('Ricerca').'...
|
||||
</button>
|
||||
</div>';
|
||||
|
||||
echo '
|
||||
<script>
|
||||
function search(btn) {
|
||||
var restore = buttonLoading(btn);
|
||||
|
||||
$.ajax({
|
||||
url: globals.rootdir + "/actions.php",
|
||||
data: {
|
||||
op: "list",
|
||||
id_module: "'.$id_module.'",
|
||||
id_plugin: "'.$id_plugin.'",
|
||||
},
|
||||
type: "post",
|
||||
success: function(data){
|
||||
data = JSON.parse(data);
|
||||
|
||||
count = data.length;
|
||||
buttonRestore(btn, restore);
|
||||
|
||||
swal({
|
||||
title: "'.tr('Ricevute da importare: _COUNT_', [
|
||||
'_COUNT_' => '" + count + "'
|
||||
]).'",
|
||||
html: "'.tr('Sono state individuate _COUNT_ ricevute da importare', [
|
||||
'_COUNT_' => '" + count + "'
|
||||
]).'.",
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "'.tr('Procedi').'",
|
||||
type: "info",
|
||||
}).then(function (result) {
|
||||
importAll(btn);
|
||||
});
|
||||
},
|
||||
error: function(data) {
|
||||
alert("'.tr('Errore').': " + data);
|
||||
|
||||
buttonRestore(btn, restore);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function importAll(btn) {
|
||||
var restore = buttonLoading(btn);
|
||||
|
||||
$.ajax({
|
||||
url: globals.rootdir + "/actions.php",
|
||||
data: {
|
||||
op: "import",
|
||||
id_module: "'.$id_module.'",
|
||||
id_plugin: "'.$id_plugin.'",
|
||||
},
|
||||
type: "post",
|
||||
success: function(data){
|
||||
data = JSON.parse(data);
|
||||
|
||||
var html = "'.tr("Le seguenti ricevute sono state considerate:").'";
|
||||
|
||||
console.log(data);
|
||||
data.forEach(function(element) {
|
||||
var text = "";
|
||||
if(element.fattura) {
|
||||
text += element.fattura;
|
||||
} else {
|
||||
text += "<i>'.tr('Ricevuta non ottenuta correttamente').'</i>";
|
||||
}
|
||||
|
||||
text += " (" + element.file + ")";
|
||||
|
||||
html += "<li>" + text + "</li>";
|
||||
});
|
||||
|
||||
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({
|
||||
title: "'.tr('Importazione completata!').'",
|
||||
html: html,
|
||||
type: "info",
|
||||
})
|
||||
|
||||
buttonRestore(btn, restore);
|
||||
},
|
||||
error: function(data) {
|
||||
alert("'.tr('Errore').': " + data);
|
||||
|
||||
buttonRestore(btn, restore);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>';
|
36
plugins/receiptFE/src/Interaction.php
Normal file
36
plugins/receiptFE/src/Interaction.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Plugins\ReceiptFE;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Plugins\ExportFE\Connection;
|
||||
|
||||
/**
|
||||
* Classe per l'interazione con API esterne.
|
||||
*
|
||||
* @since 2.4.3
|
||||
*/
|
||||
class Interaction extends Connection
|
||||
{
|
||||
public static function getReceiptList()
|
||||
{
|
||||
$response = static::request('POST', 'get_receipt_list');
|
||||
$body = static::responseBody($response)['results'];
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
public static function getReceipt($name)
|
||||
{
|
||||
$response = static::request('POST', 'get_receipt', [
|
||||
'name' => $name,
|
||||
]);
|
||||
$body = static::responseBody($response);
|
||||
|
||||
if($body['code'] != '200'){
|
||||
return false;
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
}
|
46
plugins/receiptFE/src/Ricevuta.php
Normal file
46
plugins/receiptFE/src/Ricevuta.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Plugins\ReceiptFE;
|
||||
|
||||
use Modules\Fatture\Fattura;
|
||||
use Util\XML;
|
||||
use Uploads;
|
||||
use Modules;
|
||||
use UnexpectedValueException;
|
||||
|
||||
/**
|
||||
* Classe per la gestione della fatturazione elettronica in XML.
|
||||
*
|
||||
* @since 2.4.2
|
||||
*/
|
||||
class Ricevuta
|
||||
{
|
||||
/** @var array XML della fattura */
|
||||
protected $xml = null;
|
||||
|
||||
/** @var array XML della fattura */
|
||||
protected $fattura = null;
|
||||
|
||||
public function __construct($content)
|
||||
{
|
||||
$this->xml = XML::read($content);
|
||||
|
||||
$nome = $this->xml['NomeFile'];
|
||||
$pieces = explode('_', $nome);
|
||||
|
||||
$progressivo_invio = explode('.', $pieces[1])[0];
|
||||
|
||||
$this->fattura = Fattura::where([
|
||||
'progressivo_invio' => $progressivo_invio,
|
||||
])->first();
|
||||
|
||||
if (empty($this->fattura)) {
|
||||
throw new UnexpectedValueException();
|
||||
}
|
||||
}
|
||||
|
||||
public function getFattura()
|
||||
{
|
||||
return $this->fattura;
|
||||
}
|
||||
}
|
2
update/2_4_5.sql
Normal file
2
update/2_4_5.sql
Normal file
@ -0,0 +1,2 @@
|
||||
INSERT INTO `zz_plugins` (`id`, `name`, `title`, `idmodule_from`, `idmodule_to`, `position`, `directory`, `options`) VALUES
|
||||
(NULL, 'Ricevute FE', 'Ricevute FE', (SELECT `id` FROM `zz_modules` WHERE `name`='Fatture di vendita'), (SELECT `id` FROM `zz_modules` WHERE `name`='Fatture di vendita'), 'tab_main', 'receiptFE', 'custom'),
|
Loading…
x
Reference in New Issue
Block a user