forked from Wavyzz/dolibarr
NEW Support the Swiss QR-Code
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user