Skip to content

Commit

Permalink
WIP #7
Browse files Browse the repository at this point in the history
- test that JSON files converted via PHP validate against the JSON schema

other changes:
- supply malformed / incomplete test XML files
- turn Xml2Json into a PHP class
- add PHP unit tests with PHPunit
- add PHP json validation script using `justinrainbow/json-schema`
- add Test and Contributing sections in README
- lint js, PHP & sh
- add `bin/validate_xml.sh` script
- update JSON schema to require NumeroColli, NumeroLinea, Numero
  • Loading branch information
Paolo Greppi committed Jul 3, 2018
1 parent 4d4e150 commit 60680f1
Show file tree
Hide file tree
Showing 36 changed files with 2,476 additions and 99 deletions.
36 changes: 30 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Poiché per lo sviluppo di API ed SDK è più comodo manipolare i dati in format
## Prerequisiti

```
sudo apt install make nodejs yarnpkg php-cli libxml2-utils composer
sudo apt install make nodejs yarnpkg php-cli libxml2-utils composer phpunit shellcheck
yarnpkg install
composer install
```
Expand All @@ -35,8 +35,6 @@ Innanzitutto lo [schema XML (*XSD**)](https://en.wikipedia.org/wiki/XML_Schema_(
+ <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd"/>
```

Quindi i files XML di esempio tratti dal sito `fatturapa.gov.it` sono stati validati con questo schema così modificato (script [`bin/validate_samples.sh`](bin/validate_samples.sh)).

Le fatture in formato JSON possono essere validate per mezzo di un **JSON schema** (vedi [paragrafo Riferimenti](#riferimenti)), anche se quest'ultimo è più limitato dello schema XML, alcuni vincoli dovranno essere validati dall'applicazione, ad esempio:

- limitazioni ai **set di caratteri ammessi**: ad esempio il campo `FatturaElettronica.FatturaElettronicaHeader.DatiTrasmissione.ProgressivoInvio` secondo lo schema XML è vincolato al tipo `String10Type` così definito:
Expand Down Expand Up @@ -69,7 +67,7 @@ nodejs ./node_modules/jgexml/testxsd2j.js Schema_del_file_xml_FatturaPA_versione
```
ottenendo però uno schema non utilizzabile.
Successivamente i files XML di esempio sono stati convertiti a JSON per mezzo della libreria [node-xml2json](https://github.com/buglabs/node-xml2json) (script [`bin/convert_samples.sh`](bin/convert_samples.sh)).
Successivamente i files XML di esempio sono stati convertiti a JSON per mezzo della libreria javascript [node-xml2json](https://github.com/buglabs/node-xml2json) (script [`bin/convert_samples.sh`](bin/convert_samples.sh)).
La liberia xml2json [non è supportata nel browser](https://github.com/buglabs/node-xml2json/issues/97) quindi per i client la conversione va fatta server side con lo script PHP [`www/xml2json.php`](www/xml2json.php), ad esempio:
```
Expand All @@ -78,15 +76,41 @@ curl -X POST -F 'xml=@samples/IT01234567890_FPA01.xml' http://localhost:8000/xml
Si è quindi generato uno schema a partire dai files fattura JSON di esempio, per mezzo del servizio on-line [jsonschema.net](https://www.jsonschema.net/), che dopo semplificazione (`grep -v '$id'`) e aggiustamento manuale aggiunta di campi `title` e `description` desunti dalle SPECIFICHE TECNICHE OPERATIVE DEL FORMATO DELLA FATTURA DEL SISTEMA DI INTERSCAMBIO ha dato origine allo schema [`fatturaPA_1.2_schema.json`](fatturaPA_1.2_schema.json).
Tutti i files di esempio JSON sono validati dallo schema (script [`bin/validate_samples_json.sh`](bin/validate_samples_json.sh)).
La generazione di files XML random a scopo di test è possibile con alcuni strumenti commerciali, ad esempio:
- https://msdn.microsoft.com/en-us/library/aa302296.aspx "Generating XML Documents from XML Schemas" Priya Lakshminarayanan, Microsoft Corporation - August 2004
- https://msdn.microsoft.com/en-us/library/dd489258.aspx "How to: Create an XML Document Based on an XSD Schema Visual Studio 2015"
- https://msdn.microsoft.com/en-us/library/cc716766.aspx "XML Schema Explorer"
In questo proof-of-concept si è scelto di generare dei files JSON random partendo dallo schema JSON per mezzo di [json-schema-faker](https://github.com/json-schema-faker/json-schema-faker), e di riconvertirli a XML per mezzo del template [handlebars](http://handlebarsjs.com/) [`fatturaPA_1.2.hbs`](fatturaPA_1.2.hbs) (script [`bin/generate_random.sh`](bin/generate_random.sh)).
## Contributing
Check your changes with:
```
# lint javascript
./node_modules/jshint/bin/jshint --extract=auto www/index.html
./node_modules/jshint/bin/jshint bin/*.js
# lint shell scripts
shellcheck bin/*.sh
# lint PHP
./vendor/bin/phpcs --standard=PSR2 tests/*.php
./vendor/bin/phpcs --standard=PSR2 www/*.php
./vendor/bin/phpcs --standard=PSR2 bin/*.php
```
You **must** use the [git-flow workflow](https://danielkummer.github.io/git-flow-cheatsheet/)
## Test
I files XML di esempio tratti dal sito `fatturapa.gov.it` sono stati validati con lo schema XML modificato (script [`bin/validate_samples_xml.sh`](bin/validate_samples_xml.sh)).
Tutti i files di esempio XML convertiti a JSON per mezzo della libreria javascript node-xml2json sono stati validati con lo schema JSON sia col validatore javascript che col validatore PHP (script [`bin/validate_samples_json.sh`](bin/validate_samples_json.sh)).
Test della classe PHP `Xml2Json`:
```
phpunit --testdox tests
```
Il template handlebars è stato validato riconvertendo ad XML i files di esempio (script [`bin/reconvert_samples.sh`](bin/reconvert_samples.sh)).
## Demo
Expand Down
2 changes: 1 addition & 1 deletion bin/generate_random.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ do
echo "generating $name.json"
bin/fake.js > "random/$name.json"
echo "validate $name.json"
bin/validate.js "random/$name.json"
bin/validate_json.js "random/$name.json"
echo "convert to $name.xml"
bin/hbs.js "random/$name.json" > "random/$name.xml"
# echo "validate $name.xml"
Expand Down
File renamed without changes.
27 changes: 27 additions & 0 deletions bin/validate_json.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/php
<?php
// validates the supplied JSON invoice file against the JSON invoice schema
//
// Copyright (c) 2018, Paolo Greppi <[email protected]>
// License: BSD 3-Clause

require_once './vendor/autoload.php';

if (count($argv) <= 1) {
echo "Usage: validate.php file.json\n";
exit(-1);
}

$filename = $argv[1];
$data = json_decode(file_get_contents($filename));
$validator = new JsonSchema\Validator;
$validator->validate($data, (object)['$ref' => 'file://' . realpath('fatturaPA_1.2_schema.json')]);

if ($validator->isValid()) {
echo "The supplied JSON validates against the schema.\n";
} else {
echo "JSON does not validate. Violations:\n";
foreach ($validator->getErrors() as $error) {
echo sprintf("[%s] %s\n", $error['property'], $error['message']);
}
}
6 changes: 4 additions & 2 deletions bin/validate_samples_json.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ set -e

for name in "samples/IT01234567890_FPA01.json" "samples/IT01234567890_FPA02.json" "samples/IT01234567890_FPA03.json" "samples/IT01234567890_FPR01.json" "samples/IT01234567890_FPR02.json" "samples/IT01234567890_FPR03.json"
do
echo "validating $name"
./bin/validate.js "$name"
echo "validating $name with javascript"
./bin/validate_json.js "$name"
echo "validating $name with PHP"
./bin/validate_json.php "$name"
done
2 changes: 1 addition & 1 deletion bin/validate_samples.sh → bin/validate_samples_xml.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ set -e
for name in "samples/IT01234567890_FPA01.xml" "samples/IT01234567890_FPA02.xml" "samples/IT01234567890_FPA03.xml" "samples/IT01234567890_FPR01.xml" "samples/IT01234567890_FPR02.xml" "samples/IT01234567890_FPR03.xml"
do
echo "validating $name"
xmllint --debug --schema Schema_del_file_xml_FatturaPA_versione_1.2_cleanup.xsd "$name" -noout
./bin/validate_xml.sh "$name"
done
10 changes: 10 additions & 0 deletions bin/validate_xml.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh
#
# validates against the XML invoice schema the supplied XML invoice file
#
# Copyright (c) 2018, Paolo Greppi <[email protected]>
# License: BSD 3-Clause

set -e

xmllint --debug --schema Schema_del_file_xml_FatturaPA_versione_1.2_cleanup.xsd "$1" -noout
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"require": {
"squizlabs/php_codesniffer": "*"
"squizlabs/php_codesniffer": "*",
"justinrainbow/json-schema": "^5.2"
}
}
68 changes: 67 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 18 additions & 27 deletions fatturaPA_1.2_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -806,9 +806,8 @@
"maxLength": 100
},
"NumeroColli": {
"type": "integer",
"minimum": 1,
"maximum": 9999
"type": "string",
"pattern": "^[0-9]{1,4}$"
},
"Descrizione": {
"type": "string",
Expand Down Expand Up @@ -967,9 +966,8 @@
"type": "array",
"title": "Numero identificativo della linea di dettaglio ",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 9999,
"type": "string",
"pattern": "^[0-9]{1,4}$",
"default": "",
"examples": [
1
Expand Down Expand Up @@ -1026,9 +1024,8 @@
"type": "array",
"title": "Numero identificativo della linea di dettaglio ",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 9999,
"type": "string",
"pattern": "^[0-9]{1,4}$",
"default": "",
"examples": [
1
Expand Down Expand Up @@ -1085,9 +1082,8 @@
"type": "array",
"title": "Numero identificativo della linea di dettaglio ",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 9999,
"type": "string",
"pattern": "^[0-9]{1,4}$",
"default": "",
"examples": [
1
Expand Down Expand Up @@ -1144,9 +1140,8 @@
"type": "array",
"title": "Numero identificativo della linea di dettaglio ",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 9999,
"type": "string",
"pattern": "^[0-9]{1,4}$",
"default": "",
"examples": [
1
Expand Down Expand Up @@ -1203,9 +1198,8 @@
"type": "array",
"title": "Numero identificativo della linea di dettaglio ",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 9999,
"type": "string",
"pattern": "^[0-9]{1,4}$",
"default": "",
"examples": [
1
Expand Down Expand Up @@ -1254,9 +1248,8 @@
"type":"object",
"properties": {
"RiferimentoFase": {
"type": "integer",
"minimum": 1,
"maximum": 999,
"type": "string",
"pattern": "^[0-9]{1-3}$",
"title": "Fase dello stato avanzamento cui la fattura si riferisce",
"default": "",
"examples": [
Expand Down Expand Up @@ -1293,9 +1286,8 @@
"title": "Numero della linea o delle linee di dettaglio della fattura alle quali si riferisce il DDT (così come identificato dagli elementi NumeroDDT e DataDDT)",
"description": "nel caso in cui il documento di trasporto si riferisce all’intera fattura, questo elemento non deve essere valorizzato",
"items": {
"type": "integer",
"minimum": 1,
"maximum": 9999,
"type": "string",
"pattern": "^[0-9]{1,4}$",
"default": "",
"examples": [
1
Expand All @@ -1320,9 +1312,8 @@
"type": "object",
"properties": {
"NumeroLinea": {
"type": "integer",
"minimum": 1,
"maximum": 9999,
"type": "string",
"pattern": "^[0-9]{1,4}$",
"title": "Numero identificativo della linea di dettaglio ",
"default": "",
"examples": [
Expand Down
Loading

0 comments on commit 60680f1

Please sign in to comment.