E-INVOICE extract all documents from XML and store in DB
This commit is contained in:
parent
9db299594d
commit
35d73582b0
7 changed files with 288 additions and 96 deletions
90
include/XMLDocument/document_reference_type.class.php
Normal file
90
include/XMLDocument/document_reference_type.class.php
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
namespace Noalyss\XMLDocument;
|
||||
|
||||
/*
|
||||
* This file is part of NOALYSS.
|
||||
*
|
||||
* NOALYSS 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NOALYSS 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 NOALYSS; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
// Copyright Author Dany De Bontridder danydb@aevalys.eu 22/10/23
|
||||
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Document Reference Type ; documents included in a UBL21
|
||||
* xml
|
||||
*/
|
||||
class Binary_Object
|
||||
{
|
||||
public $filecontent;
|
||||
public $mimecode;
|
||||
public $filename;
|
||||
function __toString(): string
|
||||
{
|
||||
return "Binary_Object[filecontent=" . $this->filecontent
|
||||
. ", mimecode=" . $this->mimecode
|
||||
. ", filename=" . $this->filename
|
||||
. "]";
|
||||
}
|
||||
}
|
||||
|
||||
class Document_Reference
|
||||
{
|
||||
protected $id;
|
||||
protected $description;
|
||||
protected Binary_Object $binary_object;
|
||||
function __toString(): string
|
||||
{
|
||||
return "Document_Reference[id=" . $this->id
|
||||
. ", description=" . $this->description
|
||||
. ", binary_object=" . $this->binary_object
|
||||
. "]";
|
||||
}
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function getBinary_object(): Binary_Object
|
||||
{
|
||||
return $this->binary_object;
|
||||
}
|
||||
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBinary_object(Binary_Object $binary_object)
|
||||
{
|
||||
$this->binary_object = $binary_object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -86,6 +86,14 @@ class InvoiceUBL21 extends XMLInvoice {
|
|||
/**
|
||||
* check that PEPPOL ID is valid
|
||||
*/
|
||||
if ( isset($company['COMPANY_UBL_ID']))
|
||||
{
|
||||
if ( strpos($company['COMPANY_UBL_ID'],':') == 0 )
|
||||
{
|
||||
$a_error[]="COMPANY_UBL_ID";
|
||||
}
|
||||
|
||||
}
|
||||
return $a_error;
|
||||
}
|
||||
/**
|
||||
|
|
@ -107,7 +115,7 @@ class InvoiceUBL21 extends XMLInvoice {
|
|||
$a_error[]=$value;
|
||||
}
|
||||
}
|
||||
if ( $this->data['customer'][ATTR_DEF_PEPPOLID] != "")
|
||||
if ( $this->data['customer']["endpoint_id"] != "")
|
||||
{
|
||||
// check if peppol id has the form 9999:9999...
|
||||
list($scheme_id,$peppol)=explode(":", $this->data['customer'][$value]);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ class XMLInvoice_Reader
|
|||
{
|
||||
$this->domDocument = $domDocument;
|
||||
$this->xpath = new \DOMXPath($this->domDocument);
|
||||
$this->xpath->registerNamespace("ns4", 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2');
|
||||
$this->xpath->registerNamespace("cac", 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2');
|
||||
$this->xpath->registerNamespace("cbc", 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -136,35 +139,53 @@ class XMLInvoice_Reader
|
|||
/**
|
||||
* @brief returns the embedded document in an array (keys : filecontent (BYTES),mimecode , filename)
|
||||
* or false if there is no document
|
||||
* @return bool|array keys : filecontent (BYTES),mimecode , filename)
|
||||
* or false if there is no document
|
||||
* @return bool|array of array : filecontent (BYTES),mimecode , filename)
|
||||
* @throws \Exception if there are several documents
|
||||
*
|
||||
*/
|
||||
public function get_embedded_document()
|
||||
{
|
||||
if (($node = $this->get_node("//cac:AdditionalDocumentReference")) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ($node->length > 1)
|
||||
{
|
||||
throw new \Exception("XR110 Too many documents found", 110);
|
||||
}
|
||||
///@var DOMNodeList $data //cac:AdditionalDocumentReference[1]/cac:Attachment[1]/cbc:EmbeddedDocumentBinaryObject[1]
|
||||
if (
|
||||
($data = $this->get_node("//cac:AdditionalDocumentReference[1]/cac:Attachment[1]/cbc:EmbeddedDocumentBinaryObject[1]")) == null
|
||||
$a_document_reference=array();
|
||||
foreach (array(
|
||||
"AdditionalDocumentReference",
|
||||
"ReceiptDocumentReference",
|
||||
"StatementDocumentReference",
|
||||
"OriginatorDocumentReference",
|
||||
"ContractDocumentReference"
|
||||
)
|
||||
as $document)
|
||||
{
|
||||
$document=$this->domDocument->getElementsByTagName($document);
|
||||
if ( $document->length == 0 ) {
|
||||
continue;
|
||||
}
|
||||
for ($e=0;$e < $document->count();$e++)
|
||||
{
|
||||
$item=$document->item($e);
|
||||
|
||||
if ( $item->nodeType == XML_ELEMENT_NODE )
|
||||
{
|
||||
$id=$item->getElementsByTagName("ID")[0]?->nodeValue;
|
||||
$description=$item->getElementsByTagName("DocumentDescription")[0]?->nodeValue;
|
||||
$embedded_document=$item->getElementsByTagName("EmbeddedDocumentBinaryObject");
|
||||
if ( $embedded_document->length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$binary_object=new Binary_Object;
|
||||
$binary_object->filecontent=base64_decode($embedded_document[0]->nodeValue);
|
||||
$binary_object->mimecode=$embedded_document[0]->getAttribute("mimeCode");
|
||||
$binary_object->filename=$embedded_document[0]->getAttribute("filename");
|
||||
$document_reference=new Document_Reference();
|
||||
$document_reference->setId($id)
|
||||
->setDescription($description)
|
||||
->setBinary_object($binary_object);
|
||||
$a_document_reference[]=clone $document_reference;
|
||||
}
|
||||
}
|
||||
|
||||
throw new \Exception("X116 Document corrupted", 116);
|
||||
}
|
||||
$filecontent = base64_decode($data->item(0)->nodeValue);
|
||||
$mimecode = $data->item(0)->getAttribute("mimeCode");
|
||||
$filename = $data->item(0)->getAttribute("filename");
|
||||
return array("filecontent" => $filecontent,
|
||||
"mimecode" => $mimecode,
|
||||
"filename" => $filename);
|
||||
return $a_document_reference;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,6 +213,7 @@ class XMLInvoice_Reader
|
|||
$result['postcode'] = $this->get_node_value('//cac:AccountingCustomerParty[1]/cac:Party[1]/cac:PostalAddress[1]/cbc:PostalZone[1]');
|
||||
$result['country_code'] = $this->get_node_value("//cac:AccountingCustomerParty[1]/cac:Party[1]/cac:PostalAddress[1]/cac:Country[1]/cbc:IdentificationCode[1]");
|
||||
$result['company_id'] = $this->get_node_value("//cac:AccountingCustomerParty[1]/cac:Party[1]/cac:PartyTaxScheme[1]/cbc:CompanyID[1]");
|
||||
$result['scheme']=$this->get_node("//cac:AccountingCustomerParty[1]/cac:Party[1]/cbc:EndpointID[1]")[0]->getAttribute("schemeID");
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
@ -209,6 +231,7 @@ class XMLInvoice_Reader
|
|||
$result['postcode'] = $this->get_node_value("//cac:AccountingSupplierParty[1]/cac:Party[1]/cac:PostalAddress[1]/cbc:PostalZone[1]");
|
||||
$result['country_code'] = $this->get_node_value("//cac:AccountingSupplierParty[1]/cac:Party[1]/cac:PostalAddress[1]/cac:Country[1]/cbc:IdentificationCode[1]");
|
||||
$result['company_id'] = $this->get_node_value("//cac:AccountingSupplierParty[1]/cac:Party[1]/cac:PartyTaxScheme[1]/cbc:CompanyID[1]");
|
||||
$result['scheme']=$this->get_node("//cac:AccountingSupplierParty[1]/cac:Party[1]/cbc:EndpointID[1]")[0]->getAttribute("schemeID");
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -320,70 +320,55 @@ class Acc_Document extends Document {
|
|||
//,mimecode mimetype and filename (string)
|
||||
try
|
||||
{
|
||||
$embedded_file=$xmlreader->get_embedded_document();
|
||||
if ($embedded_file == false)
|
||||
{
|
||||
$embedded_file=array();
|
||||
// create a PDF with standard information
|
||||
$pdf=$xmlreader->to_pdf($this->db);
|
||||
$file_oid=$this->db->lo_write($pdf->Output("S"));
|
||||
$embedded_file['filename']="invoice.pdf";
|
||||
$embedded_file['mimecode']="application/pdf";
|
||||
}
|
||||
else
|
||||
{
|
||||
$file_oid=$this->db->lo_write($embedded_file['filecontent']);
|
||||
if ( $file_oid == false )
|
||||
{
|
||||
// create a PDF with standard information
|
||||
$pdf=$xmlreader->to_pdf($this->db);
|
||||
$file_oid=$this->db->lo_write($pdf->Output("S"));
|
||||
}
|
||||
}
|
||||
|
||||
// create a PDF with standard information
|
||||
$pdf=$xmlreader->to_pdf($this->db);
|
||||
$file_oid=$this->db->lo_write($pdf->Output("S"));
|
||||
|
||||
//@var $file_oid OID of the large object saved in DB
|
||||
$this->d_name="invoice.pdf";
|
||||
$this->d_description="Auto generated invoice";
|
||||
$this->d_lob=$file_oid;
|
||||
$this->d_mimetype="application/pdf";
|
||||
|
||||
// save extracted document into DB
|
||||
$this->db->exec_sql("update jrn set jr_pj=$1 , jr_pj_name=$2,
|
||||
jr_pj_type=$3 where jr_id=$4",
|
||||
array(
|
||||
$this->d_lob
|
||||
, $this->d_name
|
||||
, $this->d_description
|
||||
, $this->d_id
|
||||
)
|
||||
);
|
||||
// save all the documents into the DB
|
||||
// @var embedded_file (array of Noalyss\XML\Document_Reference)
|
||||
$embedded_file=$xmlreader->get_embedded_document();
|
||||
$nb_file = count($embedded_file);
|
||||
for ($i=0;$i <$nb_file ; $i++)
|
||||
{
|
||||
// other documents save in jrn_sup_document
|
||||
// @var $file (Binary File from XML)
|
||||
$binary=$embedded_file[$i]->getBinary_object();
|
||||
|
||||
//@var $sup_oid : oid of the supplemental
|
||||
$sup_oid=$this->db->lo_write($binary->filecontent);
|
||||
|
||||
$jrn_sup_document=new Jrn_Sup_Document_SQL($this->db);
|
||||
$jrn_sup_document->jr_id=$this->d_id;
|
||||
$jrn_sup_document->js_mimetype=$binary->mimecode;
|
||||
$jrn_sup_document->js_filename=$binary->filename;
|
||||
$jrn_sup_document->js_lob=$sup_oid;
|
||||
$jrn_sup_document->js_description=$embedded_file[$i]->getDescription();
|
||||
$jrn_sup_document->js_cbc_id=$embedded_file[$i]->getId();
|
||||
$jrn_sup_document->save();
|
||||
}
|
||||
|
||||
$this->d_name=$embedded_file['filename'];
|
||||
$this->d_description=$embedded_file['filename'];
|
||||
$this->d_lob=$file_oid;
|
||||
$this->d_mimetype=$embedded_file['mimecode'];
|
||||
// save extracted document into DB
|
||||
$this->db->exec_sql("update jrn set jr_pj=$1 , jr_pj_name=$2,
|
||||
jr_pj_type=$3 where jr_id=$4",
|
||||
array(
|
||||
$this->d_lob
|
||||
, $this->d_name
|
||||
, $this->d_description
|
||||
, $this->d_id
|
||||
)
|
||||
);
|
||||
return $file_oid;
|
||||
} catch (\Exception $e ) {
|
||||
\record_log($e);
|
||||
// if exception is not too many document or document corrupted
|
||||
// then rethrow the exception
|
||||
if ( !in_array(e->getCode(),[110,116]) )
|
||||
{
|
||||
throw new \Exception("X281 ",281,$e);
|
||||
}
|
||||
throw new \Exception("X281 ",281,$e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// save new document
|
||||
$this->db->exec_sql("update jrn set jr_pj=$1 , jr_pj_name=$2,
|
||||
jr_pj_type=$3 where jr_id=$4",
|
||||
array(
|
||||
$oid
|
||||
, $_FILES['pj']['name']
|
||||
, $_FILES['pj']['type']
|
||||
, $this->d_id
|
||||
)
|
||||
);
|
||||
$this->d_name=$_FILES['pj']['name'];
|
||||
$this->d_description=$_FILES['pj']['name'];
|
||||
$this->d_lob=$oid;
|
||||
$this->d_mimetype=$_FILES['pj']['type'];
|
||||
$this->db->commit();
|
||||
|
||||
return $oid;
|
||||
|
|
|
|||
|
|
@ -441,7 +441,9 @@ function noalyss_class_autoloader($class)
|
|||
'noalyss\xmldocument\xmlinvoice_reader'=>'XMLDocument/xmlinvoice_reader.class.php',
|
||||
'noalyss\mail_parameter'=>'lib/mail_parameter.class.php',
|
||||
'noalyss\smtpmail'=>'lib/smtpmail.class.php',
|
||||
'noalyss\iban_number'=>'lib/iban_number.class.php'
|
||||
'noalyss\iban_number'=>'lib/iban_number.class.php',
|
||||
'noalyss\xmldocument\document_reference'=>'XMLDocument/document_reference_type.class.php',
|
||||
'noalyss\xmldocument\binary_object'=>'XMLDocument/document_reference_type.class.php'
|
||||
);
|
||||
if (isset ($aClass[$class])) {
|
||||
require_once NOALYSS_INCLUDE . "/" . $aClass[$class];
|
||||
|
|
|
|||
71
include/database/jrn_sup_document_sql.class.php
Normal file
71
include/database/jrn_sup_document_sql.class.php
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Autogenerated file
|
||||
* This file is part of NOALYSS.
|
||||
*
|
||||
* NOALYSS 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NOALYSS 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 NOALYSS; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
require_once NOALYSS_INCLUDE . '/lib/data_sql.class.php';
|
||||
require_once NOALYSS_INCLUDE . '/class/database.class.php';
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief abstract of the table public.jrn_sup_document
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class Jrn_Sup_Document_SQL
|
||||
* @brief abstract of the table public.jrn_sup_document
|
||||
*/
|
||||
class Jrn_Sup_Document_SQL extends \Table_Data_SQL
|
||||
{
|
||||
|
||||
function __construct(Database $p_cn, $p_id = -1)
|
||||
{
|
||||
$this->table = "public.jrn_sup_document";
|
||||
$this->primary_key = "js_id";
|
||||
/*
|
||||
* List of columns
|
||||
*/
|
||||
$this->name = array(
|
||||
"js_id" => "js_id"
|
||||
, "js_mimetype" => "js_mimetype"
|
||||
, "js_lob" => "js_lob"
|
||||
, "jr_id" => "jr_id"
|
||||
,'js_filename'=>'js_filename'
|
||||
,'js_description'=>'js_description'
|
||||
,'js_cbc_id'=>'js_cbc_id'
|
||||
);
|
||||
|
||||
/*
|
||||
* Type of columns
|
||||
*/
|
||||
$this->type = array(
|
||||
"js_id" => "numeric"
|
||||
, "js_mimetype" => "text"
|
||||
, "js_lob" => "oid"
|
||||
, "jr_id" => "numeric"
|
||||
,'js_filename'=>'text'
|
||||
,'js_description'=>'text'
|
||||
,'js_cbc_id'=>'text'
|
||||
);
|
||||
|
||||
$this->default = array("js_id" => "auto");
|
||||
|
||||
$this->date_format = "DD.MM.YYYY";
|
||||
parent::__construct($p_cn, $p_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -233,7 +233,7 @@ insert into parameter_extra(pe_code,pe_label) values ('COMPANY_LEGAL_REGISTRATIO
|
|||
insert into parameter_extra(pe_code,pe_label) values ('COMPANY_LEGAL_ENTITY','Forme légal de la société (SRL,ASBL,AISBL,...') on conflict do nothing;
|
||||
insert into parameter_extra(pe_code,pe_label) values ('COMPANY_BANK_IBAN','Compte en banque (IBAN)') on conflict do nothing;
|
||||
insert into parameter_extra(pe_code,pe_label) values ('COMPANY_BANK_BIC','BIC Bank Identification Code') on conflict do nothing;
|
||||
insert into parameter_extra(pe_code,pe_label) values ('COMPANY_UBL_ID','ID PEPPOL') on conflict do nothing;
|
||||
insert into parameter_extra(pe_code,pe_label) values ('COMPANY_UBL_ID','Identifiant PEPPOL') on conflict do nothing;
|
||||
insert into parameter_extra(pe_code,pe_label) values ('SIREN','n° SIREN') on conflict do nothing;
|
||||
insert into parameter_extra(pe_code,pe_label) values ('SIRET','n° SIRET') on conflict do nothing;
|
||||
|
||||
|
|
@ -438,24 +438,14 @@ insert into jnt_fic_attr (fd_id,ad_id,jnt_order)
|
|||
--
|
||||
CREATE OR REPLACE FUNCTION comptaproc.update_peppol ()
|
||||
RETURNS int2
|
||||
/*- SETOF menu_tree : (TABLE FUNCTION) menu_tree is a type of a rowtype create type menu_tree as (code text,description text);
|
||||
- int2, text,varchar...
|
||||
- trigger : if called from a trigger
|
||||
- void : nothing
|
||||
- boolean
|
||||
*/ AS
|
||||
AS
|
||||
$BODY$
|
||||
declare
|
||||
/*
|
||||
* Section for variables
|
||||
*/
|
||||
n_card_id int;
|
||||
vat_number text;
|
||||
record_card RECORD;
|
||||
result_fct int;
|
||||
country_code text;
|
||||
n_card_id int;
|
||||
vat_number text;
|
||||
record_card RECORD;
|
||||
result_fct int;
|
||||
begin
|
||||
select pi_value into country_code from parameter_internal where pi_id ='COUNTRY_CODE';
|
||||
|
||||
result_fct := 0;
|
||||
|
||||
|
|
@ -478,4 +468,27 @@ end;
|
|||
$BODY$
|
||||
LANGUAGE plpgsql;
|
||||
|
||||
select comptaproc.update_peppol();
|
||||
select comptaproc.update_peppol();
|
||||
|
||||
|
||||
CREATE TABLE public.jrn_sup_document (
|
||||
js_id int8 GENERATED BY DEFAULT AS IDENTITY( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1 NO CYCLE) NOT NULL, -- PK
|
||||
js_mimetype text NOT NULL, -- Mimetype
|
||||
js_lob oid NOT NULL, -- OID
|
||||
jr_id int8 NOT NULL, -- FK to jrn
|
||||
js_filename text not null,
|
||||
js_description text ,
|
||||
js_cbc_id text,
|
||||
CONSTRAINT jrn_sup_document_pkey PRIMARY KEY (js_id),
|
||||
CONSTRAINT jrn_sup_document_jrn_fk FOREIGN KEY (jr_id) REFERENCES public.jrn(jr_id) ON DELETE SET NULL ON UPDATE CASCADE
|
||||
);
|
||||
COMMENT ON TABLE public.jrn_sup_document IS 'Supplement document for operation';
|
||||
|
||||
-- Column comments
|
||||
|
||||
COMMENT ON COLUMN public.jrn_sup_document.js_id IS 'PK';
|
||||
COMMENT ON COLUMN public.jrn_sup_document.js_mimetype IS 'Mimetype';
|
||||
COMMENT ON COLUMN public.jrn_sup_document.js_lob IS 'OID';
|
||||
COMMENT ON COLUMN public.jrn_sup_document.jr_id IS 'FK to jrn';
|
||||
COMMENT ON COLUMN public.jrn_sup_document.js_description IS 'Description of document';
|
||||
COMMENT ON COLUMN public.jrn_sup_document.js_cbc_id IS 'ID in XML';
|
||||
Loading…
Add table
Add a link
Reference in a new issue