Skip to content
Code-Schnipsel Gruppen Projekte

Revisionen vergleichen

Änderungen werden so angezeigt, als ob die Quellrevision mit der Zielrevision zusammengeführt würde. Erfahre mehr über den Vergleich von Revisionen.

Quelle

Zielprojekt auswählen
No results found

Ziel

Zielprojekt auswählen
  • quiqqer/invoice
1 Ergebnis
Änderungen anzeigen
Commits auf Quelle (7)
......@@ -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, 'dialog.invoice.download.button'),
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\Defaults;
use QUI\System\Log;
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 {
$Invoice = Handler::getInstance()->getInvoiceByHash($invoiceHash);
$fileName = InvoiceUtils::getInvoiceFilename($Invoice);
if ($type === 'PDF') {
$defaultTemplates = Defaults::conf('output', 'default_templates');
$defaultTemplates = json_decode($defaultTemplates, true);
$templateProvider = '';
$templateId = '';
if (!empty($defaultTemplates['Invoice'])) {
$templateProvider = $defaultTemplates['Invoice']['provider'];
$templateId = $defaultTemplates['Invoice']['id'];
}
$Request = QUI::getRequest();
$Request->query->set('id', $invoiceHash);
$Request->query->set('t', 'Invoice');
$Request->query->set('ep', 'quiqqer/invoice');
$Request->query->set('tpl', $templateId);
$Request->query->set('tplpr', $templateProvider);
include dirname(__FILE__, 4) . '/erp/bin/output/backend/download.php';
} else {
$document = InvoiceUtils::getElectronicInvoice($Invoice, $profileMap[$type]);
$content = $document->getContent();
$contentType = 'application/xml';
$fileName .= '.xml';
$response = new Response($content);
$response->headers->set('Content-Type', $contentType);
$response->headers->set('Content-Disposition', 'attachment; filename="' . $fileName . '"');
$response->headers->set('Content-Length', strlen($content));
$response->send();
}
} catch (Exception $e) {
Log::writeException($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();
}
};
});
......@@ -29,7 +29,8 @@
"quiqqer/htmltopdf": "^3",
"quiqqer/utils": "^2",
"ramsey/uuid": "^3|^4",
"chillerlan/php-qrcode": "^4.3"
"chillerlan/php-qrcode": "^4.3",
"horstoeko/zugferd": "^1"
},
"autoload": {
"psr-4": {
......
......@@ -91,7 +91,7 @@
<field type="VARCHAR(50) NULL">invoice_address_id</field>
<field type="TEXT NULL">invoice_address</field>
<field type="INT NULL">delivery_address_id</field>
<field type="VARCHAR(50) NULL">delivery_address_id</field>
<field type="TEXT NULL">delivery_address</field>
<field type="VARCHAR(255) NULL">order_id</field>
......
......@@ -415,6 +415,43 @@
<en><![CDATA[Edit Invoice status:]]></en>
</locale>
<locale name="invoice.settings.e-invoice.xInvoiceAttachment.text">
<de><![CDATA[X-Rechnung anhängen]]></de>
<en><![CDATA[Attach X-bill]]></en>
</locale>
<locale name="invoice.settings.e-invoice.xInvoiceAttachment.description">
<de><![CDATA[
Bei Rechnungsmails werden Rechnungen automatisch auch als X-Rechnung XML angehängt,
um den Standard für elektronische Rechnungen zu erfüllen.
]]></de>
<en><![CDATA[
Invoices are automatically attached to invoice e-mails as X-invoices xml format,
to comply with the standard for electronic invoices.
]]></en>
</locale>
<locale name="invoice.settings.e-invoice.xInvoiceAttachmentType.text">
<de><![CDATA[X-Rechnung Profil]]></de>
<en><![CDATA[X-bill profile]]></en>
</locale>
<locale name="invoice.settings.e-invoice.zugferdInvoiceAttachment.text">
<de><![CDATA[Zugferd-Rechnung anhängen]]></de>
<en><![CDATA[Attach Zugferd-bill]]></en>
</locale>
<locale name="invoice.settings.e-invoice.zugferdInvoiceAttachment.description">
<de><![CDATA[
Bei Rechnungsmails werden Rechnungen automatisch im Zugferd PDF Format angehängt.
]]></de>
<en><![CDATA[
Invoices are automatically attached to invoice emails in Zugferd PDF format.
]]></en>
</locale>
<locale name="invoice.settings.e-invoice.zugferdInvoiceAttachmentType.text">
<de><![CDATA[Zugferd-Rechnung Profil]]></de>
<en><![CDATA[Zugferd-bill profile]]></en>
</locale>
<locale name="invoice.type.creditNote">
<de><![CDATA[Gutschrift]]></de>
<en><![CDATA[Credit Note]]></en>
......@@ -1245,6 +1282,23 @@
<en><![CDATA[Please enter a reason for cancellation.]]></en>
</locale>
<locale name="dialog.invoice.download.button">
<de><![CDATA[Rechnung herunterladen]]></de>
<en><![CDATA[Download invoice]]></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>
......
......@@ -41,6 +41,23 @@
<conf name="invoiceAddressRequirementThreshold">
<type><![CDATA[float]]></type>
</conf>
<conf name="xInvoiceAttachment">
<type><![CDATA[bool]]></type>
<defaultvalue><![CDATA[1]]></defaultvalue>
</conf>
<conf name="xInvoiceAttachmentType">
<type><![CDATA[int]]></type>
<defaultvalue><![CDATA[2]]></defaultvalue>
</conf>
<conf name="zugferdInvoiceAttachment">
<type><![CDATA[bool]]></type>
<defaultvalue><![CDATA[1]]></defaultvalue>
</conf>
<conf name="zugferdInvoiceAttachmentType">
<type><![CDATA[int]]></type>
<defaultvalue><![CDATA[2]]></defaultvalue>
</conf>
</section>
<section name="temporaryInvoice">
......@@ -214,6 +231,74 @@
</input>
</settings>
<settings title="eInvoice" name="eInvoice">
<title>
<locale group="quiqqer/invoice" var="invoice.settings.e-invoice.title"/>
</title>
<input conf="invoice.xInvoiceAttachment" type="checkbox">
<text>
<locale group="quiqqer/invoice"
var="invoice.settings.e-invoice.xInvoiceAttachment.text"/>
</text>
<description>
<locale group="quiqqer/invoice"
var="invoice.settings.e-invoice.xInvoiceAttachment.description"/>
</description>
</input>
<select conf="invoice.xInvoiceAttachmentType">
<text>
<locale group="quiqqer/invoice"
var="invoice.settings.e-invoice.xInvoiceAttachmentType.text"/>
</text>
<option value="0">Basic</option>
<option value="1">Basic WL</option>
<option value="2">EN16931</option>
<option value="3">Extended</option>
<option value="4">XRechnung (Germany only)</option>
<option value="5">XRechnung 2.0 (Germany only)</option>
<option value="6">XRechnung 2.1 (Germany only)</option>
<option value="7">XRechnung 2.2 (Germany only)</option>
<option value="8">Minimum</option>
<option value="9">XRechnung 2.3 (Germany only)</option>
<option value="10">XRechnung 3.0 (Germany only)</option>
</select>
<input conf="invoice.zugferdInvoiceAttachment" type="checkbox">
<text>
<locale group="quiqqer/invoice"
var="invoice.settings.e-invoice.zugferdInvoiceAttachment.text"/>
</text>
<description>
<locale group="quiqqer/invoice"
var="invoice.settings.e-invoice.zugferdInvoiceAttachment.description"/>
</description>
</input>
<select conf="invoice.zugferdInvoiceAttachmentType">
<text>
<locale group="quiqqer/invoice"
var="invoice.settings.e-invoice.zugferdInvoiceAttachmentType.text"/>
</text>
<option value="0">Basic</option>
<option value="1">Basic WL</option>
<option value="2">EN16931</option>
<option value="3">Extended</option>
<option value="4">XRechnung (Germany only)</option>
<option value="5">XRechnung 2.0 (Germany only)</option>
<option value="6">XRechnung 2.1 (Germany only)</option>
<option value="7">XRechnung 2.2 (Germany only)</option>
<option value="8">Minimum</option>
<option value="9">XRechnung 2.3 (Germany only)</option>
<option value="10">XRechnung 3.0 (Germany only)</option>
</select>
</settings>
<settings title="invoiceDownload" name="invoiceDownload">
<title>
<locale group="quiqqer/invoice" var="invoice.settings.download.title"/>
......
......@@ -6,6 +6,9 @@
namespace QUI\ERP\Accounting\Invoice;
use horstoeko\zugferd\ZugferdDocumentBuilder;
use horstoeko\zugferd\ZugferdDocumentPdfBuilder;
use horstoeko\zugferd\ZugferdDocumentPdfMerger;
use QUI;
use QUI\ERP\Accounting\Invoice\Output\OutputProviderCancelled;
use QUI\ERP\Accounting\Invoice\Output\OutputProviderCreditNote;
......@@ -23,6 +26,7 @@
use function file_get_contents;
use function in_array;
use function is_numeric;
use function str_replace;
use function strtolower;
use function strtotime;
......@@ -287,6 +291,7 @@ public static function onQuiqqerErpGetHistoryByUser(
* @param string $entityType
* @param string $recipient
* @param Mailer $Mailer
* @param string $mailFile
* @return void
*
* @throws Exception
......@@ -297,7 +302,8 @@ public static function onQuiqqerErpOutputSendMailBefore(
$entityId,
string $entityType,
string $recipient,
QUI\Mail\Mailer $Mailer
QUI\Mail\Mailer $Mailer,
string $mailFile = ''
): void {
$allowedEntityTypes = [
OutputProviderInvoice::getEntityType(),
......@@ -316,6 +322,29 @@ public static function onQuiqqerErpOutputSendMailBefore(
return;
}
// extend pdf with e-invoice
$Config = QUI::getPackage('quiqqer/invoice')->getConfig();
if ($Config->getValue('invoice', 'xInvoiceAttachment')) {
$xmlFile = str_replace('.pdf', '.xml', $mailFile);
$document = QUI\ERP\Accounting\Invoice\Utils\Invoice::getElectronicInvoice(
$Invoice,
$Config->getValue('invoice', 'xInvoiceAttachmentType')
);
$document->writeFile($xmlFile);
$Mailer->addAttachment($xmlFile);
}
if (file_exists($mailFile) && $Config->getValue('invoice', 'zugferdInvoiceAttachment')) {
$document = QUI\ERP\Accounting\Invoice\Utils\Invoice::getElectronicInvoice(
$Invoice,
$Config->getValue('invoice', 'xInvoiceAttachmentType')
);
$pdfBuilder = new ZugferdDocumentPdfBuilder($document, $mailFile);
$pdfBuilder->generateDocument()->saveDocument($mailFile);
}
// @todo
$customerFiles = $Invoice->getCustomerFiles();
......
......@@ -6,13 +6,17 @@
namespace QUI\ERP\Accounting\Invoice\Utils;
use IntlDateFormatter;
use DateTime;
use QUI;
use QUI\ERP\Accounting\Invoice\Exception;
use QUI\ERP\Accounting\Invoice\InvoiceTemporary;
use QUI\ERP\Accounting\Invoice\ProcessingStatus\Handler as ProcessingStatuses;
use QUI\ERP\Currency\Currency;
use QUI\ExceptionStack;
use QUI\ERP\Defaults;
use IntlDateFormatter;
use horstoeko\zugferd\ZugferdDocumentBuilder;
use horstoeko\zugferd\ZugferdProfiles;
use function array_map;
use function array_merge;
......@@ -657,4 +661,128 @@ public static function addressRequirementThreshold(): float
return floatval($threshold);
}
public static function getElectronicInvoice(
InvoiceTemporary|QUI\ERP\Accounting\Invoice\Invoice $Invoice,
$type = ZugferdProfiles::PROFILE_EN16931
): ZugferdDocumentBuilder {
$document = ZugferdDocumentBuilder::CreateNew($type);
$date = $Invoice->getAttribute('date');
$date = strtotime($date);
$date = (new DateTime())->setTimestamp($date);
$document->setDocumentInformation(
$Invoice->getPrefixedNumber(),
"380",
$date,
$Invoice->getCurrency()->getCode()
);
// seller / owner
$document
->setDocumentSeller(Defaults::conf('company', 'name'))
->addDocumentSellerGlobalId("4000001123452", "0088")
->addDocumentSellerTaxRegistration("FC", "201/113/40209")
->addDocumentSellerTaxRegistration("VA", "DE123456789")
->setDocumentSellerAddress(
Defaults::conf('company', 'street'),
"",
"",
Defaults::conf('company', 'zip'),
Defaults::conf('company', 'city'),
Defaults::conf('company', 'country') // @todo country ->code<-
)
->setDocumentSellerCommunication(
'EM',
Defaults::conf('company', 'email')
)
->setDocumentSellerContact(
Defaults::conf('company', 'owner'), // @todo contact person
'', // @todo contact department
Defaults::conf('company', 'phone'), // @todo contact phone
Defaults::conf('company', 'fax'), // @todo contact fax
Defaults::conf('company', 'email') // @todo contact email
);
// bank stuff
$bankAccount = QUI\ERP\BankAccounts\Handler::getCompanyBankAccount();
if (!empty($bankAccount)) {
$document->addDocumentPaymentMeanToDirectDebit(
$bankAccount['iban'],
$Invoice->getPrefixedNumber()
);
}
// customer
$Customer = $Invoice->getCustomer();
$document
->setDocumentBuyer(
$Customer->getName(),
$Customer->getCustomerNo()
)
->setDocumentBuyerAddress(
$Customer->getAddress()->getAttribute('street_no'),
"",
"",
$Customer->getAddress()->getAttribute('zip'),
$Customer->getAddress()->getAttribute('city'),
$Customer->getAddress()->getCountry()->getCode()
)
->setDocumentBuyerCommunication('EM', $Customer->getAddress()->getAttribute('email'))
->setDocumentBuyerReference($Customer->getUUID());
// total
$priceCalculation = $Invoice->getPriceCalculation();
$vatTotal = 0;
foreach ($priceCalculation->getVat() as $vat) {
$document->addDocumentTax(
"S",
"VAT",
$priceCalculation->getSum()->value(),
$vat->value(),
$vat->getVat()
);
$vatTotal = $vatTotal + $vat->value();
}
$document->setDocumentSummation(
$priceCalculation->getSum()->value(),
$priceCalculation->getSum()->value(),
$priceCalculation->getSum()->value(),
0.0,
0.0,
$priceCalculation->getSum()->value(),
$vatTotal,
null,
0.0
);
// products
foreach ($Invoice->getArticles() as $Article) {
/* @var $Article QUI\ERP\Accounting\Article */
$article = $Article->toArray();
$document
->addNewPosition($article['position'])
->setDocumentPositionProductDetails(
$article['title'],
$article['description'],
null,
null,
null,
null
)
->setDocumentPositionNetPrice($article['calculated']['nettoPrice'])
->setDocumentPositionQuantity($article['quantity'], "H87")
->addDocumentPositionTax('S', 'VAT', $article['vat'])
->setDocumentPositionLineSummation($article['sum']);
}
return $document;
}
}