Task #2446 : add supplemental documents

This commit is contained in:
sparkyx 2025-12-24 11:26:13 +01:00
parent a5bb6cfc97
commit f621850e4a
13 changed files with 175 additions and 9 deletions

View file

@ -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
<cac:AdditionalDocumentReference>
<cbc:ID>P01</cbc:ID>
<cbc:DocumentDescription>Facture PDF</cbc:DocumentDescription>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject
mimeCode="application/pdf"
filename="invoice.pdf">$base64Pdf</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<!-- OU -->
<cac:AdditionalDocumentReference>
<cbc:ID>REF_ODT_001</cbc:ID>
<cbc:DocumentDescription>Fichier OpenDocument</cbc:DocumentDescription>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject
mimeCode="application/vnd.oasis.opendocument.text"
filename="facture.odt">[base64-encodage du fichier]</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>
@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,6 +635,15 @@ 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());

View file

@ -100,6 +100,8 @@ 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;
}
}

View file

@ -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.='<p class="decale">';
$r.= _("Ajoutez des documents additionnels");
$r.=$supplemental_doc->input();
$r.='</p>';
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(); }
}
}
?>

View file

@ -701,8 +701,11 @@ class Acc_Ledger_Fin extends Acc_Ledger
// check for upload piece
$file=new IFile();
$file->setAlertOnSize(true);
$r.="<br>"._("Ajoutez une pièce justificative")." ";
$r.="<p class=\"decale\">"._("Ajoutez une pièce justificative")." ";
$r.=$file->input("pj", "");
$r.='</p>';
$r.=$this->input_supplemental_document();
$r.='</div>';
//--------------------------------------------------
@ -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)

View file

@ -2140,6 +2140,7 @@ EOF;
" from document_modele where md_affect='ACH' order by 2");
$r.=$doc_gen->input().'<br>';
}
$r.=$this->input_supplemental_document();
$r.='<br>';
$obj=new IText();
$r.=_('Numero de bon de commande : ').$obj->input('bon_comm').'<br>';

View file

@ -1398,6 +1398,7 @@ EOF;
" union select -2,'"._("Z - Facture PDF Standard")."' ".
" order by 2");
$r.=$doc_gen->input() . '<br>';
$r.=$this->input_supplemental_document();
$r.='<br>';
$obj = new IText();

View file

@ -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)
{

View file

@ -78,6 +78,7 @@ 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", ""));

View file

@ -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

View file

@ -102,6 +102,9 @@ if ( in_array("document",$a_show)) {
?>
<div id="document_div_id" style="display:none;height:185px;height:10rem">
<?php
/**
* receipt
*/
$file = new IFile();
$file->setAlertOnSize(true);
$file->table = 0;
@ -110,6 +113,11 @@ if ( in_array("document",$a_show)) {
echo $file->input("pj", "");
echo '</p>';
?>
<p class="decale">
<?php
echo $this->input_supplemental_document();
?>
</p>
</div>
<?php

View file

@ -129,7 +129,7 @@ class Acc_TVATest extends TestCase
['S',true,null]
,['Z',true,null]
,['A',false,""]
,['A',true,"XX"]
,['K',true,"XX"]
);
}
/**

View file

@ -126,7 +126,7 @@ class FacturXTest extends TestCase {
$cn=\Dossier::connect();
$facturx=new \Noalyss\XMLDocument\FacturX($cn);
$a_error=$facturx->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()

View file

@ -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() {