From f621850e4afdff1e1868d031725ea84158d4b417 Mon Sep 17 00:00:00 2001 From: sparkyx Date: Wed, 24 Dec 2025 11:26:13 +0100 Subject: [PATCH] Task #2446 : add supplemental documents --- include/XMLDocument/invoiceubl21.class.php | 68 ++++++++++++++++++- include/XMLDocument/xmlinvoice.class.php | 29 +++++++- include/class/acc_ledger.class.php | 57 ++++++++++++++++ include/class/acc_ledger_fin.class.php | 6 +- include/class/acc_ledger_purchase.class.php | 1 + include/class/acc_ledger_sale.class.php | 3 +- include/compta_ach.inc.php | 1 + include/compta_ods.inc.php | 3 +- include/compta_ven.inc.php | 2 +- .../template/acc_ledger-input_extra_info.php | 8 +++ unit-test/include/class/Acc_TVATest.php | 2 +- unit-test/include/class/FacturXTest.php | 2 +- unit-test/include/class/InvoiceUBL21Test.php | 2 +- 13 files changed, 175 insertions(+), 9 deletions(-) diff --git a/include/XMLDocument/invoiceubl21.class.php b/include/XMLDocument/invoiceubl21.class.php index 33259119d..42eb5863d 100644 --- a/include/XMLDocument/invoiceubl21.class.php +++ b/include/XMLDocument/invoiceubl21.class.php @@ -533,6 +533,63 @@ class InvoiceUBL21 extends XMLInvoice { return $result; } + /** + * @brief Insert a PDF in the XML + * the document type is not needed for BELGIUM + */ + /** + * +@code + + P01 + Facture PDF + + $base64Pdf + + + + + REF_ODT_001 + Fichier OpenDocument + + [base64-encodage du fichier] + + + + +@endcode + * @return \DOMElement + */ + function include_document($i):\DOMElement + { + + $pdfContent=$this->cn->lo_read($this->data['document'][$i]['oid']); + // Lire le fichier PDF + + $result=$this->createElement("cac:AdditionalDocumentReference"); + $id=$this->createElement("cbc:ID",sprintf("SD%d",$i)); + $d=( $this->data['document'][$i]['description'] == "")?"NONE":$this->data['document'][$i]['description']; + $document_description=$this->createElement("cbc:DocumentDescription" + ,$d ); + + // PDF in base64 + $base64Pdf = base64_encode($pdfContent); + $embeddedDocument=$this->createElement("cbc:EmbeddedDocumentBinaryObject",$base64Pdf); + $embeddedDocument->setAttribute("mimeCode", "application/pdf"); + $embeddedDocument->setAttribute("filename", $this->data['document'][$i]['filename']); + $attachment=$this->createElement("cac:Attachment"); + $attachment->appendChild($embeddedDocument); + + $result->appendChild($id); + $result->appendChild($document_description); + $result->appendChild($attachment); + + return $result; + } /** * @brief create an XML invoice(UBL2.1) based on JRN.JR_ID operation * @parameter $jr_id (int) operation JRN.JR_ID operation @@ -578,7 +635,16 @@ class InvoiceUBL21 extends XMLInvoice { if ($x != null ) { $root->appendChild($x); } - + /** + * insert all Additionnal documents if any + */ + $nb_document=count($this->data['document']); + for ($z=0;$z <$nb_document;$z++) + { + $x= $this->include_document($z); + $root->appendChild($x); + } + // add the supplier $root->appendChild($this->build_supplier()); // add the customer diff --git a/include/XMLDocument/xmlinvoice.class.php b/include/XMLDocument/xmlinvoice.class.php index 9bfe5d10c..52244fc32 100644 --- a/include/XMLDocument/xmlinvoice.class.php +++ b/include/XMLDocument/xmlinvoice.class.php @@ -99,7 +99,9 @@ namespace Noalyss\XMLDocument; ) ) - + + * + * ) @@ -256,6 +258,8 @@ abstract class XMLInvoice extends \DOMDocument } } $result['info']['communication']=($result['info']['communication']=="")?$result['id']:""; + $result['document']=$this->fill_document($jr_id); + /** * Compute totals VAT and AMOUNT */ @@ -545,5 +549,28 @@ abstract class XMLInvoice extends \DOMDocument $this->pdf_filename = $pdf_filename; return $this; } + /** + * @brief retrieve additionnal documents but only PDF , not other files + * @param $jr_id (int) JRN.JR_DEF_ID + * @return array : empty or keys= (filename,description, log id) from table from JRN_SUP_DOCUMENT + */ + public function fill_document($jr_id) + { + $result=[]; + $a_document=$this->cn->get_array("select js_id,js_filename,js_description,js_lob from jrn_sup_document where js_mimetype='application/pdf' AND jr_id=$1", + [$jr_id]); + if ($a_document == null) return array(); + + foreach ($a_document as $document) + { + $result[]=array("filename"=>$document['js_filename'] + ,"description"=>$document['js_description'] + ,'oid'=>$document['js_lob'] + ,'id'=>$document['js_id'] + ); + } + return $result; + + } } diff --git a/include/class/acc_ledger.class.php b/include/class/acc_ledger.class.php index 7c13b95d3..5017ddda2 100644 --- a/include/class/acc_ledger.class.php +++ b/include/class/acc_ledger.class.php @@ -3668,6 +3668,63 @@ EOF; return span (_("Attention ! Numéro de Pièce non automatique mais forcée"),'class="warning"'); } } + /** + * @brief display INPUT type to ask the supplementary documents + * @return HTML string + * @throws \Exception 3674 If ledger JRN.JRN_DEF_ID == 0 + */ + protected function input_supplemental_document() + { + if ( $this->id==0) { + throw new \Exception ("ACL3674: invalid ledger",3674); + } + /** + * add suppl.documents + */ + $supplemental_doc=new IFile('document_supplemental[]'); + $supplemental_doc->setAlertOnSize(true); + $supplemental_doc->set_multiple(true); + $r=""; + $r.='

'; + $r.= _("Ajoutez des documents additionnels"); + $r.=$supplemental_doc->input(); + $r.='

'; + return $r; + } + /** + * @brief upload the supplementary documents and attach them to the JRN.JR_ID + * start a new transaction if the connection to the database is not + * already in a transaction + * @param $jr_id (int) JRN.JR_ID + */ + public function upload_supplemental_document($jr_id) + { + if (! isset ($_FILES['document_supplemental']) || count($_FILES['document_supplemental']['name'])==0) { + return; + } + $nb=count($_FILES['document_supplemental']["name"]); + if ( $this->db->status() !== PGSQL_TRANSACTION_INTRANS ) { + $a=1; + $this->db->start(); + } + for ($i=0;$i<$nb;$i++) + { + $file= tempnam($_ENV["TMP"], "sup_file"); + if ( move_uploaded_file($_FILES['document_supplemental']['tmp_name'][$i],$file)) + { + if ( ($oid=$this->db->lo_import($file)) != false ) + { + $jrn_sup=new Jrn_Sup_Document_SQL($this->db); + $jrn_sup->jr_id=$jr_id; + $jrn_sup->js_lob=$oid; + $jrn_sup->js_mimetype=$_FILES['document_supplemental']['type'][$i]; + $jrn_sup->js_filename=$_FILES['document_supplemental']['name'][$i]; + $jrn_sup->insert(); + } + } + } + if ( $a == 1) { $this->db->commit(); } + } } ?> diff --git a/include/class/acc_ledger_fin.class.php b/include/class/acc_ledger_fin.class.php index b5a9a8cee..933b03b03 100644 --- a/include/class/acc_ledger_fin.class.php +++ b/include/class/acc_ledger_fin.class.php @@ -701,8 +701,11 @@ class Acc_Ledger_Fin extends Acc_Ledger // check for upload piece $file=new IFile(); $file->setAlertOnSize(true); - $r.="
"._("Ajoutez une pièce justificative")." "; + $r.="

"._("Ajoutez une pièce justificative")." "; $r.=$file->input("pj", ""); + $r.='

'; + + $r.=$this->input_supplemental_document(); $r.=''; //-------------------------------------------------- @@ -1087,6 +1090,7 @@ class Acc_Ledger_Fin extends Acc_Ledger jr_pj_type=$3 where jr_grpt_id=$4", array($oid, $_FILES['pj']['name'], $_FILES['pj']['type'], $seq)); } + $this->upload_supplemental_document($jr_id); } // for nbitem // increment pj if (noalyss_strlentrim($e_pj)!=0) diff --git a/include/class/acc_ledger_purchase.class.php b/include/class/acc_ledger_purchase.class.php index 96463a209..ab8e09b63 100644 --- a/include/class/acc_ledger_purchase.class.php +++ b/include/class/acc_ledger_purchase.class.php @@ -2140,6 +2140,7 @@ EOF; " from document_modele where md_affect='ACH' order by 2"); $r.=$doc_gen->input().'
'; } + $r.=$this->input_supplemental_document(); $r.='
'; $obj=new IText(); $r.=_('Numero de bon de commande : ').$obj->input('bon_comm').'
'; diff --git a/include/class/acc_ledger_sale.class.php b/include/class/acc_ledger_sale.class.php index 7bcd924a0..6a6a7b265 100644 --- a/include/class/acc_ledger_sale.class.php +++ b/include/class/acc_ledger_sale.class.php @@ -1398,7 +1398,8 @@ EOF; " union select -2,'"._("Z - Facture PDF Standard")."' ". " order by 2"); $r.=$doc_gen->input() . '
'; - + $r.=$this->input_supplemental_document(); + $r.='
'; $obj = new IText(); $r.=_('Numero de bon de commande') . $obj->input('bon_comm') . '
'; diff --git a/include/compta_ach.inc.php b/include/compta_ach.inc.php index 6d5ade61e..4ea6d6097 100644 --- a/include/compta_ach.inc.php +++ b/include/compta_ach.inc.php @@ -108,6 +108,7 @@ if (isset($_POST['record'])) try { $internal = $Ledger->insert($_POST); + $Ledger->upload_supplemental_document($Ledger->jr_id); } catch (\Exception $e) { if ( $e->getCode()==EXC_BALANCE) { diff --git a/include/compta_ods.inc.php b/include/compta_ods.inc.php index b4468737d..8bde2927e 100644 --- a/include/compta_ods.inc.php +++ b/include/compta_ods.inc.php @@ -78,7 +78,8 @@ if (!isset($_POST['summary']) && !isset($_POST['save'])) { try { $ledger->save($array); $jr_id = $ledger->jr_id; - + $ledger->upload_supplemental_document($jr_id); + /* save followup */ $ledger->save_followup($http->request("action_gestion", "string", "")); diff --git a/include/compta_ven.inc.php b/include/compta_ven.inc.php index 07ad55f1e..97231536e 100644 --- a/include/compta_ven.inc.php +++ b/include/compta_ven.inc.php @@ -151,7 +151,7 @@ if ( isset($_POST['record']) ) $Ledger=new Acc_Ledger_Sale($cn,$post_jrn); try { $internal=$Ledger->insert($_POST); - + $Ledger->upload_supplemental_document($Ledger->jr_id); // var $receipt (string) contains the name of the file name of // the invoice (document created), if empty there // is no invoice diff --git a/include/template/acc_ledger-input_extra_info.php b/include/template/acc_ledger-input_extra_info.php index 0054e482b..446829dab 100644 --- a/include/template/acc_ledger-input_extra_info.php +++ b/include/template/acc_ledger-input_extra_info.php @@ -102,6 +102,9 @@ if ( in_array("document",$a_show)) { ?> check_company_data(); - $this->assertTrue(count($a_error)==10, "nb of error incorrect ".print_r($a_error,true)); + $this->assertTrue(count($a_error)==8, "nb of error incorrect ".print_r($a_error,true)); } function testCustomer_Data() diff --git a/unit-test/include/class/InvoiceUBL21Test.php b/unit-test/include/class/InvoiceUBL21Test.php index a53eace33..70b4c647d 100644 --- a/unit-test/include/class/InvoiceUBL21Test.php +++ b/unit-test/include/class/InvoiceUBL21Test.php @@ -161,7 +161,7 @@ class InvoiceUBL21Test extends TestCase { $ublinvoice21 = new \Noalyss\XMLDocument\InvoiceUBL21($cn); $a_error=array(); $a_error=$ublinvoice21->check_company_data(); - $this->assertTrue(count($a_error) ==8 , " nb of errors incorrect ".print_r($a_error,true)); + $this->assertTrue(count($a_error) ==9 , " nb of errors incorrect ".print_r($a_error,true)); } function testCustomer_Data() {