diff --git a/ChangeLog b/ChangeLog
index 37957f61c1d..fb83d84bc60 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/dev/resources/iso-normes/barcodes/QR code for invoices.txt b/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt
similarity index 76%
rename from dev/resources/iso-normes/barcodes/QR code for invoices.txt
rename to dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt
index 639435238f9..df0be6b6659 100644
--- a/dev/resources/iso-normes/barcodes/QR code for invoices.txt
+++ b/dev/resources/iso-normes/qr-bar-codes/QR code for invoices.txt
@@ -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
diff --git a/dev/resources/iso-normes/barcodes/barcode_EAN13.txt b/dev/resources/iso-normes/qr-bar-codes/barcode_EAN13.txt
similarity index 100%
rename from dev/resources/iso-normes/barcodes/barcode_EAN13.txt
rename to dev/resources/iso-normes/qr-bar-codes/barcode_EAN13.txt
diff --git a/htdocs/admin/pdf_other.php b/htdocs/admin/pdf_other.php
index d8afe43720f..b064cbb8cd8 100644
--- a/htdocs/admin/pdf_other.php
+++ b/htdocs/admin/pdf_other.php
@@ -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 '';
+ print '
| '.$langs->trans("MAIN_PDF_PROPAL_USE_ELECTRONIC_SIGNING").' | ';
if ($conf->use_javascript_ajax) {
diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php
index 14b19023420..dd30a2e3cab 100644
--- a/htdocs/core/class/commoninvoice.class.php
+++ b/htdocs/core/class/commoninvoice.class.php
@@ -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% d’escompte à 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;
+ }
}
diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php
index 71ecd3f75d1..4a95bb7d345 100644
--- a/htdocs/core/class/commonobject.class.php
+++ b/htdocs/core/class/commonobject.class.php
@@ -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;
diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php
index e1fe08c7f18..48f0b3f452f 100644
--- a/htdocs/core/lib/functions.lib.php
+++ b/htdocs/core/lib/functions.lib.php
@@ -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."' ";
@@ -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;
}
diff --git a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php
index 09f1a0b27e8..63e9d61c409 100644
--- a/htdocs/core/modules/facture/doc/pdf_crabe.modules.php
+++ b/htdocs/core/modules/facture/doc/pdf_crabe.modules.php
@@ -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(
diff --git a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php
index 9210946128e..46ac4ffde37 100644
--- a/htdocs/core/modules/facture/doc/pdf_sponge.modules.php
+++ b/htdocs/core/modules/facture/doc/pdf_sponge.modules.php
@@ -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(
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index 341789af7bf..26c2a959a13 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -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
\ No newline at end of file
|