diff --git a/bin/backend/utils/Dialogs.js b/bin/backend/utils/Dialogs.js index 17e9b43aa600700ab66f3b61db2fc1ec75e53d88..27189b115b39a29c4576d1032590a6ef3421d19f 100644 --- a/bin/backend/utils/Dialogs.js +++ b/bin/backend/utils/Dialogs.js @@ -14,10 +14,10 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [ 'css!package/quiqqer/invoice/bin/backend/utils/Dialogs.css' -], function (QUI, QUILocale, Invoices, QUIConfirm) { - "use strict"; +], function(QUI, QUILocale, Invoices, QUIConfirm) { + 'use strict'; - var lg = 'quiqqer/invoice'; + const lg = 'quiqqer/invoice'; return { @@ -28,18 +28,18 @@ 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, + entityId: invoiceId, entityType: entityType, - comments : comments.length ? comments : false + comments: comments.length ? comments : false }).open(); resolve(); @@ -54,72 +54,83 @@ 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) { - var id = result.id_prefix + result.id; + 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', - title : QUILocale.get(lg, 'dialog.invoice.reversal.title', { + icon: 'fa fa-ban', + texticon: 'fa fa-ban', + title: QUILocale.get(lg, 'dialog.invoice.reversal.title', { invoiceId: id }), - text : QUILocale.get(lg, 'dialog.invoice.reversal.text', { + text: QUILocale.get(lg, 'dialog.invoice.reversal.text', { invoiceId: id }), information: QUILocale.get(lg, 'dialog.invoice.reversal.information', { invoiceId: id }), - autoclose : false, - ok_button : { - text : QUILocale.get(lg, 'dialog.invoice.reversal.submit'), + autoclose: false, + ok_button: { + text: QUILocale.get(lg, 'dialog.invoice.reversal.submit'), textimage: 'fa fa-ban' }, - maxHeight : 500, - maxWidth : 750, - events : { - onOpen: function (Win) { - var Container = Win.getContent().getElement('.textbody'); + maxHeight: 500, + maxWidth: 750, + events: { + onOpen: function(Win) { + const Container = Win.getContent().getElement('.textbody'); // #locale - var Label = new Element('label', { - html : '<span>' + QUILocale.get(lg, 'dialog.invoice.reversal.reason.title') + '</span>', + const Label = new Element('label', { + html: '<span>' + QUILocale.get( + lg, + 'dialog.invoice.reversal.reason.title' + ) + '</span>', styles: { - display : 'block', + display: 'block', fontWeight: 'bold', - marginTop : 20, - width : 'calc(100% - 100px)' + marginTop: 20, + width: 'calc(100% - 100px)' } }).inject(Container); - var Reason = new Element('textarea', { - name : 'reason', - autofocus : true, + const Reason = new Element('textarea', { + name: 'reason', + autofocus: true, placeholder: QUILocale.get(lg, 'dialog.invoice.reversal.reason.placeholder'), - styles : { - height : 160, + styles: { + height: 160, marginTop: 10, - width : '100%' + width: '100%' } }).inject(Label); Reason.focus(); }, - onSubmit: function (Win) { - var value = Win.getContent().getElement('[name="reason"]').value; + 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(); + } + return; } 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); }); @@ -138,7 +149,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); }, @@ -148,7 +159,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); }, @@ -158,34 +169,34 @@ 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) { - var id = result.id_prefix + result.id; + 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'), + title: QUILocale.get(lg, 'dialog.invoice.copy.title'), + text: QUILocale.get(lg, 'dialog.invoice.copy.text'), information: QUILocale.get(lg, 'dialog.invoice.copy.information', { id: id }), - icon : 'fa fa-copy', - texticon : 'fa fa-copy', - maxHeight : 400, - maxWidth : 600, - autoclose : false, - ok_button : { - text : QUILocale.get('quiqqer/system', 'copy'), + icon: 'fa fa-copy', + texticon: 'fa fa-copy', + maxHeight: 400, + maxWidth: 600, + autoclose: false, + ok_button: { + text: QUILocale.get('quiqqer/system', 'copy'), textimage: 'fa fa-copy' }, - events : { - onSubmit: function (Win) { + events: { + 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(); }); } @@ -201,38 +212,38 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [ * @param {String} invoiceId - Invoice ID or Hash * @return {Promise} */ - openCreateCreditNoteDialog: function (invoiceId) { - var self = this; + openCreateCreditNoteDialog: function(invoiceId) { + const self = this; - return Invoices.get(invoiceId).then(function (result) { - var paymentHasRefund = false; - var id = result.id_prefix + result.id; + 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', - title : QUILocale.get(lg, 'dialog.invoice.createCreditNote.title', { + icon: 'fa fa-clipboard', + texticon: 'fa fa-clipboard', + title: QUILocale.get(lg, 'dialog.invoice.createCreditNote.title', { invoiceId: id }), - text : QUILocale.get(lg, 'dialog.invoice.createCreditNote.text', { + text: QUILocale.get(lg, 'dialog.invoice.createCreditNote.text', { invoiceId: id }), information: QUILocale.get(lg, 'dialog.invoice.createCreditNote.information', { invoiceId: id }), - autoclose : false, - ok_button : { - text : QUILocale.get(lg, 'dialog.invoice.createCreditNote.submit'), + autoclose: false, + ok_button: { + text: QUILocale.get(lg, 'dialog.invoice.createCreditNote.submit'), textimage: 'fa fa-clipboard' }, - maxHeight : 400, - maxWidth : 600, - events : { - onOpen: function (Win) { + maxHeight: 400, + maxWidth: 600, + events: { + 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]); @@ -242,15 +253,18 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [ return; } - var Content = Win.getContent(), - Body = Content.getElement('.textbody'); + const Content = Win.getContent(), + Body = Content.getElement('.textbody'); new Element('label', { 'class': 'quiqqer-invoice-dialog-refund-label', - html : '<input type="checkbox" name="refund" />' + QUILocale.get(lg, 'dialog.invoice.createCreditNote.refund'), - styles : { - cursor : 'pointer', - display : 'block', + html: '<input type="checkbox" name="refund" />' + QUILocale.get( + lg, + 'dialog.invoice.createCreditNote.refund' + ), + styles: { + cursor: 'pointer', + display: 'block', marginTop: 20 } }).inject(Body); @@ -259,16 +273,16 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [ }); }, - onSubmit: function (Win) { + onSubmit: function(Win) { Win.Loader.show(); - var Content = Win.getContent(), - Refund = Content.getElement('[name="refund"]'); + const Content = Win.getContent(), + Refund = Content.getElement('[name="refund"]'); - var 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] @@ -276,7 +290,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); @@ -285,7 +299,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; @@ -294,7 +308,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); }); @@ -304,7 +318,7 @@ define('package/quiqqer/invoice/bin/backend/utils/Dialogs', [ createInvoice(); }, - onCancel: function () { + onCancel: function() { resolve(false); } } @@ -318,17 +332,17 @@ 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, + invoiceId: invoiceId, autoRefund: false, - events : { + events: { onSubmit: resolve, - onCancel: function () { + onCancel: function() { resolve(false); } } diff --git a/locale.xml b/locale.xml index 5748b3f42e53f1e3ce74311de56c23375a539a7a..7885e89163129065a631e2b818068e5e4dbf14ae 100644 --- a/locale.xml +++ b/locale.xml @@ -666,7 +666,7 @@ </ul> ]]></de> <en><![CDATA[ - <p>Subject of the cancelletion Invoice mail. Available placeholders:</p> + <p>Subject of the cancellation invoice mail. Available placeholders:</p> <ul> <li><b>[invoiceId]:</b> Invoice no.</li> <li><b>[cancelledInvoiceId]:</b> Invoice no. of the <b>cancelled</b> invoice</li> @@ -706,7 +706,7 @@ </ul> ]]></de> <en><![CDATA[ - <p>Content of the cancellation Invoice mail. Available placeholders:</p> + <p>Content of the cancellation invoice mail. Available placeholders:</p> <ul> <li><b>[invoiceId]:</b> Invoice no.</li> <li><b>[cancelledInvoiceId]:</b> Invoice no. of the <b>cancelled</b> invoice</li> @@ -1739,9 +1739,25 @@ <de><![CDATA[Gutschrift zu Rechnung #[id] vom [date]]]></de> <en><![CDATA[Credit Note to invoice #[id] from [date]]]></en> </locale> + <locale name="message.create.reversal.from"> + <de><![CDATA[Storno-Rechnung erstellt aus Rechnung #[invoiceId]]]></de> + <en><![CDATA[Created cancellation invoice from Invoice #[invoiceId]]]></en> + </locale> + <locale name="message.invoice.reversal.additionalInvoiceText" html="true"> + <de><![CDATA[Storno-Rechnung zu Rechnung #[id] vom [date]]]></de> + <en><![CDATA[Cancellation invoice to invoice #[id] from [date]]]></en> + </locale> + <locale name="message.invoice.reversal.additionalInvoiceText.creditNote" html="true"> + <de><![CDATA[Storno-Rechnung zu Gutschrift #[id] vom [date]]]></de> + <en><![CDATA[Cancellation invoice to Credit Note #[id] from [date]]]></en> + </locale> + <locale name="message.create.reversal"> + <de><![CDATA[Storno-Rechnung erstellt. Neue Storno-Rechnungs-ID #[invoiceId]]]></de> + <en><![CDATA[Cancellation invoice invoice. New Cancelletion invoice ID #[invoiceId]]]></en> + </locale> <locale name="message.invoice.cancellationInvoice.additionalInvoiceText" html="true"> <de><![CDATA[Storno-Rechnung zu Rechnung #[id] vom [date]]]></de> - <en><![CDATA[Cancelletion invoice to invoice #[id] from [date]]]></en> + <en><![CDATA[Cancellation invoice to invoice #[id] from [date]]]></en> </locale> <locale name="message.add.history.sent.to"> <de><![CDATA[Rechnung wurde versendet an [recipient]]]></de> @@ -1765,7 +1781,7 @@ </locale> <locale name="invoice.cancelled.title"> <de><![CDATA[Storno-Rechnungsmail]]></de> - <en><![CDATA[Cancelletion Invoice mail]]></en> + <en><![CDATA[Cancellation invoice mail]]></en> </locale> <locale name="invoice.cancelled.description"> <de><![CDATA[ ]]></de> @@ -1821,7 +1837,7 @@ <locale name="invoice.cancelled.send.mail.subject"> <de><![CDATA[Ihre Storno-Rechnung - [invoiceId]]]></de> - <en><![CDATA[Your Cancelletion Invoice - [invoiceId]]]></en> + <en><![CDATA[Your cancellation invoice - [invoiceId]]]></en> </locale> <locale name="invoice.cancelled.send.mail.message"> <de><![CDATA[ diff --git a/src/QUI/ERP/Accounting/Invoice/Handler.php b/src/QUI/ERP/Accounting/Invoice/Handler.php index 94c59dff783fbc8bdccdea9a16f2f9f70bc30b2d..c1db6e441c3e66c03d91848cd75ae443973211ff 100644 --- a/src/QUI/ERP/Accounting/Invoice/Handler.php +++ b/src/QUI/ERP/Accounting/Invoice/Handler.php @@ -10,6 +10,7 @@ use function array_flip; use function explode; +use function is_numeric; use function is_string; use function mb_strtoupper; use function str_replace; @@ -383,21 +384,48 @@ public function getInvoiceByHash(string $hash) /** * Return the data from an invoice * - * @param string|integer $id + * @param integer|string $id * @return array * * @throws Exception * @throws QUI\Exception */ - public function getInvoiceData($id): array + public function getInvoiceData(int|string $id): array { + // check invoice via hash + $result = QUI::getDataBase()->fetch([ + 'from' => self::invoiceTable(), + 'where' => [ + 'hash' => $id + ], + 'limit' => 1 + ]); + + if (!empty($result)) { + $result[0]['id'] = (int)$result[0]['id']; + $result[0]['customer_id'] = (int)$result[0]['customer_id']; + $result[0]['order_id'] = (int)$result[0]['order_id']; + $result[0]['isbrutto'] = (int)$result[0]['isbrutto']; + $result[0]['paid_status'] = (int)$result[0]['paid_status']; + $result[0]['canceled'] = (int)$result[0]['canceled']; + $result[0]['c_user'] = (int)$result[0]['c_user']; + + $result[0]['nettosum'] = (float)$result[0]['nettosum']; + $result[0]['subsum'] = (float)$result[0]['subsum']; + $result[0]['sum'] = (float)$result[0]['sum']; + $result[0]['processing_status'] = (int)$result[0]['processing_status']; + + return $result[0]; + } + + // check invoice via old ids $whereOr = [ 'id_with_prefix' => $id ]; - $idSanitized = \str_replace(Settings::getInstance()->getInvoicePrefix(), '', $id); + $idSanitized = str_replace(Settings::getInstance()->getInvoicePrefix(), '', $id); - if (\is_numeric($idSanitized)) { + if (is_numeric($idSanitized)) { $whereOr['id'] = (int)$idSanitized; } @@ -491,13 +519,13 @@ public function getTemporaryInvoiceByHash(string $hash): InvoiceTemporary /** * Return the data from a temporary invoice * - * @param string|int $id + * @param int|string $id * @return array * * @throws Exception * @throws QUI\Exception */ - public function getTemporaryInvoiceData($id): array + public function getTemporaryInvoiceData(int|string $id): array { $prefix = Settings::getInstance()->getTemporaryInvoicePrefix(); diff --git a/src/QUI/ERP/Accounting/Invoice/Invoice.php b/src/QUI/ERP/Accounting/Invoice/Invoice.php index b46f060fe4cbafaa4b25487820f0d87ebdad06ff..4089b0990d03b5320b07fd64744fa8a533552dc2 100644 --- a/src/QUI/ERP/Accounting/Invoice/Invoice.php +++ b/src/QUI/ERP/Accounting/Invoice/Invoice.php @@ -603,12 +603,12 @@ public function reversal(string $reason, $PermissionUser = null): int ) ); - $CreditNote = $this->createCreditNote( + $Reversal = $this->createReversal( QUI::getUsers()->getSystemUser(), $this->getGlobalProcessId() ); - $CreditNote->setInvoiceType(Handler::TYPE_INVOICE_REVERSAL); + //$CreditNote->setInvoiceType(Handler::TYPE_INVOICE_REVERSAL); // Cancellation invoice extra text $localeCode = QUI::getLocale()->getLocalesByLang( @@ -643,14 +643,14 @@ public function reversal(string $reason, $PermissionUser = null): int } // saving copy - $CreditNote->setAttribute('additional_invoice_text', $message); + $Reversal->setAttribute('additional_invoice_text', $message); - $CreditNote->save(QUI::getUsers()->getSystemUser()); + $Reversal->save(QUI::getUsers()->getSystemUser()); try { Permission::checkPermission('quiqqer.invoice.canEditCancelInvoice', $PermissionUser); } catch (QUI\Exception $Exception) { - $CreditNote->post(QUI::getUsers()->getSystemUser()); + $Reversal->post(QUI::getUsers()->getSystemUser()); } $this->addHistory( @@ -660,7 +660,7 @@ public function reversal(string $reason, $PermissionUser = null): int [ 'username' => $User->getName(), 'uid' => $User->getId(), - 'creditNoteId' => $CreditNote->getId() + 'creditNoteId' => $Reversal->getId() ] ) ); @@ -668,9 +668,9 @@ public function reversal(string $reason, $PermissionUser = null): int // set the invoice status $this->type = Handler::TYPE_INVOICE_CANCEL; - $CreditNote = $CreditNote->post(QUI::getUsers()->getSystemUser()); + $Reversal = $Reversal->post(QUI::getUsers()->getSystemUser()); - $this->data['canceledId'] = $CreditNote->getCleanId(); + $this->data['canceledId'] = $Reversal->getCleanId(); QUI::getDataBase()->update( Handler::getInstance()->invoiceTable(), @@ -686,10 +686,10 @@ public function reversal(string $reason, $PermissionUser = null): int QUI::getEvents()->fireEvent( 'quiqqerInvoiceReversalEnd', - [$this, $CreditNote] + [$this, $Reversal] ); - return $CreditNote->getCleanId(); + return $Reversal->getCleanId(); } /** @@ -1029,6 +1029,178 @@ public function createCreditNote($PermissionUser = null, $globalProcessId = fals return $CreditNote; } + /** + * Create a credit note, set the invoice to credit note + * - Gutschrift + * + * @param null|QUI\Interfaces\Users\User $PermissionUser + * @param bool|string $globalProcessId + * @return InvoiceTemporary + * + * @throws Exception + * @throws QUI\Exception + * @throws QUI\Permissions\Exception + */ + public function createReversal($PermissionUser = null, $globalProcessId = false): InvoiceTemporary + { + Permission::checkPermission('quiqqer.invoice.reversal', $PermissionUser); + + QUI::getEvents()->fireEvent('quiqqerInvoiceCreateReversal', [$this]); + + $Copy = $this->copy(QUI::getUsers()->getSystemUser(), $globalProcessId); + $articles = $Copy->getArticles()->getArticles(); + + // change all prices + $ArticleList = $Copy->getArticles(); + $ArticleList->clear(); + $ArticleList->setCurrency($this->getCurrency()); + + $priceKeyList = [ + 'price', + 'basisPrice', + 'nettoPriceNotRounded', + 'sum', + 'nettoSum', + 'nettoSubSum', + 'nettoPrice', + 'nettoBasisPrice', + 'unitPrice', + ]; + + foreach ($articles as $Article) { + $article = $Article->toArray(); + + foreach ($priceKeyList as $priceKey) { + if (isset($article[$priceKey])) { + $article[$priceKey] = $article[$priceKey] * -1; + } + } + + if (isset($article['calculated'])) { + foreach ($priceKeyList as $priceKey) { + if (isset($article['calculated'][$priceKey])) { + $article['calculated'][$priceKey] = $article['calculated'][$priceKey] * -1; + } + } + } + + if (isset($article['calculated']['vatArray'])) { + $article['calculated']['vatArray']['sum'] = $article['calculated']['vatArray']['sum'] * -1; + } + + $Clone = new QUI\ERP\Accounting\Article($article); + $ArticleList->addArticle($Clone); + } + + $PriceFactors = $ArticleList->getPriceFactors(); + $Currency = $this->getCurrency(); + + /* @var $PriceFactor QUI\ERP\Accounting\PriceFactors\Factor */ + foreach ($PriceFactors as $PriceFactor) { + $PriceFactor->setNettoSum($PriceFactor->getNettoSum() * -1); + $PriceFactor->setSum($PriceFactor->getSum() * -1); + $PriceFactor->setValue($PriceFactor->getValue() * -1); + + $PriceFactor->setNettoSumFormatted($Currency->format($PriceFactor->getNettoSum())); + $PriceFactor->setSumFormatted($Currency->format($PriceFactor->getSum())); + $PriceFactor->setValueText($Currency->format($PriceFactor->getValue())); + } + + $Copy->addHistory( + QUI::getLocale()->get('quiqqer/invoice', 'message.create.reversal.from', [ + 'invoiceParentId' => $this->getId(), + 'invoiceId' => $this->getId() + ]) + ); + + // credit note extra text + $localeCode = QUI::getLocale()->getLocalesByLang( + QUI::getLocale()->getCurrent() + ); + + $Formatter = new IntlDateFormatter( + $localeCode[0], + IntlDateFormatter::SHORT, + IntlDateFormatter::NONE + ); + + $currentDate = $this->getAttribute('date'); + + if (!$currentDate) { + $currentDate = time(); + } else { + $currentDate = strtotime($currentDate); + } + + if ($this->getInvoiceType() === Handler::TYPE_INVOICE_CREDIT_NOTE) { + $message = $this->getCustomer()->getLocale()->get( + 'quiqqer/invoice', + 'message.invoice.reversal.additionalInvoiceText.creditNote', + [ + 'id' => $this->getId(), + 'date' => $Formatter->format($currentDate) + ] + ); + } else { + $message = $this->getCustomer()->getLocale()->get( + 'quiqqer/invoice', + 'message.invoice.reversal.additionalInvoiceText', + [ + 'id' => $this->getId(), + 'date' => $Formatter->format($currentDate) + ] + ); + } + + + $additionalText = $Copy->getAttribute('additional_invoice_text'); + + if (!empty($additionalText)) { + $additionalText .= '<br />'; + } + + $additionalText .= $message; + + // saving copy + $Copy->setData('originalId', $this->getCleanId()); + $Copy->setData('originalIdPrefixed', $this->getId()); + + $Copy->setAttribute('date', date('Y-m-d H:i:s')); + $Copy->setAttribute('additional_invoice_text', $additionalText); + $Copy->setAttribute('currency_data', $this->getAttribute('currency_data')); + $Copy->setInvoiceType(Handler::TYPE_INVOICE_REVERSAL); + + if ($this->getAttribute('invoice_address')) { + try { + $address = json_decode($this->getAttribute('invoice_address'), true); + $Address = new QUI\ERP\Address($address); + + $invoiceAddressId = $Address->getId(); + $invoiceAddress = $Address->toJSON(); + + $Copy->setAttribute('invoice_address_id', $invoiceAddressId); + $Copy->setAttribute('invoice_address', $invoiceAddress); + } catch (\Exception $Exception) { + QUI\System\Log::addDebug($Exception->getMessage()); + } + } + + $Copy->save(QUI::getUsers()->getSystemUser()); + + $this->addHistory( + QUI::getLocale()->get('quiqqer/invoice', 'message.create.reversal', [ + 'invoiceParentId' => $this->getId(), + 'invoiceId' => $Copy->getId() + ]) + ); + + $Reversal = Handler::getInstance()->getTemporaryInvoice($Copy->getId()); + + QUI::getEvents()->fireEvent('quiqqerInvoiceCreateReversalEnd', [$this, $Reversal]); + + return $Reversal; + } + /** * Links an existing transaction (i.e. a transaction that was originally created for a different entity than * this invoice) to this invoice.