Skip to content
Code-Schnipsel Gruppen Projekte
Commit 7a58e053 erstellt von Patrick Müller's avatar Patrick Müller
Dateien durchsuchen

feat: epc qr code in invoices #121

Übergeordneter 381be8fa
Branches feat-qrcode
No related tags found
Keine zugehörigen Merge Requests gefunden
{
"name": "quiqqer\/invoice",
"type": "quiqqer-module",
"description": "",
"license": [
"PCSG QEL-1.0"
],
"authors": [
{
"name": "Henning Leutz",
"email": "leutz@pcsg.de",
"homepage": "http:\/\/www.pcsg.de",
"role": "Developer"
}
],
"support": {
"email": "support@pcsg.de",
"url": "http:\/\/www.pcsg.de"
},
"require": {
"php": ">=7.2",
"quiqqer\/quiqqer": ">=1.5|dev-master|dev-dev",
"quiqqer\/erp": "^1.4|dev-master|dev-dev",
"quiqqer/customer": "^1.1|dev-master|dev-dev",
"quiqqer\/payments": "1.*|dev-master|dev-dev",
"quiqqer\/payment-transactions": ">=1.1.3|dev-master|dev-dev",
"quiqqer\/htmltopdf": "^2|dev-master|dev-dev",
"ramsey\/uuid": "3.*"
},
"autoload": {
"psr-4": {
"QUI\\ERP\\": "src\/QUI\/ERP"
}
"name": "quiqqer\/invoice",
"type": "quiqqer-module",
"description": "",
"license": [
"PCSG QEL-1.0"
],
"authors": [
{
"name": "Henning Leutz",
"email": "leutz@pcsg.de",
"homepage": "http:\/\/www.pcsg.de",
"role": "Developer"
}
],
"support": {
"email": "support@pcsg.de",
"url": "http:\/\/www.pcsg.de"
},
"require": {
"php": ">=7.2",
"quiqqer\/quiqqer": ">=1.5|dev-master|dev-dev",
"quiqqer\/erp": "^1.4|dev-master|dev-dev",
"quiqqer/customer": "^1.1|dev-master|dev-dev",
"quiqqer\/payments": "1.*|dev-master|dev-dev",
"quiqqer\/payment-transactions": ">=1.1.3|dev-master|dev-dev",
"quiqqer\/htmltopdf": "^2|dev-master|dev-dev",
"ramsey\/uuid": "3.*",
"chillerlan/php-qrcode": "^4.3"
},
"autoload": {
"psr-4": {
"QUI\\ERP\\": "src\/QUI\/ERP"
}
}
}
......@@ -524,6 +524,14 @@
You can create a product field at <b>Administration -> Shop -> Product fields</b> with type text (normal or multilangual).
]]></en>
</locale>
<locale name="invoice.settings.invoice.includeQrCode">
<de><![CDATA[EPC-QR-Code (GiroCode) auf Rechnung anzeigen]]></de>
<en><![CDATA[Show EPC QR code on invoice]]></en>
</locale>
<locale name="invoice.settings.invoice.includeQrCode.description">
<de><![CDATA[Auf Rechnungen mit Zahlungsart Rechnung und Vorkasse soll ein EPC-QR-Code (auch "GiroCode") angezeigt werden. Mit diesem können alle nötigen Zahlungsinformationen für SEPA-Überweisungen in gängigen Banking-Apps über das Scannen des QR-Codes verfügbar gemacht werden.]]></de>
<en><![CDATA[An EPC QR code is to be displayed on invoices with payment methods invoice and prepayment. With this, all necessary payment information for SEPA transfers can be made available in common banking apps by scanning the QR code.]]></en>
</locale>
<locale name="invoice.send.mail.message.description" html="true">
<de><![CDATA[
......@@ -1637,6 +1645,10 @@
<groups name="quiqqer/invoice" datatype="php">
<locale name="OutputProvider.epc_qr_code_purpose">
<de><![CDATA[Rechnung [invoiceNo]]]></de>
<en><![CDATA[Invoice [invoiceNo]]]></en>
</locale>
<locale name="exception.Invoice.addCustomerFile.no_customer">
<de><![CDATA[Die Rechnung hat noch keinen zugewiesenen Kunden. Bitte weise der Rechnung zuerst einen Kunden zu, bevor du der Rechnung Kunden-Dateien zuweist.]]></de>
<en><![CDATA[The invoice does not have an assigned customer yet. Please assign a customer to the invoice first before assigning customer files to the invoice.]]></en>
......
......@@ -30,6 +30,10 @@
<conf name="productDescriptionSource">
<type>integer</type>
</conf>
<conf name="includeQrCode">
<type><![CDATA[bool]]></type>
<defaultvalue><![CDATA[0]]></defaultvalue>
</conf>
</section>
<section name="temporaryInvoice">
......@@ -163,6 +167,17 @@
var="invoice.settings.invoice.productDescriptionSource.description"/>
</description>
</input>
<input type="checkbox" conf="invoice.includeQrCode">
<text>
<locale group="quiqqer/invoice"
var="invoice.settings.invoice.includeQrCode"/>
</text>
<description>
<locale group="quiqqer/invoice"
var="invoice.settings.invoice.includeQrCode.description"/>
</description>
</input>
</settings>
<settings title="invoiceDownload" name="invoiceDownload">
......
......@@ -8,6 +8,13 @@
use QUI\ERP\Accounting\Invoice\Utils\Invoice as InvoiceUtils;
use QUI\Interfaces\Users\User;
use QUI\Locale;
use chillerlan\QRCode\QROptions;
use chillerlan\QRCode\QRCode;
use QUI\ERP\Payments\SEPA\Provider as SepaProvider;
use QUI\ERP\BankAccounts\Handler as BankAccounts;
use QUI\ERP\Accounting\Invoice\Settings;
use QUI\ERP\Accounting\Payments\Methods\AdvancePayment\Payment as AdvancePayment;
use QUI\ERP\Accounting\Payments\Methods\Invoice\Payment as InvoicePayment;
/**
* Class OutputProvider
......@@ -185,6 +192,13 @@ public static function getTemplateData($entityId)
}
}
// EPC QR Code
$epcQrCodeImageSrc = false;
if (Settings::getInstance()->isIncludeQrCode()) {
$epcQrCodeImageSrc = self::getEpcQrCodeImageImgSrc($Invoice);
}
return [
'this' => $InvoiceView,
'ArticleList' => $Articles,
......@@ -197,7 +211,8 @@ public static function getTemplateData($entityId)
'projectName' => $Invoice->getAttribute('project_name'),
'useShipping' => QUI::getPackageManager()->isInstalled('quiqqer/shipping'),
'globalInvoiceText' => $globalInvoiceText,
'orderNumber' => $orderNumber
'orderNumber' => $orderNumber,
'epcQrCodeImageSrc' => $epcQrCodeImageSrc
];
}
......@@ -436,4 +451,108 @@ public static function dateFormat($date)
return $Formatter->format($date);
}
/**
* Get raw base64 img src for EPC QR code.
*
* @param QUI\ERP\Accounting\Invoice\Invoice|InvoiceTemporary $Invoice
* @return string|false - Raw <img> "src" attribute with base64 image data or false if code can or must not be generated.
*/
protected static function getEpcQrCodeImageImgSrc($Invoice)
{
try {
// Check currency (must be EUR)
if ($Invoice->getCurrency()->getCode() !== 'EUR') {
return false;
}
// Check payment type (must be "invoice" or "pay in advance")
$paymentTypeClassName = $Invoice->getPayment()->getPaymentType();
$allowedPaymentTypeClasses = [
AdvancePayment::class,
InvoicePayment::class
];
if (!\in_array($paymentTypeClassName, $allowedPaymentTypeClasses)) {
return false;
}
$varDir = QUI::getPackage('quiqqer/invoice')->getVarDir();
} catch (\Exception $Exception) {
QUI\System\Log::writeException($Exception);
return false;
}
// Prefer bank account set in SEPA module if available
if (QUI::getPackageManager()->isInstalled('quiqqer/payment-sepa')) {
$creditorBankAccount = SepaProvider::getCreditorBankAccount();
} else {
$creditorBankAccount = BankAccounts::getCompanyBankAccount();
}
$requiredFields = [
'accountHolder',
'iban',
'bic',
];
foreach ($requiredFields as $requiredField) {
if (empty($creditorBankAccount[$requiredField])) {
return false;
}
}
try {
$paidStatus = $Invoice->getPaidStatusInformation();
} catch (\Exception $Exception) {
QUI\System\Log::writeException($Exception);
return false;
}
$amount = $paidStatus['toPay'];
if ($amount <= 0) {
return false;
}
$purposeText = QUI::getLocale()->get(
'quiqqer/invoice',
'OutputProvider.epc_qr_code_purpose',
[
'invoiceNo' => $Invoice->getId()
]
);
// @todo Warnung, wenn $purposeText zu lang
// See
$qrCodeLines = [
'BCD',
'002',
'1', // UTF-8
'SCT',
$creditorBankAccount['bic'],
$creditorBankAccount['accountHolder'],
$creditorBankAccount['iban'],
'EUR'.\number_format($amount, 2, '.', ''),
'',
'',
$purposeText
];
$qrCodeText = \implode(\PHP_EOL, $qrCodeLines);
$QrOptions = new QROptions([
'version' => QRCode::VERSION_AUTO,
'outputType' => QRCode::OUTPUT_IMAGE_PNG,
'eccLevel' => QRCode::ECC_M,
'pngCompression' => -1
]);
$QrCode = new QRCode($QrOptions);
return $QrCode->render($qrCodeText);
}
}
......@@ -230,5 +230,22 @@ public function getDefaultTemplate()
return $first['name'];
}
/**
* Check if EPC QR code shall be included.
*
* @return bool
*/
public function isIncludeQrCode(): bool
{
try {
$Config = QUI::getPackage('quiqqer/invoice')->getConfig();
} catch (\Exception $Exception) {
QUI\System\Log::writeException($Exception);
return false;
}
return !empty($Config->getValue('invoice', 'includeQrCode'));
}
//endregion
}
0% oder .
You are about to add 0 people to the discussion. Proceed with caution.
Bearbeitung dieser Nachricht zuerst beenden!
Bitte registrieren oder zum Kommentieren