openstamanager/plugins/exportFE/src/Validator.php

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), [
'&' => '&amp;',
'"' => '&quot;',
"'" => '&apos;',
'<' => '&lt;',
'>' => '&gt;',
// Caratteri personalizzati
'€' => 'euro',
'—' => '-',
'…' => '...',
]);
$output = preg_replace('/[[:^print:]]/', ' ', $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;
}
}