Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IP-939]: Implementing e-invoicing flow #977

Open
wants to merge 9 commits into
base: development
Choose a base branch
from
16 changes: 16 additions & 0 deletions application/helpers/XMLconfigs/About e-Invoicing templates.md
@@ -0,0 +1,16 @@
# How to: Adding e-Invoicing XML-templates

To implement a new e-invoicing xml template, there are 2 files that need to be placed in their respective folder.
Add the configuration file ("Shortidv10.php") in the folder "helpers/XMLconfigs/" and the xml-template file ("Shortidv10Xml.php") in the folder "libraries/XMLtemplates".
It is important to make the file names as short as possible and preferably use only numbers and letters.
Each country has its format specifications and version on which it is best to base the shortened name.

E.g. for Germany, the most commonly used format for B2B is Zugferd.
The version number of the Zugferd template used in IP is version 1.0.
So the abbreviated name for this xml template will be "Zugferdv10".
- Add ".php" to the configuration file and "Xml.php" to the xml template file.
- Then copy "Zugferdv10.php" into the "helpers/XMLconfigs" folder and "Zugferdv10Xml.php" into the "libraries/XMLtemplate" folder.

The configuration file contains explanations of the config items.
In the included examples (Ublexamv20Xml.php and Zugferdv10Xml.php) you can find information that can help you create the proper XML template.
Specific explanations about the correct e-invoicing format for a particular country (of your customer) can be found online on a government website, in principle.
14 changes: 14 additions & 0 deletions application/helpers/XMLconfigs/Ublexamv20.php
@@ -0,0 +1,14 @@
<?php

// Filename => 'Ublexamv20.php' -> "Shortid" + "version" + ".php"
// (preferably without spaces " ", dots ".", hyphen "-", underscore "_" or special characters)

// 'full-name' => 'UBL example v2.0', -> UBL version name visible in the clients drop-down menu
// 'countrycode' => 'EX', -> associated countrycode (if available in your native language country list)
// 'embedXML' => false, -> for 'Zugferd' (and similar = Xml embedded in Pdf) set to true

$xml_setting = array(
'full-name' => 'UBL example v2.0',
'countrycode' => 'EX',
'embedXML' => false,
);
14 changes: 14 additions & 0 deletions application/helpers/XMLconfigs/Zugferdv10.php
@@ -0,0 +1,14 @@
<?php

// Filename => 'Ublexamv20.php' -> "Shortid" + "version" + ".php"
// (preferably without spaces " ", dots ".", hyphen "-", underscore "_" or special characters)

// 'full-name' => 'UBL example v2.0', -> UBL version name visible in the clients drop-down menu
// 'countrycode' => 'EX', -> associated countrycode (if available in your native language country list)
// 'embedXML' => false, -> for 'Zugferd' (and similar = Xml embedded in Pdf) set to true

$xml_setting = array(
'full-name' => 'ZUGFeRD v1.0',
'countrycode' => 'DE',
'embedXML' => true,
);
75 changes: 75 additions & 0 deletions application/helpers/e-invoice_helper.php
@@ -0,0 +1,75 @@
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');

/*
* InvoicePlane
*
* @author InvoicePlane Developers & Contributors
* @copyright Copyright (c) 2012 - 2018 InvoicePlane.com
* @license https://invoiceplane.com/license.txt
* @link https://invoiceplane.com
* @added Verony-makesIT 2023
*/

function generate_xml_invoice_file($invoice, $items, $xml_lib, $filename)
{
$CI = &get_instance();

$CI->load->library('XMLtemplates/'.$xml_lib.'Xml', array('invoice' => $invoice, 'items' => $items, 'filename' => $filename), 'ublciixml');
$CI->ublciixml->xml();
$path = './uploads/temp/' . $filename . '.xml';

return $path;
}

function include_rdf($filename)
{
$s = '<rdf:Description rdf:about="" xmlns:zf="urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#">' . "\n";
$s .= ' <zf:DocumentType>INVOICE</zf:DocumentType>' . "\n";
$s .= ' <zf:DocumentFileName>ZUGFeRD-invoice.xml</zf:DocumentFileName>' . "\n";
// $s .= ' <zf:DocumentFileName>'. $filename .'</zf:DocumentFileName>' . "\n";
$s .= ' <zf:Version>1.0</zf:Version>' . "\n";
$s .= ' <zf:ConformanceLevel>COMFORT</zf:ConformanceLevel>' . "\n";
$s .= '</rdf:Description>' . "\n";
return $s;
}

/**
* Returns all available xml-template items.
*
* @return array
*/
function get_xml_template_files()
{
$path = APPPATH . 'libraries/XMLtemplates';
$xml_template_files = array_diff(scandir($path), array('.', '..'));

foreach ($xml_template_files as $key => $xml_template_file) {
$xml_template_files[$key] = str_replace('Xml.php', '', $xml_template_file);

if (file_exists(APPPATH . 'helpers/XMLconfigs/' . $xml_template_files[$key] . '.php')) {
include APPPATH . 'helpers/XMLconfigs/' . $xml_template_files[$key] . '.php';

$xml_template_items[$xml_template_files[$key]] = $xml_setting['full-name'] ." - ". get_country_name(trans('cldr'), $xml_setting['countrycode']);
}
}

return $xml_template_items;
}

/**
* Returns the XML template (UBL / CII) fullname of a given client_e-invoice_version value.
*
* @param $xml_Id
* @return mixed
*/
function get_xml_full_name($xml_id)
{

if (file_exists(APPPATH . 'helpers/XMLconfigs/' . $xml_id . '.php')) {
include APPPATH . 'helpers/XMLconfigs/' . $xml_id . '.php';

return ($xml_setting['full-name'] ." - ". get_country_name(trans('cldr'), $xml_setting['countrycode']));
}

}
15 changes: 8 additions & 7 deletions application/helpers/mpdf_helper.php
Expand Up @@ -19,7 +19,7 @@
* @param null $password
* @param null $isInvoice
* @param null $is_guest
* @param bool $zugferd_invoice
* @param bool $embed_xml
* @param null $associated_files
*
* @return string
Expand All @@ -32,7 +32,7 @@ function pdf_create(
$password = null,
$isInvoice = null,
$is_guest = null,
$zugferd_invoice = false,
$embed_xml = false, // eInvoicing++
$associated_files = null
) {
$CI = &get_instance();
Expand All @@ -57,12 +57,12 @@ function pdf_create(
$mpdf->showImageErrors = true;
}

// Include zugferd if enabled
if ($zugferd_invoice) {
$CI->load->helper('zugferd');
// Include (zugferd?) XML if enabled for the client // eInvoicing++
if ($embed_xml) { // eInvoicing++
$CI->load->helper('e-invoice'); // eInvoicing++
$mpdf->PDFA = true;
$mpdf->PDFAauto = true;
$mpdf->SetAdditionalXmpRdf(zugferd_rdf());
$mpdf->SetAdditionalXmpRdf(include_rdf($filename)); // eInvoicing++
$mpdf->SetAssociatedFiles($associated_files);
}

Expand Down Expand Up @@ -111,7 +111,8 @@ function pdf_create(
}
}

$archived_file = UPLOADS_ARCHIVE_FOLDER . date('Y-m-d') . '_' . $filename . '.pdf';
// $archived_file = UPLOADS_ARCHIVE_FOLDER . date('Y-m-d') . '_' . $filename . '.pdf';
$archived_file = UPLOADS_ARCHIVE_FOLDER . $filename . '.pdf'; // eInvoicing++
$mpdf->Output($archived_file, 'F');

if ($stream) {
Expand Down
49 changes: 35 additions & 14 deletions application/helpers/pdf_helper.php
Expand Up @@ -31,6 +31,7 @@ function generate_invoice_pdf($invoice_id, $stream = true, $invoice_template = n

$CI->load->helper('country');
$CI->load->helper('client');
$CI->load->helper('e-invoice'); // eInvoicing++

$invoice = $CI->mdl_invoices->get_by_id($invoice_id);
$invoice = $CI->mdl_invoices->get_payments($invoice);
Expand Down Expand Up @@ -70,23 +71,30 @@ function generate_invoice_pdf($invoice_id, $stream = true, $invoice_template = n
$custom_fields['quote'] = $CI->mdl_custom_fields->get_values_for_fields('mdl_quote_custom', $invoice->quote_id);
}

// PDF associated files
$include_zugferd = $CI->mdl_settings->setting('include_zugferd');
// START eInvoicing++ changes
$replace = array('.', ' ', '/', '\\', '#');
$filename = str_replace($replace, '', $invoice->user_vat_id) . '_' . str_replace($replace, '', $invoice->invoice_number);

if ($include_zugferd) {
$CI->load->helper('zugferd');
// Generate the appropriate UBL/CII
$xml_id = $invoice->client_einvoice_version;
$embed_xml = '';
if (file_exists(APPPATH . 'helpers/XMLconfigs/' . $xml_id . '.php')) {
include APPPATH . 'helpers/XMLconfigs/' . $xml_id . '.php';

$associatedFiles = array(
array(
$embed_xml = $xml_setting['embedXML'];
}

// PDF associated or embedded (Zugferd) Xml file
$associatedFiles = null;
if ($embed_xml) {
// Create the CII XML file
$associatedFiles = array(array(
'name' => 'ZUGFeRD-invoice.xml',
'description' => 'ZUGFeRD Invoice',
'description' => $xml_id .' CII Invoice',
'AFRelationship' => 'Alternative',
'mime' => 'text/xml',
'path' => generate_invoice_zugferd_xml_temp_file($invoice, $items)
)
);
} else {
$associatedFiles = null;
'path' => generate_xml_invoice_file($invoice, $items, $xml_id, $filename),
));
}

$data = array(
Expand All @@ -101,9 +109,22 @@ function generate_invoice_pdf($invoice_id, $stream = true, $invoice_template = n

$html = $CI->load->view('invoice_templates/pdf/' . $invoice_template, $data, true);

// Create PDF with or without an embedded XML
$CI->load->helper('mpdf');
return pdf_create($html, trans('invoice') . '_' . str_replace(array('\\', '/'), '_', $invoice->invoice_number),
$stream, $invoice->invoice_password, true, $is_guest, $include_zugferd, $associatedFiles);
$retval = pdf_create($html, $filename, $stream, $invoice->invoice_password, true, $is_guest, $embed_xml, $associatedFiles);

// Delete the tmp (zugferd) XML file if exist
if (file_exists('./uploads/temp/' . $filename . '.xml')) {
unlink('./uploads/temp/' . $filename . '.xml');
}
// Create the UBL XML file
if ($xml_id != '' && $embed_xml != 'true') {
$path = generate_xml_invoice_file($invoice, $items, $xml_id, $filename);
}

// END eInvoicing++ changes
return $retval;

}

function generate_invoice_sumex($invoice_id, $stream = true, $client = false)
Expand Down
45 changes: 0 additions & 45 deletions application/helpers/zugferd_helper.php

This file was deleted.

10 changes: 9 additions & 1 deletion application/language/english/ip_lang.php
Expand Up @@ -35,6 +35,8 @@
'automatic_email_on_recur' => 'Automatically Email recurring invoices',
'balance' => 'Balance',
'back' => 'Back',
'bank' => 'Bank',
'bank_information' => 'Bank Information',
'base_invoice' => 'Base Invoice',
'bcc' => 'BCC',
'bcc_mails_to_admin' => 'Send all outgoing emails as BCC to the admin account',
Expand Down Expand Up @@ -96,6 +98,7 @@
'company' => 'Company',
'confirm' => 'Confirm',
'confirm_deletion' => 'Confirm deletion',
'contact' => 'Contact',
'contact_information' => 'Contact Information',
'continue' => 'Continue',
'copy_invoice' => 'Copy Invoice',
Expand Down Expand Up @@ -281,6 +284,7 @@
'invoiceplane_news' => 'InvoicePlane News',
'invoices' => 'Invoices',
'invoices_due_after' => 'Invoices Due After (Days)',
'invoicing' => 'Invoicing',
'is_not_writable' => 'is not writable',
'is_writable' => 'is writable',
'item' => 'Item',
Expand Down Expand Up @@ -332,7 +336,7 @@
'no_overdue_invoices' => 'No overdue Invoices',
'no_quotes_requiring_approval' => 'There are no quotes requiring approval.',
'no_updates_available' => 'No updates available.',
'no_update_invoice_due_date_mail' => 'Disable the change of invoice date and due date before emailing',
'no_update_invoice_due_date_mail' => 'Disable the change of invoice date and due date before emailing',
'none' => 'None',
'note' => 'Note',
'notes' => 'Notes',
Expand Down Expand Up @@ -458,6 +462,7 @@
'reject' => 'Reject',
'reject_this_quote' => 'Reject This Quote',
'rejected' => 'Rejected',
'remittance' => 'Remittance',
'remove' => 'Remove',
'remove_logo' => 'Remove Logo',
'report_options' => 'Report Options',
Expand Down Expand Up @@ -575,6 +580,7 @@
'total_paid' => 'Total Paid',
'try_again' => 'Try Again',
'type' => 'Type',
'ubl_cii_select_help' => 'Select the correct UBL or CII version for your customer or his country. The application will create and send the Pdf and XML-file.',
'unknown' => 'Unknown',
'updatecheck' => 'Updatecheck',
'updatecheck_failed' => 'Updatecheck failed! Check your network connection.',
Expand All @@ -585,6 +591,7 @@
'user_form' => 'User Form',
'user_type' => 'User Type',
'username' => 'Username',
'user_remittance_tmpl' => 'User Remittance Template Tag(s)',
'users' => 'Users',
'unit' => 'Unit',
'units' => 'Units',
Expand All @@ -598,6 +605,7 @@
'vat_id' => 'VAT ID',
'vat_id_short' => 'VAT',
'verify_password' => 'Verify Password',
'version' => 'version',
'version_history' => 'Version History',
'view' => 'View',
'view_all' => 'View All',
Expand Down