Skip to content
Code-Schnipsel Gruppen Projekte
Commit 2dbb4c1f erstellt von Henning Leutz's avatar Henning Leutz :martial_arts_uniform:
Dateien durchsuchen

feat: invoice download in different formats

Übergeordneter c82da602
No related branches found
No related tags found
3 Merge Requests!85Next 2.x,!84Feat e rechnung,!80Update 'next-3.x' with latest changes from 'main'
Pipeline #13318 fehlgeschlagen mit Phase
in 2 Minuten und 30 Sekunden
......@@ -36,6 +36,7 @@ define('package/quiqqer/invoice/bin/backend/controls/panels/Invoice', [
Binds: [
'print',
'storno',
'download',
'copy',
'creditNote',
'openInfo',
......@@ -199,6 +200,14 @@ define('package/quiqqer/invoice/bin/backend/controls/panels/Invoice', [
}
});
Actions.appendChild({
icon: 'fa fa-download',
text: QUILocale.get(lg, 'erp.panel.invoice.button.download'),
events: {
onClick: this.download
}
});
this.fireEvent('actionButtonCreate', [
this,
Actions
......@@ -554,6 +563,13 @@ define('package/quiqqer/invoice/bin/backend/controls/panels/Invoice', [
});
},
download: function()
{
require(['package/quiqqer/invoice/bin/backend/utils/Dialogs'], (Dialogs)=> {
Dialogs.openDownloadDialog(this.getAttribute('data').hash);
});
},
/**
* Opens the storno / cancellation dialog
*
......
<?php
use QUI\ERP\Accounting\Invoice\Handler;
use QUI\ERP\Accounting\Invoice\Utils\Invoice as InvoiceUtils;
use horstoeko\zugferd\ZugferdProfiles;
use QUI\ERP\Output\Output;
use Symfony\Component\HttpFoundation\Response;
define('QUIQQER_SYSTEM', true);
define('QUIQQER_AJAX', true);
require_once dirname(__FILE__, 5) . '/header.php';
$User = QUI::getUserBySession();
if (!$User->canUseBackend()) {
exit;
}
if (empty($_REQUEST['invoice'])) {
exit;
}
if (empty($_REQUEST['type'])) {
exit;
}
$invoiceHash = $_REQUEST['invoice'];
$type = mb_strtoupper($_REQUEST['type']);
$profileMap = [
'PROFILE_BASIC' => ZugferdProfiles::PROFILE_BASIC,
'PROFILE_BASICWL' => ZugferdProfiles::PROFILE_BASICWL,
'PROFILE_EN16931' => ZugferdProfiles::PROFILE_EN16931,
'PROFILE_EXTENDED' => ZugferdProfiles::PROFILE_EXTENDED,
'PROFILE_XRECHNUNG' => ZugferdProfiles::PROFILE_XRECHNUNG,
'PROFILE_XRECHNUNG_2' => ZugferdProfiles::PROFILE_XRECHNUNG_2,
'PROFILE_XRECHNUNG_2_1' => ZugferdProfiles::PROFILE_XRECHNUNG_2_1,
'PROFILE_XRECHNUNG_2_2' => ZugferdProfiles::PROFILE_XRECHNUNG_2_2,
'PROFILE_MINIMUM' => ZugferdProfiles::PROFILE_MINIMUM,
'PROFILE_XRECHNUNG_2_3' => ZugferdProfiles::PROFILE_XRECHNUNG_2_3,
'PROFILE_XRECHNUNG_3' => ZugferdProfiles::PROFILE_XRECHNUNG_3,
];
try {
if ($type === 'PDF') {
$OutputDocument = Output::getDocumentPdf(
$invoiceHash,
QUI\ERP\Accounting\Invoice\Output\OutputProviderInvoice::getEntityType()
);
$OutputDocument->download();
exit;
}
$Invoice = Handler::getInstance()->getInvoiceByHash($invoiceHash);
$document = InvoiceUtils::getElectronicInvoice($Invoice, $profileMap[$type]);
$xmlContent = $document->getContent();
$fileName = InvoiceUtils::getInvoiceFilename($Invoice);
$response = new Response($xmlContent);
$response->headers->set('Content-Type', 'application/xml');
$response->headers->set('Content-Disposition', 'attachment; filename="'. $fileName . '.xml"');
$response->headers->set('Content-Length', strlen($xmlContent));
$response->send();
} catch (Exception $e) {
}
.quiqqer-invoice-dialog-refund-label input {
float: left;
margin-right: 10px;
}
\ No newline at end of file
}
/** invoice download dialog
============================================================================== */
.quiqqer-invoice-download-dialog {
text-align: center;
}
.quiqqer-invoice-download-dialog-buttons {
display: flex;
width: 100%;
gap: 1rem;
flex-wrap: wrap;
margin-top: 2rem;
justify-content: center;
}
.quiqqer-invoice-download-dialog button {
width: 200px;
}
......@@ -11,10 +11,11 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
'Locale',
'package/quiqqer/invoice/bin/Invoices',
'qui/controls/windows/Confirm',
'qui/controls/windows/Popup',
'css!package/quiqqer/invoice/bin/backend/utils/Dialogs.css'
], function(QUI, QUILocale, Invoices, QUIConfirm) {
], function (QUI, QUILocale, Invoices, QUIConfirm, QUIPopup) {
'use strict';
const lg = 'quiqqer/invoice';
......@@ -28,14 +29,14 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
* @param {String} [entityType]
* @return {Promise}
*/
openPrintDialog: function(invoiceId, entityType) {
openPrintDialog: function (invoiceId, entityType) {
entityType = entityType || 'Invoice';
return Invoices.getInvoiceHistory(invoiceId).then(function(comments) {
return new Promise(function(resolve) {
return Invoices.getInvoiceHistory(invoiceId).then(function (comments) {
return new Promise(function (resolve) {
require([
'package/quiqqer/erp/bin/backend/controls/OutputDialog'
], function(OutputDialog) {
], function (OutputDialog) {
new OutputDialog({
entityId: invoiceId,
entityType: entityType,
......@@ -55,11 +56,11 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
* @param {String} invoiceId - Invoice ID or Hash
* @return {Promise}
*/
openStornoDialog: function(invoiceId) {
return Invoices.get(invoiceId).then(function(result) {
openStornoDialog: function (invoiceId) {
return Invoices.get(invoiceId).then(function (result) {
const id = result.id_prefix + result.id;
return new Promise(function(resolve, reject) {
return new Promise(function (resolve, reject) {
new QUIConfirm({
icon: 'fa fa-ban',
texticon: 'fa fa-ban',
......@@ -80,7 +81,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
maxHeight: 500,
maxWidth: 750,
events: {
onOpen: function(Win) {
onOpen: function (Win) {
const Container = Win.getContent().getElement('.textbody');
// #locale
......@@ -111,14 +112,14 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
Reason.focus();
},
onSubmit: function(Win) {
onSubmit: function (Win) {
const Reason = Win.getContent().getElement('[name="reason"]');
const value = Reason.value;
if (value === '') {
Reason.focus();
Reason.required = true;
if ('reportValidity' in Reason) {
Reason.reportValidity();
}
......@@ -128,10 +129,10 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
Win.Loader.show();
Invoices.reversalInvoice(result.hash, value).then(function(result) {
Invoices.reversalInvoice(result.hash, value).then(function (result) {
Win.close();
resolve(result);
}).catch(function(Exception) {
}).catch(function (Exception) {
Win.close();
reject(Exception);
});
......@@ -150,7 +151,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
* @param {String} invoiceId - Invoice ID or Hash
* @return {*|Promise}
*/
openCancellationDialog: function(invoiceId) {
openCancellationDialog: function (invoiceId) {
return this.openStornoDialog(invoiceId);
},
......@@ -160,7 +161,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
* @param {String} invoiceId - Invoice ID or Hash
* @return {*|Promise}
*/
openReversalDialog: function(invoiceId) {
openReversalDialog: function (invoiceId) {
return this.openStornoDialog(invoiceId);
},
......@@ -170,11 +171,11 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
* @param {String} invoiceId - Invoice ID or Hash
* @return {Promise}
*/
openCopyDialog: function(invoiceId) {
return Invoices.get(invoiceId).then(function(result) {
openCopyDialog: function (invoiceId) {
return Invoices.get(invoiceId).then(function (result) {
const id = result.id_prefix + result.id;
return new Promise(function(resolve) {
return new Promise(function (resolve) {
new QUIConfirm({
title: QUILocale.get(lg, 'dialog.invoice.copy.title'),
text: QUILocale.get(lg, 'dialog.invoice.copy.text'),
......@@ -191,13 +192,13 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
textimage: 'fa fa-copy'
},
events: {
onSubmit: function(Win) {
onSubmit: function (Win) {
Win.Loader.show();
Invoices.copyInvoice(result.hash).then(function(newId) {
Invoices.copyInvoice(result.hash).then(function (newId) {
Win.close();
resolve(newId);
}).then(function() {
}).then(function () {
Win.Loader.hide();
});
}
......@@ -213,14 +214,14 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
* @param {String} invoiceId - Invoice ID or Hash
* @return {Promise}
*/
openCreateCreditNoteDialog: function(invoiceId) {
openCreateCreditNoteDialog: function (invoiceId) {
const self = this;
return Invoices.get(invoiceId).then(function(result) {
return Invoices.get(invoiceId).then(function (result) {
let paymentHasRefund = false;
const id = result.id_prefix + result.id;
return new Promise(function(resolve, reject) {
return new Promise(function (resolve, reject) {
new QUIConfirm({
icon: 'fa fa-clipboard',
texticon: 'fa fa-clipboard',
......@@ -241,10 +242,10 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
maxHeight: 400,
maxWidth: 600,
events: {
onOpen: function(Win) {
onOpen: function (Win) {
Win.Loader.show();
Invoices.hasRefund(id).then(function(hasRefund) {
Invoices.hasRefund(id).then(function (hasRefund) {
paymentHasRefund = hasRefund;
QUI.fireEvent('quiqqerInvoiceCreateCreditNoteDialogOpen', [id, Win]);
......@@ -274,16 +275,16 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
});
},
onSubmit: function(Win) {
onSubmit: function (Win) {
Win.Loader.show();
const Content = Win.getContent(),
Refund = Content.getElement('[name="refund"]');
const createInvoice = function(values) {
const createInvoice = function (values) {
values = values || {};
Invoices.createCreditNote(result.hash, values).then(function(newId) {
Invoices.createCreditNote(result.hash, values).then(function (newId) {
QUI.fireEvent(
'quiqqerInvoiceCreateCreditNoteDialogSubmit',
[newId, Win]
......@@ -291,7 +292,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
resolve(newId);
Win.close();
}).catch(function(Err) {
}).catch(function (Err) {
Win.Loader.hide();
console.error(Err);
......@@ -300,7 +301,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
};
if (paymentHasRefund && Refund.checked) {
self.openRefundWindow(invoiceId).then(function(RefundWindow) {
self.openRefundWindow(invoiceId).then(function (RefundWindow) {
if (!RefundWindow) {
Win.Loader.hide();
return;
......@@ -309,7 +310,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
createInvoice({
refund: RefundWindow.getValues()
});
}).catch(function(Err) {
}).catch(function (Err) {
Win.Loader.hide();
console.error(Err);
});
......@@ -319,7 +320,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
createInvoice();
},
onCancel: function() {
onCancel: function () {
resolve(false);
}
}
......@@ -333,23 +334,84 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [
* @param invoiceId
* @return {Promise}
*/
openRefundWindow: function(invoiceId) {
return new Promise(function(resolve) {
openRefundWindow: function (invoiceId) {
return new Promise(function (resolve) {
require([
'package/quiqqer/invoice/bin/backend/controls/panels/refund/Window'
], function(RefundWindow) {
], function (RefundWindow) {
new RefundWindow({
invoiceId: invoiceId,
autoRefund: false,
events: {
onSubmit: resolve,
onCancel: function() {
onCancel: function () {
resolve(false);
}
}
}).open();
});
});
},
openDownloadDialog: function (hash) {
new QUIPopup({
icon: 'fa fa-download',
title: QUILocale.get(lg, 'dialog.invoice.download.title'),
autoclose: false,
maxHeight: 400,
maxWidth: 600,
buttons: false,
events: {
onOpen: function (Win) {
Win.Loader.show();
const Content = Win.getContent();
Content.classList.add('quiqqer-invoice-download-dialog');
Content.set(
'html',
'<h3>' + QUILocale.get(lg, 'dialog.invoice.download.header') + '</h3>' +
QUILocale.get(lg, 'dialog.invoice.download.text') +
'<div class="quiqqer-invoice-download-dialog-buttons">' +
' <button value="PDF" class="qui-button">PDF</button>' +
' <button value="PROFILE_BASIC" class="qui-button">ZUGFeRD Basic</button>' +
' <button value="PROFILE_EN16931" class="qui-button">ZUGFeRD EN16931</button>' +
' <button value="PROFILE_EXTENDED" class="qui-button">ZUGFeRD Extended</button>' +
' <button value="PROFILE_XRECHNUNG_2_3" class="qui-button">XRechnung 2.3</button>' +
' <button value="PROFILE_XRECHNUNG_3" class="qui-button">XRechnung 3</button>' +
'</div>'
);
Content.querySelectorAll('button').forEach(function (Button) {
Button.addEventListener('click', function () {
const id = 'download-invoice-' + hash + '-' + Button.value;
new Element('iframe', {
src: URL_OPT_DIR + 'quiqqer/invoice/bin/backend/download.php?' + Object.toQueryString({
invoice: hash,
type: Button.value
}),
id: id,
styles: {
position: 'absolute',
top: -200,
left: -200,
width: 50,
height: 50
}
}).inject(document.body);
(function () {
document.getElements('#' + id).destroy();
}).delay(1000, this);
});
});
Win.Loader.hide();
}
}
}).open();
}
};
});
......@@ -1282,6 +1282,19 @@
<en><![CDATA[Please enter a reason for cancellation.]]></en>
</locale>
<locale name="dialog.invoice.download.title">
<de><![CDATA[Lade die Rechnung in verschiedenen Formaten herunter]]></de>
<en><![CDATA[Download the invoice in various formats]]></en>
</locale>
<locale name="dialog.invoice.download.header">
<de><![CDATA[Rechnung herunterladen]]></de>
<en><![CDATA[Download invoice]]></en>
</locale>
<locale name="dialog.invoice.download.text" html="true">
<de><![CDATA[<p>Wähle das gewünschte Format aus, um deine Rechnung herunterzuladen.</p>]]></de>
<en><![CDATA[<p>Select the desired format to download your invoice.</p>]]></en>
</locale>
<locale name="dialog.create.address.title">
<de><![CDATA[Rechnungsadresse anlegen]]></de>
<en><![CDATA[Create invoice address]]></en>
......
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