2
0
forked from Wavyzz/dolibarr

NEW Support the Swiss QR-Code

This commit is contained in:
Laurent Destailleur
2022-06-19 13:06:07 +02:00
parent 3e34c2cab2
commit 233d712e39
10 changed files with 148 additions and 20 deletions

View File

@@ -13,6 +13,7 @@ NEW: PHP 8.1 compatibility
NEW: Support for recurring purchase invoices.
NEW: #20292 Include German public holidays
NEW: Can show ZATCA QRCode on PDFs
NEW: Can show Swiss QR Code on PDFs
NEW: #17123 added ExtraFields for Stock Mouvement
NEW: #20609 : new massaction to assign a sale representatives on a selection of thirdparties
NEW: #20653 edit discount pourcentage for all lines in one shot

View File

@@ -20,3 +20,9 @@ https://www.pwc.com/m1/en/services/tax/me-tax-legal-news/2021/saudi-arabia-guide
https://www.tecklenborgh.com/post/ksa-zatca-publishes-guide-on-how-to-develop-a-fatoora-compliant-qr-code
Method to encode/decode ZATCA string is available in test/phpunit/BarcodeTest.php
* FOR QR-Bill in switzerland
----------------------------
Syntax of QR Code https://www.swiss-qr-invoice.org/fr/
Syntax of complentary field named "structured information of invoice S1": https://www.swiss-qr-invoice.org/downloads/qr-bill-s1-syntax-fr.pdf

View File

@@ -62,6 +62,11 @@ if ($action == 'update') {
}
if (GETPOSTISSET('INVOICE_ADD_ZATCA_QR_CODE')) {
dolibarr_set_const($db, "INVOICE_ADD_ZATCA_QR_CODE", GETPOST("INVOICE_ADD_ZATCA_QR_CODE", 'int'), 'chaine', 0, '', $conf->entity);
dolibarr_del_const($db, "INVOICE_ADD_SWISS_QR_CODE", $conf->entity);
}
if (GETPOSTISSET('INVOICE_ADD_SWISS_QR_CODE')) {
dolibarr_set_const($db, "INVOICE_ADD_SWISS_QR_CODE", GETPOST("INVOICE_ADD_SWISS_QR_CODE", 'int'), 'chaine', 0, '', $conf->entity);
dolibarr_del_const($db, "INVOICE_ADD_ZATCA_QR_CODE", $conf->entity);
}
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
@@ -138,6 +143,17 @@ if (isModEnabled('facture')) {
}
print '</td></tr>';
print '<tr class="oddeven"><td>';
print $form->textwithpicto($langs->trans("INVOICE_ADD_SWISS_QR_CODE"), '');
print '</td><td>';
if ($conf->use_javascript_ajax) {
print ajax_constantonoff('INVOICE_ADD_SWISS_QR_CODE');
} else {
$arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
print $form->selectarray("INVOICE_ADD_SWISS_QR_CODE", $arrval, $conf->global->INVOICE_ADD_SWISS_QR_CODE);
}
print '</td></tr>';
/*
print '<tr class="oddeven"><td>'.$langs->trans("MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING").'</td><td>';
if ($conf->use_javascript_ajax) {

View File

@@ -900,6 +900,94 @@ abstract class CommonInvoice extends CommonObject
return $s;
}
/**
* Build string for QR-Bill (Switzerland)
*
* @return string String for Switzerland QR Code if QR-Bill
*/
public function buildSwitzerlandQRString()
{
global $conf, $mysoc;
$tmplang = new Translate('', $conf);
$tmplang->setDefaultLang('en_US');
$tmplang->load("main");
$pricewithtaxstring = price2num($this->total_ttc, 2, 1);
$pricetaxstring = price2num($this->total_tva, 2, 1);
$complementaryinfo = '';
/*
Example: //S1/10/10201409/11/190512/20/1400.000-53/30/106017086/31/180508/32/7.7/40/2:10;0:30
/10/ Numéro de facture 10201409
/11/ Date de facture 12.05.2019
/20/ Référence client 1400.000-53
/30/ Numéro IDE pour la TVA CHE-106.017.086 TVA
/31/ Date de la prestation pour la comptabilisation de la TVA 08.05.2018
/32/ Taux de TVA sur le montant total de la facture 7.7%
/40/ Conditions 2% descompte à 10 jours, paiement net à 30 jours
*/
$datestring = dol_print_date($this->date, '%y%m%d');
//$pricewithtaxstring = price($this->total_ttc, 0, $tmplang, 0, -1, 2);
//$pricetaxstring = price($this->total_tva, 0, $tmplang, 0, -1, 2);
$complementaryinfo = '//S1/10/'.str_replace('/', '', $this->ref).'/11/'.$datestring;
if ($this->ref_client) {
$complementaryinfo .= '/20/'.$this->ref_client;
}
if ($this->thirdparty->vat_number) {
$complementaryinfo .= '/30/'.$this->thirdparty->vat_number;
}
// Header
$s .= "SPC\n";
$s .= "0200\n";
$s .= "1\n";
if ($this->fk_account > 0) {
// Bank BAN if country is LI or CH
// TODO Add
} else {
$s .= "\n";
}
// Seller
$s .= "S";
$s .= dol_trunc($mysoc->name, 70, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($mysoc->address, 70, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($mysoc->zip, 16, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($mysoc->town, 35, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($mysoc->country_code, 2, 'right', 'UTF-8', 1)."\n";
// Final seller
$s .= "\n";
$s .= "\n";
$s .= "\n";
$s .= "\n";
$s .= "\n";
$s .= "\n";
$s .= "\n";
// Amount of payment (to do?)
$s .= price($pricewithtaxstring, 0, 'none', 0, 0, 2)."\n";
$s .= $this->currency_code."\n";
// Buyer
$s .= "S";
$s .= dol_trunc($this->thirdparty->name, 70, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($this->thirdparty->address, 70, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($this->thirdparty->zip, 16, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($this->thirdparty->town, 35, 'right', 'UTF-8', 1)."\n";
$s .= dol_trunc($this->thirdparty->country_code, 2, 'right', 'UTF-8', 1)."\n";
// ID of payment
$s .= "NON\n"; // NON or QRR
$s .= "\n"; // QR Code if previous field is QRR
if ($complementaryinfo) {
$s .= $complementaryinfo."\n";
} else {
$s .= "\n";
}
$s .= "EPD\n";
$s .= "\n";
//var_dump($s);exit;
return $s;
}
}

View File

@@ -278,7 +278,7 @@ abstract class CommonObject
public $country_id;
/**
* @var string
* @var string The ISO country code on 2 chars.
* @see getFullAddress(), isInEEC(), country
*/
public $country_code;

View File

@@ -5467,7 +5467,7 @@ function vatrate($rate, $addpercent = false, $info_bits = 0, $usestarfornpr = 0)
*
* @param float $amount Amount to format
* @param integer $form Type of format, HTML or not (not by default)
* @param Translate|string $outlangs Object langs for output
* @param Translate|string $outlangs Object langs for output. '' use default lang. 'none' use international separators.
* @param int $trunc 1=Truncate if there is more decimals than MAIN_MAX_DECIMALS_SHOWN (default), 0=Does not truncate. Deprecated because amount are rounded (to unit or total amount accurancy) before beeing inserted into database or after a computation, so this parameter should be useless.
* @param int $rounding Minimum number of decimal to show. If 0, no change, if -1, we use min($conf->global->MAIN_MAX_DECIMALS_UNIT,$conf->global->MAIN_MAX_DECIMALS_TOT)
* @param int $forcerounding Force the number of decimal to forcerounding decimal (-1=do not force)
@@ -5490,25 +5490,31 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $
}
$nbdecimal = $rounding;
// Output separators by default (french)
$dec = ',';
$thousand = ' ';
// If $outlangs not forced, we use use language
if (!is_object($outlangs)) {
$outlangs = $langs;
}
if ($outlangs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") {
$dec = $outlangs->transnoentitiesnoconv("SeparatorDecimal");
}
if ($outlangs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") {
$thousand = $outlangs->transnoentitiesnoconv("SeparatorThousand");
}
if ($thousand == 'None') {
if ($outlangs === 'none') {
// Use international separators
$dec = '.';
$thousand = '';
} elseif ($thousand == 'Space') {
} else {
// Output separators by default (french)
$dec = ',';
$thousand = ' ';
// If $outlangs not forced, we use use language
if (!is_object($outlangs)) {
$outlangs = $langs;
}
if ($outlangs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") {
$dec = $outlangs->transnoentitiesnoconv("SeparatorDecimal");
}
if ($outlangs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") {
$thousand = $outlangs->transnoentitiesnoconv("SeparatorThousand");
}
if ($thousand == 'None') {
$thousand = '';
} elseif ($thousand == 'Space') {
$thousand = ' ';
}
}
//print "outlangs=".$outlangs->defaultlang." amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'<br>";
@@ -5547,7 +5553,7 @@ function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $
}
// Add symbol of currency if requested
$cursymbolbefore = $cursymbolafter = '';
if ($currency_code) {
if ($currency_code && is_object($outlangs)) {
if ($currency_code == 'auto') {
$currency_code = $conf->currency;
}

View File

@@ -452,8 +452,13 @@ class pdf_crabe extends ModelePDFFactures
// You can add more thing under header here, if you increase $extra_under_address_shift too.
$extra_under_address_shift = 0;
$qrcodestring = '';
if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) {
$qrcodestring = $object->buildZATCAQRString();
} elseif (! empty($conf->global->INVOICE_ADD_SWISS_QR_CODE)) {
$qrcodestring = $object->buildSwitzerlandQRString();
}
if ($qrcodestring) {
$qrcodecolor = array('25', '25', '25');
// set style for QR-code
$styleQr = array(

View File

@@ -435,8 +435,13 @@ class pdf_sponge extends ModelePDFFactures
// You can add more thing under header here, if you increase $extra_under_address_shift too.
$extra_under_address_shift = 0;
$qrcodestring = '';
if (! empty($conf->global->INVOICE_ADD_ZATCA_QR_CODE)) {
$qrcodestring = $object->buildZATCAQRString();
} elseif (! empty($conf->global->INVOICE_ADD_SWISS_QR_CODE)) {
$qrcodestring = $object->buildSwitzerlandQRString();
}
if ($qrcodestring) {
$qrcodecolor = array('25', '25', '25');
// set style for QR-code
$styleQr = array(

View File

@@ -2266,5 +2266,6 @@ IconOnlyTextOnHover=Icon only - Text of icon appears under icon on mouse hover t
IconOnly=Icon only - Text on tooltip only
INVOICE_ADD_ZATCA_QR_CODE=Show the ZATCA QR code on invoices
INVOICE_ADD_ZATCA_QR_CODEMore=Some Arabic countries need this QR Code on their invoices
INVOICE_ADD_SWISS_QR_CODE=Show the swiss QR-Bill code on invoices
UrlSocialNetworksDesc=Url link of social network. Use {socialid} for the variable part that contains the social network ID.
IfThisCategoryIsChildOfAnother=If this category is a child of another one