noalyss Version-10
NOALYSS : serveur de comptabilité et ERP (2002)
Loading...
Searching...
No Matches
invoiceubl21.class.php
Go to the documentation of this file.
1<?php
2
3namespace Noalyss\XMLDocument;
4
5/*
6 * This file is part of NOALYSS.
7 *
8 * NOALYSS is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * NOALYSS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with NOALYSS; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22// Copyright Author Dany De Bontridder danydb@aevalys.eu 22/10/23
23
24/**
25 * @file
26 * @brief UBL2.1 Belgique
27 * - $pdf_filename PDF file to insert into XML, it is the file on the filesystem
28 */
29/**
30 * @class
31 * @brief UBL2.1 Belgique
32 * @note Doit contenir le PDF.
33 * - $pdf_filename PDF file to insert into XML, it is the file on the filesystem
34 @code
35<cac:Attachment>
36 <cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="facture.pdf" encodingCode="Base64">
37 [Contenu du PDF encodé en Base64]
38 </cbc:EmbeddedDocumentBinaryObject>
39</cac:Attachment>
40@endcode
41 *
42 */
43class InvoiceUBL21 extends XMLInvoice {
44
45 const EXTRA_PARAMETER = ["INVOICE_EMAIL_COMPANY"
46 , 'INVOICE_CONTACT_NAME'
47 , 'COMPANY_LEGAL_ENTITY'
48 , 'COMPANY_LEGAL_REGISTRATION'
49 , 'COMPANY_BANK_IBAN'
50 , 'COMPANY_BANK_BIC'
51 , 'MY_COUNTRY_CODE'
52 , 'MY_NAME'
53 , 'MY_STREET'
54 , 'MY_CITY'
55 , 'MY_TVA'
56 , 'INVOICE_EMAIL_COMPANY'
57 ,'COMPANY_PEPPOL_ID'
58 ];
59 protected $pdf_filename; //!< PDF file to insert into XML,
60 // it is the file on the filesystem
61 public function get_pdf_filename() {
63 }
64 /**
65 * @brief display_error display a warning with all error
66 */
67 function display_error()
68 {
69 $a_error=$this->verify();
70 include NOALYSS_TEMPLATE."/xmlinvoice-display_error.php";
71 }
72
73
74 /**
75 * @brief check that the VAT is using a PEPPOL Code
76 */
77 function check_VAT()
78 {
79 $a_error=array();
80 $nb_operation=count($this->data['operation']);
81 for ($i=0;$i <$nb_operation;$i++)
82 {
83 if ( $this->data['operation'][$i]['vat_code'] == "" ) {
84 $card=new \Fiche(
85 $this->cn
86 ,$this->data['operation'][$i]['card_id']
87 );
88 $tva= \Acc_Tva::build($this->cn, $this->data['operation'][$i]['vat_id']);
89 $a_error[]=sprintf(_("%s : %s code TVA pour PEPPOL non configuré code TVA [ %s %s ]")
90 , $i
91 , $card->get_quick_code()
92 ,$tva->tva_id
93 ,$tva->tva_code
94 );
95 }
96 elseif (! in_array($this->data['operation'][$i]['vat_code'],array("S","Z")))
97 {
98 $card=new \Fiche(
99 $this->cn
100 ,$this->data['operation'][$i]['card_id']
101 );
102 $tva= \Acc_Tva::build($this->cn, $this->data['operation'][$i]['vat_id']);
103 if ( $tva->vx_code == "")
104 {
105 $a_error[]=sprintf(_("%s : %s code Exemption pour PEPPOL non configuré code TVA [ %s %s ]")
106 , $i
107 , $card->get_quick_code()
108 ,$tva->tva_id
109 ,$tva->tva_code
110 );
111 }
112 }
113 }
114 return $a_error;
115 }
116 /**
117 * @brief check that mandatory info are saved in the DB for company (seller)
118 * @param $a_error (array) array of errors, empty if nothing found
119 */
121 // var $a_error (array) contains the errors for the company
122 $a_error=array();
123 $company = $this->load_noalyss_parameter();
124 foreach (InvoiceUBL21::EXTRA_PARAMETER as $item) {
125 if (!isset($company[$item]) || trim($company[$item]) == '') {
126 $a_error[]=$item;
127 }
128 }
129 /**
130 * check that PEPPOL ID is valid
131 */
132 if ( isset($company['COMPANY_PEPPOL_ID']))
133 {
134 if ( strpos($company['COMPANY_PEPPOL_ID'],':') == 0 )
135 {
136 $a_error[]="COMPANY_PEPPOL_ID";
137 }
138
139 }
140 if ( isset ($company['MY_TVA']) && preg_match('/[a-z]{2}/i',$company['MY_TVA']) == false )
141 {
142 $a_error[]="MY_TVA";
143 }
144 return $a_error;
145 }
146 /**
147 * @brief check that mandatory info are saved in the DB for customer
148 */
150 $a_error=array();
151 $a_needed=[ATTR_DEF_NAME=>'name'
152 ,ATTR_DEF_ADRESS=>'street'
153 ,ATTR_DEF_POSTCODE=>'postalzone'
154 ,ATTR_DEF_CITY=>'city'
155 ,ATTR_DEF_COUNTRY_CODE=>'country'
156 ,ATTR_DEF_NUMTVA=>'customer_vat_id'
157 ,ATTR_DEF_PEPPOLID=>'endpoint_id'
158 ];
159
160 foreach ($a_needed as $item=>$value) {
161 if ( trim($this->data['customer'][$value])=="") {
162 $a_error[]=$value;
163 }
164 }
165 if ( $this->data['customer']["endpoint_id"] != "")
166 {
167 // check if peppol id has the form 9999:9999...
168 list($scheme_id,$peppol)=explode(":", $this->data['customer'][$value]);
169 if (preg_replace('/[0-9]/', '', $scheme_id) != "")
170 {
171 $a_error[]='endpoint_id';
172 }elseif(\noalyss_trim($peppol) =="")
173 {
174 $a_error[]='endpoint_id';
175
176 }
177 }
178 if ( $this->data['customer']["customer_vat_id"] != "" && preg_match('/[a-z]{2}/i',$this->data['customer']["customer_vat_id"] ) == false)
179 {
180 $a_error[]='customer_vat_id';
181
182 }
183 return $a_error;
184 }
185
186 /**
187 * @brief transform an operation ($jr_id) into an array, which contains
188 * needed information for making an e-invoice
189 * @param $jr_id (int) operation JRN.JR_ID
190 * @return array with all info7
191 * @param type $jr_id
192 * @see XMLInvoice::build_data
193 */
194 function build_data($jr_id): array
195 {
196
197 $this->data=parent::build_data($jr_id);
198 return $this->data;
199 }
200 /**
201 * @brief Information customer
202 */
203 function build_customer()
204 {
205
206 $customer=$this->createElement('cac:AccountingCustomerParty');
207 $customer_party=$customer->appendChild($this->createElement('cac:Party'));
208 list($scheme_id,$peppol)=explode( ":",trim($this->data['customer']['endpoint_id']));
209 $customer_party->appendChild($this->createElement('cbc:EndpointID',$peppol))
210 ->setAttribute('schemeID', $scheme_id);
211
212 $party_name=$this->createElement('cac:PartyName');
213 $party_name->appendChild($this->createElement("cbc:Name", htmlspecialchars($this->data['customer']['name'],ENT_XML1,'UTF-8')));
214 $customer_party->appendChild($party_name);
215 $postal_address=$customer_party->appendChild($this->createElement('cac:PostalAddress'));
216 $postal_address->appendChild($this->createElement("cbc:StreetName", htmlspecialchars($this->data['customer']['street'],ENT_XML1,'UTF-8')));
217 $postal_address->appendChild($this->createElement("cbc:CityName", htmlspecialchars($this->data['customer']['city'],ENT_XML1,'UTF-8')));
218 $postal_address->appendChild($this->createElement("cbc:PostalZone", $this->data['customer']['postalzone']));
219 ///@todo customer = countryCode doit être dans les paramètres (voir upgrade.sql)
220 $country_code =$this->data['customer']['country'];
221 $country=$postal_address->appendChild($this->createElement("cac:Country"));
222
223 $country->appendChild($this->createElement('cbc:IdentificationCode',$country_code));
224 $postal_address->appendChild($country);
225
226 // Tax Schem
227
228
229 $tax=$this->createElement('cac:PartyTaxScheme');
230 $tax->appendChild($this->createElement('cbc:CompanyID',$this->data["customer"]['customer_vat_id']));
231
232 $tax_scheme=$this->createElement('cac:TaxScheme');
233 $tax_scheme->appendChild($this->createElement('cbc:ID',"VAT"));
234 $tax->appendChild($tax_scheme);
235 // LegalEntity
236 $ple=$this->createElement('cac:PartyLegalEntity');
237 ///@todo customer = name doit être fiche
238 $ple->appendChild($this->createElement("cbc:RegistrationName", $this->data['customer']['name']??"ERROR"));
239 ///@todo customer_vat_id = numéro de TVA doit être dans fiche
240 $ple->appendChild($this->createElement("cbc:CompanyID", $this->data['customer']['customer_vat_id']??"ERROR"));
241
242 // assemble supplier
243 $customer_party->appendChild($tax);
244 $customer_party->appendChild($ple);
245 $customer->appendChild($customer_party);
246 return $customer;
247 }
248 /**
249 * @brief Build XML Block for payment
250 * @code
251 <cac:PaymentMeans>
252 <cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
253 <cbc:PaymentID>Invoice 2019000005</cbc:PaymentID>
254 <cac:PayeeFinancialAccount>
255 <cbc:ID>BE54000000000097</cbc:ID>
256 <cac:FinancialInstitutionBranch>
257 <cbc:ID>BPOTBEB1</cbc:ID>
258 </cac:FinancialInstitutionBranch>
259 </cac:PayeeFinancialAccount>
260 </cac:PaymentMeans>
261 * @endcode
262 */
264 {
265 $company = $this->load_noalyss_parameter();
266 $payment=$this->createElement("cac:PaymentMeans");
267 $payment->appendChild($this->createElement('cbc:PaymentMeansCode',30));
268 ///@note cbc:PaymentID est la communication lors du paiement
269 $payment->appendChild($this->createElement('cbc:PaymentID', htmlspecialchars($this->data["info"]['communication'],ENT_XML1,'UTF-8')));
270 $f=$this->createElement ('cac:PayeeFinancialAccount');
271 ///@todo customer = IBAN doit être dans les paramètres (voir upgrade.sql)
272 $f->appendChild($this->createElement("cbc:ID",$company['COMPANY_BANK_IBAN']));
273 $g=$this->createElement("cac:FinancialInstitutionBranch");
274 $g->appendChild($this->createElement("cbc:ID", $company['COMPANY_BANK_BIC']));
275 $f->appendChild($g);
276
277 $payment->appendChild($f);
278 return $payment;
279 }
280 /**
281 * @brief Information supplier
282 */
283 function build_supplier()
284 {
285 $company = $this->load_noalyss_parameter();
286
287 $supplier=$this->createElement('cac:AccountingSupplierParty');
288 $supplier_party=$supplier->appendChild($this->createElement('cac:Party'));
289 list($scheme_id,$peppol)=explode( ":",trim($company['COMPANY_PEPPOL_ID']));
290 $supplier_party->appendChild($this->createElement('cbc:EndpointID',$peppol))
291 ->setAttribute('schemeID', $scheme_id);
292
293 //$supplier_party->appendChild($this->createElement('cbc:EndpointID',$this->data["supplier"]['supplier_vat_id']))->setAttribute('schemeID', 9925);
294 $party_name=$this->createElement('cac:PartyName');
295 $party_name->appendChild($this->createElement('cbc:Name', htmlspecialchars($this->data['supplier']['name'],ENT_XML1,'UTF-8')));
296 $supplier_party->appendChild($party_name);
297 $postal_address=$supplier_party->appendChild($this->createElement('cac:PostalAddress'));
298 $postal_address->appendChild($this->createElement("cbc:StreetName", htmlspecialchars($this->data['supplier']['street'],ENT_XML1,'UTF-8')));
299 $postal_address->appendChild($this->createElement("cbc:CityName", htmlspecialchars ($this->data['supplier']['city'],ENT_XML1,'UTF-8')));
300 $postal_address->appendChild($this->createElement("cbc:PostalZone", $this->data['supplier']['postalzone']));
301 $country_code = $company['MY_COUNTRY_CODE'];
302 $country=$postal_address->appendChild($this->createElement("cac:Country"));
303 $country->appendChild($this->createElement('cbc:IdentificationCode',$country_code??"ERROR"));
304 $postal_address->appendChild($country);
305
306 // Tax Schem
307 $tax=$this->createElement('cac:PartyTaxScheme');
308 $tax->appendChild($this->createElement('cbc:CompanyID',$this->data["supplier"]['supplier_vat_id']));
309 $tax_scheme=$this->createElement('cac:TaxScheme');
310 $tax_scheme->appendChild($this->createElement('cbc:ID',"VAT"));
311 $tax->appendChild($tax_scheme);
312 // LegalEntity
313 $ple=$this->createElement('cac:PartyLegalEntity');
314 $ple->appendChild($this->createElement("cbc:RegistrationName", htmlspecialchars($company['COMPANY_LEGAL_REGISTRATION']??"ERROR",ENT_XML1,'UTF-8')));
315 $ple->appendChild($this->createElement("cbc:CompanyID", $this->data['supplier']['supplier_vat_id']??"ERROR"));
316 $ple->appendChild($this->createElement("cbc:CompanyLegalForm", $company['COMPANY_LEGAL_ENTITY']??"ERROR"));
317 $contact=$this->createElement('cac:Contact');
318 $contact->appendChild($this->createElement("cbc:Name",$company['INVOICE_CONTACT_NAME']??"ERROR"));
319 $contact->appendChild($this->createElement("cbc:ElectronicMail",$company['INVOICE_EMAIL_COMPANY']??"ERROR"));
320
321 // assemble supplier
322 $supplier_party->appendChild($tax);
323 $supplier_party->appendChild($ple);
324 $supplier_party->appendChild($contact);
325 $supplier->appendChild($supplier_party);
326
327
328 return $supplier;
329 }
330 /**
331 * @brief TaxTotal Block
332 * @code
333 <cac:TaxTotal>
334 <cbc:TaxAmount currencyID="EUR">516</cbc:TaxAmount>
335 <cac:TaxSubtotal>
336 <cbc:TaxableAmount currencyID="EUR">2400</cbc:TaxableAmount>
337 <cbc:TaxAmount currencyID="EUR">504</cbc:TaxAmount>
338 <cac:TaxCategory>
339 <cbc:ID>S</cbc:ID>
340 <cbc:Percent>21</cbc:Percent>
341 <cac:TaxScheme>
342 <cbc:ID>VAT</cbc:ID>
343 </cac:TaxScheme>
344 </cac:TaxCategory>
345 </cac:TaxSubtotal>
346 <cac:TaxSubtotal>
347 <cbc:TaxableAmount currencyID="EUR">200</cbc:TaxableAmount>
348 <cbc:TaxAmount currencyID="EUR">12</cbc:TaxAmount>
349 <cac:TaxCategory>
350 <cbc:ID>S</cbc:ID>
351 <cbc:Percent>6</cbc:Percent>
352 if ID !=Z and ID != S <cbc:TaxExemptionReasonCode
353 <cac:TaxScheme>
354 <cbc:ID>VAT</cbc:ID>
355 </cac:TaxScheme>
356 </cac:TaxCategory>
357 </cac:TaxSubtotal>
358 </cac:TaxTotal>
359 * @endcode
360 */
361 function build_taxTotal()
362 {
363 $taxTotal=$this->createElement("cac:TaxTotal");
364 $taxTotal->appendChild($this->createElement('cbc:TaxAmount',sprintf("%.2f",$this->data['TaxAmount'])))
365 ->setAttribute("currencyID",$this->data['currency']);
366 // for subTotal
367 $subTotal=$this->data['subTotalVAT'];
368 $nb_sub=count($subTotal);
369 for ($i=0;$i<$nb_sub;$i++) {
370 $subTotalXML=$this->createElement("cac:TaxSubtotal");
371 $subTotalXML->appendChild($this->createElement('cbc:TaxableAmount',sprintf("%.2f",$subTotal[$i]['amount'])))
372 ->setAttribute("currencyID", $this->data['currency']);
373 $subTotalXML->appendChild($this->createElement('cbc:TaxAmount',sprintf("%.2f",$subTotal[$i]['vat'])))
374 ->setAttribute("currencyID",$this->data['currency']);
375 $taxCategory=$this->createElement("cac:TaxCategory");
376 $taxCategory->appendChild($this->createElement("cbc:ID",$subTotal[$i]['vat_code']));
377 $taxCategory->appendChild($this->createElement("cbc:Percent",sprintf("%.2f",$subTotal[$i]['percent'])));
378 if ($subTotal[$i]['vat_code'] != "S"
379 && $subTotal[$i]['vat_code'] != "Z")
380 {
381 // if cbc:ID not S and not Z then exemption VAT code is needed
382 $taxCategory->appendChild($this->createElement("cbc:TaxExemptionReasonCode",$subTotal[$i]['vatex']));
383 }
384 $taxScheme=$this->createElement("cac:TaxScheme");
385 $taxScheme->appendChild($this->createElement("cbc:ID", "VAT"));
386 $taxCategory->appendChild($taxScheme);
387 $subTotalXML->appendChild($taxCategory);
388 $taxTotal->appendChild($subTotalXML);
389 }
390
391
392 return $taxTotal;
393 }
394 /**
395 * @brief legalMonetaryTotal
396 * @code
397 <cac:LegalMonetaryTotal>
398 <cbc:LineExtensionAmount currencyID="EUR">2600</cbc:LineExtensionAmount>
399 <cbc:TaxExclusiveAmount currencyID="EUR">2600</cbc:TaxExclusiveAmount>
400 <cbc:TaxInclusiveAmount currencyID="EUR">3116</cbc:TaxInclusiveAmount>
401 <cbc:PayableAmount currencyID="EUR">3116</cbc:PayableAmount>
402 </cac:LegalMonetaryTotal>
403 * @endcode
404 */
406 {
407 $result=$this->createElement('cac:LegalMonetaryTotal' );
408 $result->appendChild($this->createElement("cbc:LineExtensionAmount",sprintf("%.2f",$this->data['LineExtensionAmount'])))
409 ->setAttribute("currencyID",$this->data['currency']);
410 $result->appendChild($this->createElement("cbc:TaxExclusiveAmount",sprintf("%.2f",$this->data['TaxExclusiveAmount'])))
411 ->setAttribute("currencyID",$this->data['currency']);
412 $result->appendChild($this->createElement("cbc:TaxInclusiveAmount",sprintf("%.2f",$this->data['TaxInclusiveAmount'])))
413 ->setAttribute("currencyID", $this->data['currency'] );
414 $result->appendChild($this->createElement("cbc:PayableAmount",sprintf("%.2f",$this->data['PayableAmount'])))
415 ->setAttribute("currencyID", $this->data['currency'] );
416 return $result;
417
418 }
419 /**
420 * @brief cac:InvoiceLine
421 * @code
422 <cac:InvoiceLine>
423 <cbc:ID>2</cbc:ID>
424 <cbc:InvoicedQuantity unitCode="C62">10</cbc:InvoicedQuantity>
425 <cbc:LineExtensionAmount currencyID="EUR">200</cbc:LineExtensionAmount>
426 <cac:Item>
427 <cbc:Name>Good X</cbc:Name>
428 <cac:ClassifiedTaxCategory>
429 <cbc:ID>S</cbc:ID>
430 <cbc:Percent>6</cbc:Percent>
431 <cac:TaxScheme>
432 <cbc:ID>VAT</cbc:ID>
433 </cac:TaxScheme>
434 </cac:ClassifiedTaxCategory>
435 </cac:Item>
436 <cac:Price>
437 <cbc:PriceAmount currencyID="EUR">20</cbc:PriceAmount>
438 </cac:Price>
439 </cac:InvoiceLine>
440 * @endcode
441 * @param $i (int) idx f $this->data->operation[$i]
442 *
443 */
445 {
446
447 $result=$this->createElement('cac:InvoiceLine');
448 $row=$this->data["operation"][$i];
449 $amount=sprintf("%.2f",$row['price']);
450
451 $result->appendChild($this->createElement("cbc:ID", $i));
452 $amount=sprintf("%.2f",$row['price']);
453 $result->appendChild(
454 $this->createElement("cbc:InvoicedQuantity", sprintf("%.2f",$row['quantity'])))
455 ->setAttribute("unitCode", $row["code_quantity"]);
456 $result->appendChild($this->createElement("cbc:LineExtensionAmount", $amount))
457 ->setAttribute("currencyID",$this->data['currency']);
458
459 // ITEM
460 $item=$this->createElement("cac:Item");
461 $item->appendChild($this->createElement("cbc:Description",htmlspecialchars($row['description'],ENT_XML1,'UTF-8')));
462 $item->appendChild($this->createElement("cbc:Name", $row['qcode']));
463 $classifiedTaxCat=$this->createElement("cac:ClassifiedTaxCategory");
464
465 //cbc:ID S = standard rate
466 /// see TVA_RATE.TVA_PEPPOL_CODE & C0TVA
467 $classifiedTaxCat->appendChild($this->createElement("cbc:ID", $row['vat_code']));
468 $classifiedTaxCat->appendChild($this->createElement("cbc:Percent", sprintf("%.2f",$row['vat_percent'])));
469
470 $tax_scheme=$this->createElement('cac:TaxScheme');
471 $tax_scheme->appendChild($this->createElement("cbc:ID", "VAT"));
472 $classifiedTaxCat->appendChild($tax_scheme);
473 $item->appendChild($classifiedTaxCat);
474 $result->appendChild($item);
475 $price=$result->appendChild($this->createElement("cac:Price"));
476 $price->appendChild($this->createElement("cbc:PriceAmount",sprintf("%.2f",abs($row['price_unit']))))
477 ->setAttribute("currencyID",$this->data['currency']);
478 $result->appendChild($price);
479
480 return $result;
481
482 }
483 /**
484 * @brief Insert a PDF in the XML
485 * the document type is not needed for BELGIUM
486 */
487 /**
488 *
489@code
490 <cac:AdditionalDocumentReference>
491 <cbc:ID>P01</cbc:ID>
492 <cbc:DocumentDescription>Facture PDF</cbc:DocumentDescription>
493 <cac:Attachment>
494 <cbc:EmbeddedDocumentBinaryObject
495 mimeCode="application/pdf"
496 filename="invoice.pdf">$base64Pdf</cbc:EmbeddedDocumentBinaryObject>
497 </cac:Attachment>
498 </cac:AdditionalDocumentReference>
499 <!-- OU -->
500 <cac:AdditionalDocumentReference>
501 <cbc:ID>REF_ODT_001</cbc:ID>
502 <cbc:DocumentDescription>Fichier OpenDocument</cbc:DocumentDescription>
503 <cac:Attachment>
504 <cbc:EmbeddedDocumentBinaryObject
505 mimeCode="application/vnd.oasis.opendocument.text"
506 filename="facture.odt">[base64-encodage du fichier]</cbc:EmbeddedDocumentBinaryObject>
507 </cac:Attachment>
508</cac:AdditionalDocumentReference>
509
510
511@endcode
512 * @return \DOMElement
513 */
514 function build_Invoice():\DOMElement
515 {
516 if ( $this->pdf_filename == "") return null;
517 /** $pdf_filename = 'chemin/vers/votre/fichier.pdf';*/
518 static $i=0;
519 $i++;
520 if ( $this->pdf_filename == null ) {
521 return null;
522 }
523 // Lire le fichier PDF
524 $pdfContent = file_get_contents( $this->pdf_filename );
525
526 $result=$this->createElement("cac:AdditionalDocumentReference");
527 $id=$this->createElement("cbc:ID",$i);
528 $document_description=$this->createElement("cbc:DocumentDescription"
529 , htmlspecialchars($this->data['description'],ENT_XML1,'UTF-8'));
530
531 // PDF in base64
532 $base64Pdf = base64_encode($pdfContent);
533 $embeddedDocument=$this->createElement("cbc:EmbeddedDocumentBinaryObject",$base64Pdf);
534 $embeddedDocument->setAttribute("mimeCode", "application/pdf");
535 $embeddedDocument->setAttribute("filename", "facture.pdf");
536 $attachment=$this->createElement("cac:Attachment");
537 $attachment->appendChild($embeddedDocument);
538
539 $result->appendChild($id);
540 $result->appendChild($document_description);
541 $result->appendChild($attachment);
542
543 return $result;
544 }
545 /**
546 * @brief Insert a PDF in the XML
547 * the document type is not needed for BELGIUM
548 */
549 /**
550 *
551@code
552 <cac:AdditionalDocumentReference>
553 <cbc:ID>P01</cbc:ID>
554 <cbc:DocumentDescription>Facture PDF</cbc:DocumentDescription>
555 <cac:Attachment>
556 <cbc:EmbeddedDocumentBinaryObject
557 mimeCode="application/pdf"
558 filename="invoice.pdf">$base64Pdf</cbc:EmbeddedDocumentBinaryObject>
559 </cac:Attachment>
560 </cac:AdditionalDocumentReference>
561 <!-- OU -->
562 <cac:AdditionalDocumentReference>
563 <cbc:ID>REF_ODT_001</cbc:ID>
564 <cbc:DocumentDescription>Fichier OpenDocument</cbc:DocumentDescription>
565 <cac:Attachment>
566 <cbc:EmbeddedDocumentBinaryObject
567 mimeCode="application/vnd.oasis.opendocument.text"
568 filename="facture.odt">[base64-encodage du fichier]</cbc:EmbeddedDocumentBinaryObject>
569 </cac:Attachment>
570</cac:AdditionalDocumentReference>
571
572
573@endcode
574 * @return \DOMElement
575 */
576 function include_document($i):\DOMElement
577 {
578
579 $pdfContent=$this->cn->lo_read($this->data['document'][$i]['oid']);
580 // Lire le fichier PDF
581
582 $result=$this->createElement("cac:AdditionalDocumentReference");
583 $id=$this->createElement("cbc:ID",sprintf("SD%d",$i));
584 $d=( $this->data['document'][$i]['description'] == "")?"NONE":$this->data['document'][$i]['description'];
585 $document_description=$this->createElement("cbc:DocumentDescription"
586 ,htmlspecialchars($d ,ENT_XML1,'UTF-8'));
587
588 // PDF in base64
589 $base64Pdf = base64_encode($pdfContent);
590 $embeddedDocument=$this->createElement("cbc:EmbeddedDocumentBinaryObject",$base64Pdf);
591 $embeddedDocument->setAttribute("mimeCode", "application/pdf");
592 $embeddedDocument->setAttribute("filename", $this->data['document'][$i]['filename']);
593 $attachment=$this->createElement("cac:Attachment");
594 $attachment->appendChild($embeddedDocument);
595
596 $result->appendChild($id);
597 $result->appendChild($document_description);
598 $result->appendChild($attachment);
599
600 return $result;
601 }
602 /**
603 * @brief create an XML invoice(UBL2.1) based on JRN.JR_ID operation
604 * @parameter $jr_id (int) operation JRN.JR_ID operation
605 * @return XML String
606 */
607 function make_xml($jr_id)
608 {
609
610
611 $this->data = $this->build_data($jr_id);
612
613 // var $company (array) all the parameters of the company
614 $company = $this->load_noalyss_parameter();
615
616 // HEADER
617 $root=$this->createElementNS('urn:oasis:names:specification:ubl:schema:xsd:Invoice-2',"Invoice",);
618 $root->setAttributeNS('http://www.w3.org/2000/xmlns/',"xmlns:cac", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2");
619 $root->setAttributeNS('http://www.w3.org/2000/xmlns/',"xmlns:cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2");
620 $root->appendChild($this->createElement('cbc:CustomizationID',"urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0"));
621 $root->appendChild($this->createElement('cbc:ProfileID',"urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"));
622
623 $root->appendChild($this->createElement('cbc:ID',$this->data['id']));
624 $root->appendChild($this->createElement('cbc:IssueDate',$this->data['issue_date']));
625 if ($this->data ['due_date'] == '')
626 {
627 $this->data ['due_date']=$this->data['issue_date'];
628 }
629 $root->appendChild($this->createElement('cbc:DueDate',$this->data['due_date']));
630 $root->appendChild($this->createElement('cbc:InvoiceTypeCode',380));
631 /**
632 * add note if any
633 */
634 if ( $this->data['note'] != "")
635 {
636 $root->appendChild($this->createElement("cbc:Note", htmlspecialchars($this->data['note'],ENT_XML1,'UTF-8')));
637 }
638 $root->appendChild($this->createElement('cbc:DocumentCurrencyCode',$this->data['currency']));
639 $root->appendChild($this->createElement('cbc:BuyerReference', htmlspecialchars($this->data['info']['order'],ENT_XML1,'UTF-8')));
640 /**
641 * insert PDF in the XML
642 */
643 $x = $this->build_Invoice();
644 if ($x != null ) {
645 $root->appendChild($x);
646 }
647 /**
648 * insert all Additionnal documents if any
649 */
650 $nb_document=count($this->data['document']);
651 for ($z=0;$z <$nb_document;$z++)
652 {
653 $x= $this->include_document($z);
654 $root->appendChild($x);
655 }
656
657 // add the supplier
658 $root->appendChild($this->build_supplier());
659 // add the customer
660 $root->appendChild($this->build_customer());
661
662 // add the payment if there is a bank account
663 if ( $company['COMPANY_BANK_IBAN'] != "")
664 $root->appendChild($this->build_paymentInfo());
665
666 // Add cac:TaxTotal
667 $root->appendChild($this->build_taxTotal());
668
669 // Add cac:LegalMonetatyTotal
670 $root->appendChild($this->build_legalMonetaryTotal());
671
672 // add all the invoiceline
673 // operation
674 $nb_operation=count($this->data["operation"]);
675 for ($i=0;$i < $nb_operation ; $i++) {
676 $root->appendChild($this->build_invoiceLine($i));
677
678 }
679
680 $this->append($root);
681 $this->formatOutput=true;
682 return $this->saveXML();
683 }
684 /**
685 * @brief create the invoice in the right format, with PDF if any
686 * @param $operation_id (int) JRN.JR_ID
687 * @return string XML Invoice
688 */
690 return $this->make_xml($operation_id);
691 }
692}
noalyss_trim($p_string)
$input_from cn
_("actif, passif,charge,...")
static build($db, $p_code)
retrieve TVA rate thanks the code that could be the tva_id or tva_code.
$pdf_filename
PDF file to insert into XML,.
build_data($jr_id)
transform an operation ($jr_id) into an array, which contains needed information for making an e-invo...
check_customer_data()
check that mandatory info are saved in the DB for customer
check_company_data()
check that mandatory info are saved in the DB for company (seller)
create_invoice($operation_id)
create the invoice in the right format, with PDF if any
check_VAT()
check that the VAT is using a PEPPOL Code
include_document($i)
Insert a PDF in the XML the document type is not needed for BELGIUM.
display_error()
display_error display a warning with all error
build_paymentInfo()
Build XML Block for payment.
make_xml($jr_id)
create an XML invoice(UBL2.1) based on JRN.JR_ID operation @parameter $jr_id (int) operation JRN....
build_Invoice()
Insert a PDF in the XML the document type is not needed for BELGIUM.
Mother class for e-invoice.
$jr_id
$data (Array) data retrieve from DB
load_noalyss_parameter()
make an array of parameter_extra where pe_code as key and pe_value as value
$country_code
const ATTR_DEF_ADRESS
Definition constant.php:230
const ATTR_DEF_NUMTVA
Definition constant.php:229
const ATTR_DEF_NAME
Definition constant.php:223
const ATTR_DEF_COUNTRY_CODE
Definition constant.php:255
const ATTR_DEF_PEPPOLID
Definition constant.php:256
const ATTR_DEF_POSTCODE
Definition constant.php:231
const ATTR_DEF_CITY
Definition constant.php:236
if( $delta< 0) elseif( $delta==0)
$nb_operation