altocompta/include/XMLDocument/invoiceubl21.class.php
2026-01-26 13:45:20 +01:00

720 lines
29 KiB
PHP

<?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 UBL2.1 Belgique
* - $pdf_filename PDF file to insert into XML, it is the file on the filesystem
*/
/**
* @class
* @brief UBL2.1 Belgique
* @note Doit contenir le PDF.
* - $pdf_filename PDF file to insert into XML, it is the file on the filesystem
@code
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="facture.pdf" encodingCode="Base64">
[Contenu du PDF encodé en Base64]
</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
@endcode
*
*/
class InvoiceUBL21 extends XMLInvoice {
const EXTRA_PARAMETER = ["INVOICE_EMAIL_COMPANY"
, 'INVOICE_CONTACT_NAME'
, 'COMPANY_LEGAL_ENTITY'
, 'COMPANY_LEGAL_REGISTRATION'
, 'COMPANY_BANK_IBAN'
, 'COMPANY_BANK_BIC'
, 'MY_COUNTRY_CODE'
, 'MY_NAME'
, 'MY_STREET'
, 'MY_CITY'
, 'MY_TVA'
, 'INVOICE_EMAIL_COMPANY'
,'COMPANY_PEPPOL_ID'
];
protected $pdf_filename; //!< PDF file to insert into XML,
// it is the file on the filesystem
public function get_pdf_filename() {
return $this->pdf_filename;
}
/**
* @brief display_error display a warning with all error
*/
function display_error()
{
$a_error=$this->verify();
include NOALYSS_TEMPLATE."/xmlinvoice-display_error.php";
}
/**
* @brief check that the VAT is using a PEPPOL Code
*/
function check_VAT()
{
$a_error=array();
$nb_operation=count($this->data['operation']);
for ($i=0;$i <$nb_operation;$i++)
{
if ( $this->data['operation'][$i]['vat_code'] == "" ) {
$card=new \Fiche(
$this->cn
,$this->data['operation'][$i]['card_id']
);
$tva= \Acc_Tva::build($this->cn, $this->data['operation'][$i]['vat_id']);
$a_error[]=sprintf(_("%s : %s code TVA pour PEPPOL non configuré code TVA [ %s %s ]")
, $i
, $card->get_quick_code()
,$tva->tva_id
,$tva->tva_code
);
}
elseif (! in_array($this->data['operation'][$i]['vat_code'],array("S","Z")))
{
$card=new \Fiche(
$this->cn
,$this->data['operation'][$i]['card_id']
);
$tva= \Acc_Tva::build($this->cn, $this->data['operation'][$i]['vat_id']);
if ( $tva->vx_code == "")
{
$a_error[]=sprintf(_("%s : %s code Exemption pour PEPPOL non configuré code TVA [ %s %s ]")
, $i
, $card->get_quick_code()
,$tva->tva_id
,$tva->tva_code
);
}
}
}
return $a_error;
}
/**
* @brief check that mandatory info are saved in the DB for company (seller)
* @param $a_error (array) array of errors, empty if nothing found
*/
function check_company_data() {
// var $a_error (array) contains the errors for the company
$a_error=array();
$company = $this->load_noalyss_parameter();
foreach (InvoiceUBL21::EXTRA_PARAMETER as $item) {
if (!isset($company[$item]) || trim($company[$item]) == '') {
$a_error[]=$item;
}
}
/**
* check that PEPPOL ID is valid
*/
if ( isset($company['COMPANY_PEPPOL_ID']))
{
if ( strpos($company['COMPANY_PEPPOL_ID'],':') == 0 )
{
$a_error[]="COMPANY_PEPPOL_ID";
}
}
if ( isset ($company['MY_TVA']) && preg_match('/[a-z]{2}/i',$company['MY_TVA']) == false )
{
$a_error[]="MY_TVA";
}
return $a_error;
}
/**
* @brief check that mandatory info are saved in the DB for customer
*/
function check_customer_data(){
$a_error=array();
$a_needed=[ATTR_DEF_NAME=>'name'
,ATTR_DEF_ADRESS=>'street'
,ATTR_DEF_POSTCODE=>'postalzone'
,ATTR_DEF_CITY=>'city'
,ATTR_DEF_COUNTRY_CODE=>'country'
,ATTR_DEF_NUMTVA=>'customer_vat_id'
,ATTR_DEF_PEPPOLID=>'endpoint_id'
];
foreach ($a_needed as $item=>$value) {
if ( trim($this->data['customer'][$value])=="") {
$a_error[]=$value;
}
}
if ( $this->data['customer']["endpoint_id"] != "")
{
// check if peppol id has the form 9999:9999...
list($scheme_id,$peppol)=explode(":", $this->data['customer'][$value]);
if (preg_replace('/[0-9]/', '', $scheme_id) != "")
{
$a_error[]='endpoint_id';
}elseif(\noalyss_trim($peppol) =="")
{
$a_error[]='endpoint_id';
}
}
if ( $this->data['customer']["customer_vat_id"] != "" && preg_match('/[a-z]{2}/i',$this->data['customer']["customer_vat_id"] ) == false)
{
$a_error[]='customer_vat_id';
}
return $a_error;
}
/**
* @brief transform an operation ($jr_id) into an array, which contains
* needed information for making an e-invoice
* @param $jr_id (int) operation JRN.JR_ID
* @return array with all info7
* @param type $jr_id
* @see XMLInvoice::build_data
*/
function build_data($jr_id): array
{
$this->data=parent::build_data($jr_id);
return $this->data;
}
/**
* @brief Information customer
*/
function build_customer()
{
$customer=$this->createElement('cac:AccountingCustomerParty');
$customer_party=$customer->appendChild($this->createElement('cac:Party'));
list($scheme_id,$peppol)=explode( ":",trim($this->data['customer']['endpoint_id']));
$customer_party->appendChild($this->createElement('cbc:EndpointID',$peppol))
->setAttribute('schemeID', $scheme_id);
$party_name=$this->createElement('cac:PartyName');
$party_name->appendChild($this->createElement("cbc:Name", htmlspecialchars($this->data['customer']['name'],ENT_XML1,'UTF-8')));
$customer_party->appendChild($party_name);
$postal_address=$customer_party->appendChild($this->createElement('cac:PostalAddress'));
$postal_address->appendChild($this->createElement("cbc:StreetName", htmlspecialchars($this->data['customer']['street'],ENT_XML1,'UTF-8')));
$postal_address->appendChild($this->createElement("cbc:CityName", htmlspecialchars($this->data['customer']['city'],ENT_XML1,'UTF-8')));
$postal_address->appendChild($this->createElement("cbc:PostalZone", $this->data['customer']['postalzone']));
///@todo customer = countryCode doit être dans les paramètres (voir upgrade.sql)
$country_code =$this->data['customer']['country'];
$country=$postal_address->appendChild($this->createElement("cac:Country"));
$country->appendChild($this->createElement('cbc:IdentificationCode',$country_code));
$postal_address->appendChild($country);
// Tax Schem
$tax=$this->createElement('cac:PartyTaxScheme');
$tax->appendChild($this->createElement('cbc:CompanyID',$this->data["customer"]['customer_vat_id']));
$tax_scheme=$this->createElement('cac:TaxScheme');
$tax_scheme->appendChild($this->createElement('cbc:ID',"VAT"));
$tax->appendChild($tax_scheme);
// LegalEntity
$ple=$this->createElement('cac:PartyLegalEntity');
///@todo customer = name doit être fiche
$ple->appendChild($this->createElement("cbc:RegistrationName", htmlspecialchars($this->data['customer']['name'],ENT_XML1,'UTF-8')));
///@todo customer_vat_id = numéro de TVA doit être dans fiche
$ple->appendChild($this->createElement("cbc:CompanyID", $this->data['customer']['customer_vat_id']??"ERROR"));
// assemble supplier
$customer_party->appendChild($tax);
$customer_party->appendChild($ple);
$customer->appendChild($customer_party);
return $customer;
}
/**
* @brief Delivery Date is mandatory for INTRACOMM , so by default
* we set the invoice date
<cac:Delivery>
<cbc:ActualDeliveryDate>
2026-01-06
</cbc:ActualDeliveryDate>
</cac:Delivery>
*/
function build_deliveryDate()
{
$delivery=$this->createElement("cac:Delivery");
$delivery->appendChild($this->createElement("cbc:ActualDeliveryDate",$this->data['issue_date']));
//(cac:Delivery/cac:DeliveryLocation/cac:Address/cac:Country/cbc:IdentificationCode//
$loc= $this->createElement("cac:DeliveryLocation");
$addr=$this->createElement('cac:Address');
$country=$this->createElement("cac:Country");
$country->appendChild($this->createElement("cbc:IdentificationCode", $this->data['customer']['country']));
$addr->appendChild($country);
$loc->appendChild($addr);
$delivery->appendChild($loc);
return $delivery;
}
/**
/**
* @brief Build XML Block for payment
* @code
<cac:PaymentMeans>
<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
<cbc:PaymentID>Invoice 2019000005</cbc:PaymentID>
<cac:PayeeFinancialAccount>
<cbc:ID>BE54000000000097</cbc:ID>
<cac:FinancialInstitutionBranch>
<cbc:ID>BPOTBEB1</cbc:ID>
</cac:FinancialInstitutionBranch>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
* @endcode
*/
function build_paymentInfo()
{
$company = $this->load_noalyss_parameter();
$payment=$this->createElement("cac:PaymentMeans");
$payment->appendChild($this->createElement('cbc:PaymentMeansCode',30));
///@note cbc:PaymentID est la communication lors du paiement
$payment->appendChild($this->createElement('cbc:PaymentID', htmlspecialchars($this->data["info"]['communication'],ENT_XML1,'UTF-8')));
$f=$this->createElement ('cac:PayeeFinancialAccount');
///@todo customer = IBAN doit être dans les paramètres (voir upgrade.sql)
$f->appendChild($this->createElement("cbc:ID",$company['COMPANY_BANK_IBAN']));
$g=$this->createElement("cac:FinancialInstitutionBranch");
$g->appendChild($this->createElement("cbc:ID", $company['COMPANY_BANK_BIC']));
$f->appendChild($g);
$payment->appendChild($f);
return $payment;
}
/**
* @brief Information supplier
*/
function build_supplier()
{
$company = $this->load_noalyss_parameter();
$supplier=$this->createElement('cac:AccountingSupplierParty');
$supplier_party=$supplier->appendChild($this->createElement('cac:Party'));
list($scheme_id,$peppol)=explode( ":",trim($company['COMPANY_PEPPOL_ID']));
$supplier_party->appendChild($this->createElement('cbc:EndpointID',$peppol))
->setAttribute('schemeID', $scheme_id);
//$supplier_party->appendChild($this->createElement('cbc:EndpointID',$this->data["supplier"]['supplier_vat_id']))->setAttribute('schemeID', 9925);
$party_name=$this->createElement('cac:PartyName');
$party_name->appendChild($this->createElement('cbc:Name', htmlspecialchars($this->data['supplier']['name'],ENT_XML1,'UTF-8')));
$supplier_party->appendChild($party_name);
$postal_address=$supplier_party->appendChild($this->createElement('cac:PostalAddress'));
$postal_address->appendChild($this->createElement("cbc:StreetName", htmlspecialchars($this->data['supplier']['street'],ENT_XML1,'UTF-8')));
$postal_address->appendChild($this->createElement("cbc:CityName", htmlspecialchars ($this->data['supplier']['city'],ENT_XML1,'UTF-8')));
$postal_address->appendChild($this->createElement("cbc:PostalZone", $this->data['supplier']['postalzone']));
$country_code = $company['MY_COUNTRY_CODE'];
$country=$postal_address->appendChild($this->createElement("cac:Country"));
$country->appendChild($this->createElement('cbc:IdentificationCode',$country_code??"ERROR"));
$postal_address->appendChild($country);
// Tax Schem
$tax=$this->createElement('cac:PartyTaxScheme');
$tax->appendChild($this->createElement('cbc:CompanyID',$this->data["supplier"]['supplier_vat_id']));
$tax_scheme=$this->createElement('cac:TaxScheme');
$tax_scheme->appendChild($this->createElement('cbc:ID',"VAT"));
$tax->appendChild($tax_scheme);
// LegalEntity
$ple=$this->createElement('cac:PartyLegalEntity');
$ple->appendChild($this->createElement("cbc:RegistrationName", htmlspecialchars($company['COMPANY_LEGAL_REGISTRATION']??"ERROR",ENT_XML1,'UTF-8')));
$ple->appendChild($this->createElement("cbc:CompanyID", $this->data['supplier']['supplier_vat_id']??"ERROR"));
$ple->appendChild($this->createElement("cbc:CompanyLegalForm", $company['COMPANY_LEGAL_ENTITY']??"ERROR"));
$contact=$this->createElement('cac:Contact');
$contact->appendChild($this->createElement("cbc:Name",$company['INVOICE_CONTACT_NAME']??"ERROR"));
$contact->appendChild($this->createElement("cbc:ElectronicMail",$company['INVOICE_EMAIL_COMPANY']??"ERROR"));
// assemble supplier
$supplier_party->appendChild($tax);
$supplier_party->appendChild($ple);
$supplier_party->appendChild($contact);
$supplier->appendChild($supplier_party);
return $supplier;
}
/**
* @brief TaxTotal Block
* @code
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">516</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">2400</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">504</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>21</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">200</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">12</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>6</cbc:Percent>
if ID !=Z and ID != S <cbc:TaxExemptionReasonCode
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
* @endcode
*/
function build_taxTotal()
{
$taxTotal=$this->createElement("cac:TaxTotal");
$taxTotal->appendChild($this->createElement('cbc:TaxAmount',sprintf("%.2f",$this->data['TaxAmount'])))
->setAttribute("currencyID",$this->data['currency']);
// for subTotal
$subTotal=$this->data['subTotalVAT'];
$nb_sub=count($subTotal);
for ($i=0;$i<$nb_sub;$i++) {
$subTotalXML=$this->createElement("cac:TaxSubtotal");
$subTotalXML->appendChild($this->createElement('cbc:TaxableAmount',sprintf("%.2f",$subTotal[$i]['amount'])))
->setAttribute("currencyID", $this->data['currency']);
$subTotalXML->appendChild($this->createElement('cbc:TaxAmount',sprintf("%.2f",$subTotal[$i]['vat'])))
->setAttribute("currencyID",$this->data['currency']);
$taxCategory=$this->createElement("cac:TaxCategory");
$taxCategory->appendChild($this->createElement("cbc:ID",$subTotal[$i]['vat_code']));
$taxCategory->appendChild($this->createElement("cbc:Percent",sprintf("%.2f",$subTotal[$i]['percent'])));
if ($subTotal[$i]['vat_code'] != "S"
&& $subTotal[$i]['vat_code'] != "Z")
{
// if cbc:ID not S and not Z then exemption VAT code is needed
$taxCategory->appendChild($this->createElement("cbc:TaxExemptionReasonCode",$subTotal[$i]['vatex']));
}
$taxScheme=$this->createElement("cac:TaxScheme");
$taxScheme->appendChild($this->createElement("cbc:ID", "VAT"));
$taxCategory->appendChild($taxScheme);
$subTotalXML->appendChild($taxCategory);
$taxTotal->appendChild($subTotalXML);
}
return $taxTotal;
}
/**
* @brief legalMonetaryTotal
* @code
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="EUR">2600</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">2600</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">3116</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="EUR">3116</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
* @endcode
*/
function build_legalMonetaryTotal()
{
$result=$this->createElement('cac:LegalMonetaryTotal' );
$result->appendChild($this->createElement("cbc:LineExtensionAmount",sprintf("%.2f",$this->data['LineExtensionAmount'])))
->setAttribute("currencyID",$this->data['currency']);
$result->appendChild($this->createElement("cbc:TaxExclusiveAmount",sprintf("%.2f",$this->data['TaxExclusiveAmount'])))
->setAttribute("currencyID",$this->data['currency']);
$result->appendChild($this->createElement("cbc:TaxInclusiveAmount",sprintf("%.2f",$this->data['TaxInclusiveAmount'])))
->setAttribute("currencyID", $this->data['currency'] );
$result->appendChild($this->createElement("cbc:PayableAmount",sprintf("%.2f",$this->data['PayableAmount'])))
->setAttribute("currencyID", $this->data['currency'] );
return $result;
}
/**
* @brief cac:InvoiceLine
* @code
<cac:InvoiceLine>
<cbc:ID>2</cbc:ID>
<cbc:InvoicedQuantity unitCode="C62">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">200</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Good X</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>6</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="EUR">20</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
* @endcode
* @param $i (int) idx f $this->data->operation[$i]
*
*/
function build_invoiceLine($i)
{
$result=$this->createElement('cac:InvoiceLine');
$row=$this->data["operation"][$i];
$amount=sprintf("%.2f",$row['price']);
$result->appendChild($this->createElement("cbc:ID", $i));
$amount=sprintf("%.2f",$row['price']);
$result->appendChild(
$this->createElement("cbc:InvoicedQuantity", sprintf("%.2f",$row['quantity'])))
->setAttribute("unitCode", $row["code_quantity"]);
$result->appendChild($this->createElement("cbc:LineExtensionAmount", $amount))
->setAttribute("currencyID",$this->data['currency']);
// ITEM
$item=$this->createElement("cac:Item");
$item->appendChild($this->createElement("cbc:Description",htmlspecialchars($row['description'],ENT_XML1,'UTF-8')));
$item->appendChild($this->createElement("cbc:Name", $row['qcode']));
$classifiedTaxCat=$this->createElement("cac:ClassifiedTaxCategory");
//cbc:ID S = standard rate
/// see TVA_RATE.TVA_PEPPOL_CODE & C0TVA
$classifiedTaxCat->appendChild($this->createElement("cbc:ID", $row['vat_code']));
$classifiedTaxCat->appendChild($this->createElement("cbc:Percent", sprintf("%.2f",$row['vat_percent'])));
$tax_scheme=$this->createElement('cac:TaxScheme');
$tax_scheme->appendChild($this->createElement("cbc:ID", "VAT"));
$classifiedTaxCat->appendChild($tax_scheme);
$item->appendChild($classifiedTaxCat);
$result->appendChild($item);
$price=$result->appendChild($this->createElement("cac:Price"));
$price->appendChild($this->createElement("cbc:PriceAmount",sprintf("%.2f",abs($row['price_unit']))))
->setAttribute("currencyID",$this->data['currency']);
$result->appendChild($price);
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 build_Invoice():\DOMElement
{
if ( $this->pdf_filename == "") return null;
/** $pdf_filename = 'chemin/vers/votre/fichier.pdf';*/
static $i=0;
$i++;
if ( $this->pdf_filename == null ) {
return null;
}
// Lire le fichier PDF
$pdfContent = file_get_contents( $this->pdf_filename );
$result=$this->createElement("cac:AdditionalDocumentReference");
$id=$this->createElement("cbc:ID",$i);
$document_description=$this->createElement("cbc:DocumentDescription"
, htmlspecialchars($this->data['description'],ENT_XML1,'UTF-8'));
// PDF in base64
$base64Pdf = base64_encode($pdfContent);
$embeddedDocument=$this->createElement("cbc:EmbeddedDocumentBinaryObject",$base64Pdf);
$embeddedDocument->setAttribute("mimeCode", "application/pdf");
$embeddedDocument->setAttribute("filename", "facture.pdf");
$attachment=$this->createElement("cac:Attachment");
$attachment->appendChild($embeddedDocument);
$result->appendChild($id);
$result->appendChild($document_description);
$result->appendChild($attachment);
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"
,htmlspecialchars($d ,ENT_XML1,'UTF-8'));
// 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
* @return XML String
*/
function make_xml($jr_id)
{
$this->data = $this->build_data($jr_id);
// var $company (array) all the parameters of the company
$company = $this->load_noalyss_parameter();
// HEADER
$root=$this->createElementNS('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2',"Invoice",);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/',"xmlns:cac", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2");
$root->setAttributeNS('http://www.w3.org/2000/xmlns/',"xmlns:cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2");
$root->appendChild($this->createElement('cbc:CustomizationID',"urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0"));
$root->appendChild($this->createElement('cbc:ProfileID',"urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"));
$root->appendChild($this->createElement('cbc:ID',$this->data['id']));
$root->appendChild($this->createElement('cbc:IssueDate',$this->data['issue_date']));
if ($this->data ['due_date'] == '')
{
$this->data ['due_date']=$this->data['issue_date'];
}
$root->appendChild($this->createElement('cbc:DueDate',$this->data['due_date']));
$root->appendChild($this->createElement('cbc:InvoiceTypeCode',380));
/**
* add note if any
*/
if ( $this->data['note'] != "")
{
$root->appendChild($this->createElement("cbc:Note", htmlspecialchars($this->data['note'],ENT_XML1,'UTF-8')));
}
$root->appendChild($this->createElement('cbc:DocumentCurrencyCode',$this->data['currency']));
$root->appendChild($this->createElement('cbc:BuyerReference', htmlspecialchars($this->data['info']['order'],ENT_XML1,'UTF-8')));
/**
* insert PDF in the XML
*/
$x = $this->build_Invoice();
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
$root->appendChild($this->build_customer());
// add delivery date
$root->appendChild($this->build_deliveryDate());
// add the payment if there is a bank account
if ( $company['COMPANY_BANK_IBAN'] != "")
$root->appendChild($this->build_paymentInfo());
// Add cac:TaxTotal
$root->appendChild($this->build_taxTotal());
// Add cac:LegalMonetatyTotal
$root->appendChild($this->build_legalMonetaryTotal());
// add all the invoiceline
// operation
$nb_operation=count($this->data["operation"]);
for ($i=0;$i < $nb_operation ; $i++) {
$root->appendChild($this->build_invoiceLine($i));
}
$this->append($root);
$this->formatOutput=true;
return $this->saveXML();
}
/**
* @brief create the invoice in the right format, with PDF if any
* @param $operation_id (int) JRN.JR_ID
* @return string XML Invoice
*/
function create_invoice($operation_id) {
return $this->make_xml($operation_id);
}
}