684 lines
18 KiB
PHP
Executable File
684 lines
18 KiB
PHP
Executable File
<?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/>.
|
|
*/
|
|
|
|
namespace Plugins\ExportFE;
|
|
|
|
use DateTime;
|
|
use Respect\Validation\Validator as v;
|
|
use Stringy\Stringy as S;
|
|
|
|
class Validator
|
|
{
|
|
/** @var array Elenco di campi dello standard per la formattazione e la validazione */
|
|
public static $validators = [
|
|
'IdPaese' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'IdCodice' => [
|
|
'type' => 'string',
|
|
'size' => [1, 28],
|
|
],
|
|
'ProgressivoInvio' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 10],
|
|
],
|
|
'FormatoTrasmissione' => [
|
|
'type' => 'string',
|
|
'size' => 5,
|
|
],
|
|
'CodiceDestinatario' => [
|
|
'type' => 'string',
|
|
'size' => [6, 7],
|
|
],
|
|
'Telefono' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [5, 12],
|
|
],
|
|
'Email' => [
|
|
'type' => 'string',
|
|
'size' => [7, 256],
|
|
],
|
|
'PECDestinatario' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [7, 256],
|
|
],
|
|
'CodiceFiscale' => [
|
|
'type' => 'string',
|
|
'size' => [11, 16],
|
|
],
|
|
'Denominazione' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 80],
|
|
],
|
|
'Nome' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'Cognome' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'Titolo' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [2, 10],
|
|
],
|
|
'CodEORI' => [
|
|
'type' => 'string',
|
|
'size' => [13, 17],
|
|
],
|
|
'AlboProfessionale' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'ProvinciaAlbo' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'NumeroIscrizioneAlbo' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'DataIscrizioneAlbo' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'RegimeFiscale' => [
|
|
'type' => 'string',
|
|
'size' => 4,
|
|
],
|
|
'Indirizzo' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'NumeroCivico' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 8],
|
|
],
|
|
'CAP' => [
|
|
'type' => 'string',
|
|
'size' => 5,
|
|
],
|
|
'Comune' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'Provincia' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'Nazione' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'Ufficio' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'NumeroREA' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'CapitaleSociale' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'SocioUnico' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'StatoLiquidazione' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'Fax' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [5, 12],
|
|
],
|
|
'RiferimentoAmministrazione' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'SoggettoEmittente' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'TipoDocumento' => [
|
|
'type' => 'string',
|
|
'size' => 4,
|
|
],
|
|
'Divisa' => [
|
|
'type' => 'string',
|
|
'size' => 3,
|
|
],
|
|
'Data' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'Numero' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'TipoRitenuta' => [
|
|
'type' => 'string',
|
|
'size' => 4,
|
|
],
|
|
'ImportoRitenuta' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'AliquotaRitenuta' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 6],
|
|
],
|
|
'CausalePagamento' => [
|
|
'type' => 'string',
|
|
'size' => [1, 2],
|
|
],
|
|
'BolloVirtuale' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'ImportoBollo' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'TipoCassa' => [
|
|
'type' => 'string',
|
|
'size' => 4,
|
|
],
|
|
'AlCassa' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 6],
|
|
],
|
|
'ImportoContributoCassa' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'ImponibileCassa' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'AliquotaIVA' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 6],
|
|
],
|
|
'Ritenuta' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'Natura' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'Tipo' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'Percentuale' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 6],
|
|
],
|
|
'Importo' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'ImportoTotaleDocumento' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'Arrotondamento' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 21],
|
|
],
|
|
'Causale' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 200],
|
|
],
|
|
'Art73' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'RiferimentoNumeroLinea' => [
|
|
'type' => 'integer',
|
|
'size' => [1, 4],
|
|
],
|
|
'IdDocumento' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'NumItem' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'CodiceCommessaConvenzione' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 100],
|
|
],
|
|
'CodiceCUP' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 15],
|
|
],
|
|
'CodiceCIG' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 15],
|
|
],
|
|
'RiferimentoFase' => [
|
|
'type' => 'integer',
|
|
'size' => [1, 3],
|
|
],
|
|
'NumeroDDT' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'DataDDT' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'NumeroLicenzaGuida' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'MezzoTrasporto' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 80],
|
|
],
|
|
'CausaleTrasporto' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 100],
|
|
],
|
|
'NumeroColli' => [
|
|
'type' => 'integer',
|
|
'size' => [1, 4],
|
|
],
|
|
'Descrizione' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 1000],
|
|
],
|
|
'UnitaMisuraPeso' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 10],
|
|
],
|
|
'PesoLordo' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 7],
|
|
],
|
|
'PesoNetto' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 7],
|
|
],
|
|
'DataOraRitiro' => [
|
|
'type' => 'date',
|
|
'size' => 19,
|
|
],
|
|
'DataInizioTrasporto' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'TipoResa' => [
|
|
'type' => 'string',
|
|
'size' => 3,
|
|
],
|
|
'DataOraConsegna' => [
|
|
'type' => 'date',
|
|
'size' => 19,
|
|
],
|
|
'NumeroFatturaPrincipale' => [
|
|
'type' => 'string',
|
|
'size' => [1, 20],
|
|
],
|
|
'DataFatturaPrincipale' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'NumeroLinea' => [
|
|
'type' => 'integer',
|
|
'size' => [1, 4],
|
|
],
|
|
'TipoCessionePrestazione' => [
|
|
'type' => 'string',
|
|
'size' => 2,
|
|
],
|
|
'CodiceArticolo' => [
|
|
'type' => 'normalizedString',
|
|
],
|
|
'CodiceTipo' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 35],
|
|
],
|
|
'CodiceValore' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 35],
|
|
],
|
|
'Quantita' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 21],
|
|
],
|
|
'UnitaMisura' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 10],
|
|
],
|
|
'DataInizioPeriodo' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'DataFinePeriodo' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'PrezzoUnitario' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 21],
|
|
],
|
|
'PrezzoTotale' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 21],
|
|
],
|
|
'TipoDato' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 10],
|
|
],
|
|
'RiferimentoTesto' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'RiferimentoNumero' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 21],
|
|
],
|
|
'RiferimentoData' => [
|
|
'type' => 'normalizedString',
|
|
'size' => 10,
|
|
],
|
|
'SpeseAccessorie' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'ImponibileImporto' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'Imposta' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'EsigibilitaIVA' => [
|
|
'type' => 'string',
|
|
'size' => 1,
|
|
],
|
|
'RiferimentoNormativo' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 100],
|
|
],
|
|
'TotalePercorso' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 15],
|
|
],
|
|
'CondizioniPagamento' => [
|
|
'type' => 'string',
|
|
'size' => 4,
|
|
],
|
|
'Beneficiario' => [
|
|
'type' => 'string',
|
|
'size' => [1, 200],
|
|
],
|
|
'ModalitaPagamento' => [
|
|
'type' => 'string',
|
|
'size' => 4,
|
|
],
|
|
'DataRiferimentoTerminiPagamento' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'GiorniTerminiPagamento' => [
|
|
'type' => 'integer',
|
|
'size' => [1, 3],
|
|
],
|
|
'DataScadenzaPagamento' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'ImportoPagamento' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'CodUfficioPostale' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 20],
|
|
],
|
|
'CognomeQuietanzante' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'NomeQuietanzante' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'CFQuietanzante' => [
|
|
'type' => 'string',
|
|
'size' => 16,
|
|
],
|
|
'TitoloQuietanzante' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [2, 10],
|
|
],
|
|
'IstitutoFinanziario' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 80],
|
|
],
|
|
'IBAN' => [
|
|
'type' => 'string',
|
|
'size' => [15, 34],
|
|
],
|
|
'ABI' => [
|
|
'type' => 'string',
|
|
'size' => 5,
|
|
],
|
|
'CAB' => [
|
|
'type' => 'string',
|
|
'size' => 5,
|
|
],
|
|
'BIC' => [
|
|
'type' => 'string',
|
|
'size' => [8, 11],
|
|
],
|
|
'ScontoPagamentoAnticipato' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'DataLimitePagamentoAnticipato' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'PenalitaPagamentiRitardati' => [
|
|
'type' => 'decimal',
|
|
'size' => [4, 15],
|
|
],
|
|
'DataDecorrenzaPenale' => [
|
|
'type' => 'date',
|
|
'size' => 10,
|
|
],
|
|
'CodicePagamento' => [
|
|
'type' => 'string',
|
|
'size' => [1, 60],
|
|
],
|
|
'NomeAttachment' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 60],
|
|
],
|
|
'AlgoritmoCompressione' => [
|
|
'type' => 'string',
|
|
'size' => [1, 10],
|
|
],
|
|
'FormatoAttachment' => [
|
|
'type' => 'string',
|
|
'size' => [1, 10],
|
|
],
|
|
'DescrizioneAttachment' => [
|
|
'type' => 'normalizedString',
|
|
'size' => [1, 100],
|
|
],
|
|
'Attachment' => [
|
|
'type' => 'base64Binary',
|
|
],
|
|
];
|
|
|
|
/** @var array Irregolarità nella fattura XML */
|
|
protected $errors = null;
|
|
|
|
/** @var string XML da validare */
|
|
protected $xml = null;
|
|
|
|
public function __construct($xml)
|
|
{
|
|
$this->xml = $xml;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getErrors()
|
|
{
|
|
if (!isset($this->errors)) {
|
|
$this->validate();
|
|
}
|
|
|
|
return $this->errors;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function isValid()
|
|
{
|
|
return empty($this->getErrors());
|
|
}
|
|
|
|
/**
|
|
* Restituisce lo stato di validazione interna dell'XML della fattura.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function validate()
|
|
{
|
|
$this->errors = [];
|
|
|
|
return $this->prepareForXML($this->xml);
|
|
}
|
|
|
|
/**
|
|
* Prepara i contenuti per la generazione dell'XML della fattura.
|
|
* Effettua inoltre dei controlli interni di validità sui campi previsti dallo standard.
|
|
*
|
|
* @param mixed $input
|
|
* @param string $key
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function prepareForXML($input, $key = null)
|
|
{
|
|
$output = null;
|
|
if (is_array($input)) {
|
|
foreach ($input as $key => $value) {
|
|
$output[$key] = $this->prepareForXML($value, $key);
|
|
}
|
|
} elseif (!is_null($input)) {
|
|
$info = static::$validators[$key];
|
|
$size = isset($info['size']) ? $info['size'] : null;
|
|
|
|
$output = $input;
|
|
|
|
// Operazioni di normalizzazione
|
|
// Formattazione decimali
|
|
if ($info['type'] == 'decimal') {
|
|
if (in_array($key, ['PrezzoUnitario'])) {
|
|
$output = number_format($output, 6, '.', '');
|
|
} elseif (in_array($key, ['Quantita'])) {
|
|
//Se i decimali per la quantità sono < 2 li imposto a 2 che è il minimo per lo standard della fatturazione elettronica
|
|
if (setting('Cifre decimali per quantità') == 1) {
|
|
$output = number_format($output, 2, '.', '');
|
|
} else {
|
|
$output = number_format($output, setting('Cifre decimali per quantità'), '.', '');
|
|
}
|
|
} else {
|
|
$output = number_format($output, 2, '.', '');
|
|
}
|
|
}
|
|
|
|
// Formattazione date
|
|
elseif ($info['type'] == 'date') {
|
|
$object = DateTime::createFromFormat('Y-m-d H:i:s', $output);
|
|
if (is_object($object)) {
|
|
$output = $object->format('Y-m-d');
|
|
}
|
|
}
|
|
|
|
// Formattazione testo
|
|
elseif ($info['type'] == 'string' || $info['type'] == 'normalizedString') {
|
|
$output = replace(html_entity_decode($output), [
|
|
'&' => '&',
|
|
'"' => '"',
|
|
"'" => ''',
|
|
'<' => '<',
|
|
'>' => '>',
|
|
|
|
// Caratteri personalizzati
|
|
'€' => 'euro',
|
|
'—' => '-',
|
|
'…' => '...',
|
|
]);
|
|
|
|
$output = preg_replace('/[^ -~òèéàùì°]+/', ' ', $output);
|
|
}
|
|
|
|
// Riduzione delle dimensioni
|
|
if ($info['type'] != 'integer' && isset($size[1])) {
|
|
$output = trim($output);
|
|
$output = S::create($output)->substr(0, $size[1])->__toString();
|
|
}
|
|
|
|
// Validazione
|
|
if ($info['type'] == 'string' || $info['type'] == 'normalizedString') {
|
|
$validator = v::stringType();
|
|
|
|
if (isset($size[1])) {
|
|
$validator = $validator->length($size[0], $size[1]);
|
|
}
|
|
} elseif ($info['type'] == 'decimal') {
|
|
$validator = v::floatVal();
|
|
} elseif ($info['type'] == 'integer') {
|
|
$validator = v::intVal();
|
|
} elseif ($info['type'] == 'date') {
|
|
$validator = v::date();
|
|
}
|
|
|
|
if (!empty($validator)) {
|
|
$validation = $validator->validate($output);
|
|
|
|
// Segnalazione dell'irregolarità
|
|
if (!intval($validation)) {
|
|
$this->errors[] = $key;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $output;
|
|
}
|
|
}
|