Skip to content
Code-Schnipsel Gruppen Projekte
Bestätigt Commit c82da602 erstellt von Henning Leutz's avatar Henning Leutz :martial_arts_uniform:
Dateien durchsuchen

feat: new e-invoice as attachment

Übergeordneter e531899c
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 #13141 bestanden mit Phase
in 2 Minuten und 30 Sekunden
......@@ -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": {
......
......@@ -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>
......
......@@ -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;
}
}
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