diff --git a/ajax/backend/getCouponPrice.php b/ajax/backend/getCouponPrice.php new file mode 100644 index 0000000000000000000000000000000000000000..2204c9ad3d8f30cffc0000385cbaae6bee873594 --- /dev/null +++ b/ajax/backend/getCouponPrice.php @@ -0,0 +1,44 @@ +<?php + +/** + * This file contains package_quiqqer_coupons_ajax_backend_getCouponPrice + */ + +/** + * Return the price factor of this coupon + * + * @param int $couponId - CouponCode ID + * @return array + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_coupons_ajax_backend_getCouponPrice', + function ($couponId, $vat) { + $Coupon = QUI\ERP\Coupons\Handler::getCouponCode($couponId); + $discounts = $Coupon->getDiscounts(); + $price = 0; + + foreach ($discounts as $Discount) { + $PriceFactor = $Discount->toPriceFactor(); + + if ($vat !== false) { + $PriceFactor->setVat($vat); + } + + $PriceFactor->setTitle( + QUI::getLocale()->get('quiqqer/coupons', 'coupon.discount.title', [ + 'code' => $Coupon->getCode() + ]) + ); + + $price = $price + $PriceFactor->getValue(); + } + + + return [ + 'title' => $Coupon->getTitle(), + 'price' => $price + ]; + }, + ['couponId', 'vat'], + 'Permission::checkAdminUser' +); diff --git a/bin/backend/controls/Window.js b/bin/backend/controls/Window.js new file mode 100644 index 0000000000000000000000000000000000000000..925a3206a330ad3ed17a4b7d84dbc0c7a4ea9fcf --- /dev/null +++ b/bin/backend/controls/Window.js @@ -0,0 +1,224 @@ +/** + * @module package/quiqqer/coupons/bin/backend/controls/Window + * @author www.pcsg.de (Henning Leutz) + */ +define('package/quiqqer/coupons/bin/backend/controls/Window', [ + + 'qui/QUI', + 'qui/controls/windows/Confirm', + 'controls/grid/Grid', + 'Locale', + 'package/quiqqer/coupons/bin/backend/CouponCodes', + +], function (QUI, QUIConfirm, Grid, QUILocale, CouponCodes) { + "use strict"; + + const lg = 'quiqqer/coupons'; + + return new Class({ + + Extends: QUIConfirm, + Type : 'package/quiqqer/coupons/bin/backend/controls/Window', + + Binds: [ + '$listRefresh', + '$onOpen', + '$onResize' + ], + + initialize: function (options) { + this.parent(options); + + this.setAttributes({ + icon : 'fa fa-credit-card-alt', + title : QUILocale.get(lg, 'controls.manager.title'), + maxHeight: 600, + maxWidth : 500, + }); + + this.addEvents({ + onOpen : this.$onOpen, + onResize: this.$onResize + }); + }, + + submit: function () { + if (!this.$Grid) { + return; + } + + this.fireEvent('submit', [ + this, + this.$Grid.getSelectedData() + ]); + + if (this.getAttribute('autoclose')) { + this.close(); + } + }, + + $onOpen: function () { + this.getContent().set('html', ''); + this.Loader.show(); + + const Container = new Element('div').inject(this.getContent()); + + this.$Grid = new Grid(Container, { + columnModel : [ + { + header : QUILocale.get('quiqqer/system', 'id'), + dataIndex: 'id', + dataType : 'number', + width : 50 + }, + { + header : QUILocale.get(lg, 'controls.manager.tbl.header.code'), + dataIndex: 'code', + dataType : 'string', + width : 150 + }, + { + header : QUILocale.get(lg, 'controls.manager.tbl.header.title'), + dataIndex: 'title', + dataType : 'string', + width : 200 + }, + { + header : QUILocale.get(lg, 'controls.manager.tbl.header.status'), + dataIndex: 'status', + dataType : 'node', + width : 200, + className: 'clickable' + }, + { + header : QUILocale.get(lg, 'controls.manager.tbl.header.validUntilDate'), + dataIndex: 'validUntilDateText', + dataType : 'string', + width : 150 + }, + { + header : QUILocale.get(lg, 'controls.manager.tbl.header.reusable'), + dataIndex: 'maxUsageLabel', + dataType : 'string', + width : 150 + }, + { + header : QUILocale.get(lg, 'controls.manager.tbl.header.createDate'), + dataIndex: 'createDate', + dataType : 'string', + width : 150 + } + ], + pagination : true, + serverSort : true, + selectable : true, + multipleSelection: true + }); + + + this.$Grid.addEvents({ + onDblClick: () => { + this.submit(); + }, + onRefresh : this.$listRefresh + }); + + this.$Grid.refresh(); + this.$onResize(); + }, + + $onResize: function () { + if (!this.$Grid) { + return; + } + + this.$Grid.setHeight( + this.getContent().getSize().y - 40 + ); + }, + + /** + * Refresh bundle list + * + * @param {Object} Grid + */ + $listRefresh: function (Grid) { + if (!this.$Grid) { + return; + } + + let GridParams = { + sortOn : Grid.getAttribute('sortOn'), + sortBy : Grid.getAttribute('sortBy'), + perPage: Grid.getAttribute('perPage'), + page : Grid.getAttribute('page') + }; + + switch (GridParams.sortOn) { + case 'status': + GridParams.sortOn = 'useDate'; + break; + + case 'user': + GridParams.sortOn = 'userId'; + break; + } + + this.Loader.show(); + + CouponCodes.getList(GridParams).then((ResultData) => { + this.Loader.hide(); + this.$setGridData(ResultData); + }); + }, + + /** + * Set license data to grid + * + * @param {Object} GridData + */ + $setGridData: function (GridData) { + let textUnlimited = QUILocale.get(lg, 'controls.manager.tbl.validUntil.unlimited'); + + for (let i = 0, len = GridData.data.length; i < len; i++) { + let Row = GridData.data[i]; + + let StatusElm = new Element('span', { + 'class': 'quiqqer-coupons-manager-tbl-status' + }); + + let usageCount = Row.usages.length; + + if (!Row.isValid) { + StatusElm.set('html', QUILocale.get(lg, 'controls.manager.tbl.status.invalid', { + usageCount: usageCount + })); + + StatusElm.addClass('quiqqer-coupons-manager-tbl-status-invalid'); + } else { + StatusElm.set('html', QUILocale.get(lg, 'controls.manager.tbl.status.valid', { + usageCount: usageCount + })); + + StatusElm.addClass('quiqqer-coupons-manager-tbl-status-used'); + } + + Row.status = StatusElm; + + if (!Row.validUntilDate) { + Row.validUntilDateText = textUnlimited; + } else { + Row.validUntilDateText = Row.validUntilDate; + } + + if (!Row.title) { + Row.title = '-'; + } + + Row.maxUsageLabel = QUILocale.get(lg, 'controls.manager.tbl.maxUsageLabel.' + Row.maxUsages); + } + + this.$Grid.setData(GridData); + } + }); +}); \ No newline at end of file diff --git a/bin/backend/load.js b/bin/backend/load.js new file mode 100644 index 0000000000000000000000000000000000000000..451e8f614d0164bf352d7de321c3302b77037e43 --- /dev/null +++ b/bin/backend/load.js @@ -0,0 +1,88 @@ +require(['qui/QUI'], function (QUI) { + "use strict"; + + + function getCouponPrice(couponId, vat) { + return new Promise(function (resolve) { + require(['Ajax'], function (QUIAjax) { + QUIAjax.get('package_quiqqer_coupons_ajax_backend_getCouponPrice', resolve, { + 'package': 'quiqqer/coupons', + couponId : couponId, + vat : vat + }); + }); + }); + } + + QUI.addEvent('quiqqerErpPriceFactorWindow', function (PriceFactorWindow) { + const Content = PriceFactorWindow.getContent(); + const Buttons = Content.getElement('.quiqqer-erp-priceFactors-button'); + const ArticleList = PriceFactorWindow.getArticleList(); + + require(['Locale'], function (QUILocale) { + new Element('button', { + 'class': 'qui-button', + html : '<span class="fa fa-credit-card-alt"></span>', + title : QUILocale.get('quiqqer/coupons', 'add.coupon.priceFactor'), + styles : { + 'float' : 'right', + marginRight: '10px' + }, + events : { + click: function (e) { + e.stop(); + + require([ + 'package/quiqqer/coupons/bin/backend/controls/Window' + ], function (CouponWindow) { + new CouponWindow({ + multiple: true, + events : { + onSubmit: function (Instance, value) { + if (!value.length) { + return; + } + + const currency = ArticleList.getAttribute('currency'); + const vat = ArticleList.getVat(); + let couponData; + + getCouponPrice(value[0].id, vat).then(function (result) { + couponData = result; + + return PriceFactorWindow.getPriceFactorData( + couponData.price, + vat, + currency + ); + }).then((data) => { + let priceFactor = { + calculation : 2, + calculation_basis: 2, + description : couponData.title, + identifier : "", + index : ArticleList.countPriceFactors(), + nettoSum : data.nettoSum, + nettoSumFormatted: data.nettoSumFormatted, + sum : data.sum, + sumFormatted : data.sumFormatted, + title : couponData.title, + value : data.sum, + valueText : data.valueText, + vat : vat, + visible : 1 + }; + + ArticleList.addPriceFactor(priceFactor); + PriceFactorWindow.refresh(); + }); + } + } + }).open(); + }); + } + } + }).inject(Buttons); + }); + }); +}); diff --git a/events.xml b/events.xml index ae15fb722fb8109dabb62b011398375229f88098..f061d54bc4132bc07c6922a21e76466a0103d99d 100644 --- a/events.xml +++ b/events.xml @@ -1,8 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <events> - <event on="onPackageSetup-quiqqer/coupons" - fire="\QUI\ERP\Coupons\Events::onPackageSetup" - /> + <event on="onPackageSetup-quiqqer/coupons" fire="\QUI\ERP\Coupons\Events::onPackageSetup"/> + <event on="onAdminLoadFooter" fire="\QUI\ERP\Coupons\Events::onAdminLoadFooter"/> <event on="onQuiqqerProductsProductCreate" fire="\QUI\ERP\Coupons\Events::onQuiqqerProductsProductCreate" diff --git a/locale.xml b/locale.xml index 8c91d79aea377e9ff3eb184deb12d2ea367fd16b..f9dd6534b97f80148ec33063fe6c8b77ffa1e465 100644 --- a/locale.xml +++ b/locale.xml @@ -19,6 +19,10 @@ <de><![CDATA[Gutschein-Codes]]></de> <en><![CDATA[Coupon codes]]></en> </locale> + <locale name="add.coupon.priceFactor"> + <de><![CDATA[Gutschein-Code hinzufügen]]></de> + <en><![CDATA[Add a coupon code]]></en> + </locale> <!-- Settings --> <locale name="settings.title"> @@ -131,16 +135,20 @@ Best Wishes<br/> <locale name="ProductCoupon.mail.transferable_info.is_transferable"> <de> <![CDATA[Sie dürfen diesen Gutschein verschenken! Der Gutschein-Code ist nicht personalisiert und kann von jedem in unserem Shop eingelöst werden. Bewahren Sie ihn daher gut auf!]]></de> - <en><![CDATA[You may give this coupn as a gift! The coupon code is not personalized and can be redeemed by anyone in our store. Therefore, keep it safe!]]></en> + <en> + <![CDATA[You may give this coupn as a gift! The coupon code is not personalized and can be redeemed by anyone in our store. Therefore, keep it safe!]]></en> </locale> <locale name="ProductCoupon.mail.transferable_info.is_not_transferable"> <de> <![CDATA[Bitte bachten Sie: Dieser Gutschein kann nur von Ihnen persönlich eingesetzt werden, wenn Sie in unserem Shop eingeloggt sind. Dritte können den Gutschein-Code nicht einlösen.]]></de> - <en><![CDATA[Please note: This voucher can only be used by you personally when you are logged in to our store. Third parties can not redeem the voucher code.]]></en> + <en> + <![CDATA[Please note: This voucher can only be used by you personally when you are logged in to our store. Third parties can not redeem the voucher code.]]></en> </locale> <locale name="ProductCoupon.mail.profile_download_info"> - <de><![CDATA[Sie finden den Gutschein als PDF-Datei im Anhang oder in Ihrem Benutzer-Profil in unserem Shop (bitte vorher einloggen).]]></de> - <en><![CDATA[You can find the coupon as a PDF file attached or in your user profile in our shop (please log in first).]]></en> + <de> + <![CDATA[Sie finden den Gutschein als PDF-Datei im Anhang oder in Ihrem Benutzer-Profil in unserem Shop (bitte vorher einloggen).]]></de> + <en> + <![CDATA[You can find the coupon as a PDF file attached or in your user profile in our shop (please log in first).]]></en> </locale> <locale name="ProductCoupon.coupon_title"> <de><![CDATA[Produkt #[productId] aus Bestellung [orderId]]]></de> @@ -152,8 +160,10 @@ Best Wishes<br/> <en><![CDATA[[productTitle]__[date]]]></en> </locale> <locale name="DownloadProduct.Order.history.coupon_code"> - <de><![CDATA[Gutschein-Code generiert für Bestellung von Produkt "[productTitle]" (#[productId]) -> [couponCode] ([couponAmount])]]></de> - <en><![CDATA[Coupon code generated for order of product "[productTitle]" (#[productId]) -> [couponCode] ([couponAmount])]]></en> + <de> + <![CDATA[Gutschein-Code generiert für Bestellung von Produkt "[productTitle]" (#[productId]) -> [couponCode] ([couponAmount])]]></de> + <en> + <![CDATA[Coupon code generated for order of product "[productTitle]" (#[productId]) -> [couponCode] ([couponAmount])]]></en> </locale> <locale name="DownloadProduct.Order.history.coupon_code_send_mail"> <de><![CDATA[Gutschein-Code "[couponCode]" per E-Mail an Kunden versandt ([customerMail]).]]></de> @@ -198,7 +208,8 @@ Best Wishes<br/> <en><![CDATA[Coupon (digital)]]></en> </locale> <locale name="product_type.DigitalCouponProductType.description"> - <de><![CDATA[Gutschein, der ausschließlich digital angeboten wird (Versand per E-Mail und/oder PDF-Download).]]></de> + <de> + <![CDATA[Gutschein, der ausschließlich digital angeboten wird (Versand per E-Mail und/oder PDF-Download).]]></de> <en><![CDATA[Coupon offered exclusively digitally (sent by e-mail and/or PDF download).]]></en> </locale> <locale name="product_type.PhysicalCouponProductType.title"> @@ -206,7 +217,8 @@ Best Wishes<br/> <en><![CDATA[Coupon (physical)]]></en> </locale> <locale name="product_type.PhysicalCouponProductType.description"> - <de><![CDATA[Gutschein, der physisch erstellt und versandt wird (kann zusätzlich auch digital angeboten werden).]]></de> + <de> + <![CDATA[Gutschein, der physisch erstellt und versandt wird (kann zusätzlich auch digital angeboten werden).]]></de> <en><![CDATA[Coupon that is physically created and shipped (can additionally be offered digitally).]]></en> </locale> @@ -292,10 +304,12 @@ Best Wishes<br/> <![CDATA[Bitte geben Sie mindestens einen Rabatt an, der mit dem Coupon-Code verknüpft werden soll.]]></de> <en><![CDATA[Please provide ad least on discount that shall be linked to the Coupon code.]]></en> </locale> - + <locale name="exception.CouponProduct.no_vat_tax_type_required" html="true"> - <de><![CDATA[Das Gutschein-Produkt "[productTitle]" (#[productId]) kann nicht aktiviert werden.<br/><br/>Es handelt sich um einen Mehrzweck- bzw. Geldwert-Gutschein, welcher beim Kauf nicht versteuert werden darf.<br/><br/>Der im Produkt ausgewählte Steuertyp (Feld "MwSt.") enthält jedoch Steuersätze, die über 0% liegen.<br/><br/>Bitte wähle einen Steuertyp, welcher ausschließlich 0%-Steuersätze enthält oder ändere den Gutschein-Typ zu "Einzweck-Gutschein".]]></de> - <en><![CDATA[The coupon product "[productTitle]" (#[productId]) cannot be activated.<br/><br/>It is a multipurpose / cash value voucher, which must not be taxed at the time of purchase.<br/><br/>However, the tax type selected for this product ("VAT" field) contains tax entries with tax values higher than 0%.<br/><br/>Please choose a tax type which contains only 0% tax rates or change the coupon type to "Single purpose coupon".]]></en> + <de> + <![CDATA[Das Gutschein-Produkt "[productTitle]" (#[productId]) kann nicht aktiviert werden.<br/><br/>Es handelt sich um einen Mehrzweck- bzw. Geldwert-Gutschein, welcher beim Kauf nicht versteuert werden darf.<br/><br/>Der im Produkt ausgewählte Steuertyp (Feld "MwSt.") enthält jedoch Steuersätze, die über 0% liegen.<br/><br/>Bitte wähle einen Steuertyp, welcher ausschließlich 0%-Steuersätze enthält oder ändere den Gutschein-Typ zu "Einzweck-Gutschein".]]></de> + <en> + <![CDATA[The coupon product "[productTitle]" (#[productId]) cannot be activated.<br/><br/>It is a multipurpose / cash value voucher, which must not be taxed at the time of purchase.<br/><br/>However, the tax type selected for this product ("VAT" field) contains tax entries with tax values higher than 0%.<br/><br/>Please choose a tax type which contains only 0% tax rates or change the coupon type to "Single purpose coupon".]]></en> </locale> </groups> @@ -314,8 +328,10 @@ Best Wishes<br/> <en><![CDATA[Usage (optional)]]></en> </locale> <locale name="controls.manager.create.template.descTitle"> - <de><![CDATA[Dient der <b>internen</b> Beschreibung des Verwendungszwecks für diesen Gutschein-Code. Kunden sehen diese Beschreibung <b>nicht</b>.]]></de> - <en><![CDATA[Used for <b>internal</b> description of the purpose for this coupon code. Customers will <b>not</b> see this description.]]></en> + <de> + <![CDATA[Dient der <b>internen</b> Beschreibung des Verwendungszwecks für diesen Gutschein-Code. Kunden sehen diese Beschreibung <b>nicht</b>.]]></de> + <en> + <![CDATA[Used for <b>internal</b> description of the purpose for this coupon code. Customers will <b>not</b> see this description.]]></en> </locale> <locale name="controls.manager.create.template.labelAmount"> <de><![CDATA[Anzahl generierte Gutschein-Codes]]></de> @@ -334,7 +350,8 @@ Best Wishes<br/> <en><![CDATA[Coupon code (optional)]]></en> </locale> <locale name="controls.manager.create.template.descCode"> - <de><![CDATA[Wird dieses Feld leergelassen, wird automatisch ein zufälliger neuer Gutschein-Code generiert.]]></de> + <de> + <![CDATA[Wird dieses Feld leergelassen, wird automatisch ein zufälliger neuer Gutschein-Code generiert.]]></de> <en><![CDATA[If this field is left blank, a random new coupon code will be generated automatically.]]></en> </locale> <locale name="controls.manager.create.template.labelReusable"> diff --git a/src/QUI/ERP/Coupons/Events.php b/src/QUI/ERP/Coupons/Events.php index a7e214b60e6d1a0a79e4d533894389491e2fd403..c17b142874aef373ba4e96019e1bf68b82ca59da 100644 --- a/src/QUI/ERP/Coupons/Events.php +++ b/src/QUI/ERP/Coupons/Events.php @@ -3,19 +3,19 @@ namespace QUI\ERP\Coupons; use QUI; +use QUI\ERP\Accounting\Calc as ErpCalc; +use QUI\ERP\Coupons\Handler as CouponsHandler; +use QUI\ERP\Coupons\Products\CouponProductException; +use QUI\ERP\Coupons\Products\DigitalCouponProductType; +use QUI\ERP\Coupons\Products\Handler as CouponProductsHandler; +use QUI\ERP\Coupons\Products\PhysicalCouponProductType; +use QUI\ERP\Discount\EventHandling as DiscountEvents; use QUI\ERP\Order\AbstractOrder; +use QUI\ERP\Order\Basket\Basket; +use QUI\ERP\Order\Basket\BasketGuest; use QUI\ERP\Products\Handler\Fields; use QUI\ERP\Products\Interfaces\ProductInterface; use Quiqqer\Engine\Collector; -use QUI\ERP\Order\Basket\Basket; -use QUI\ERP\Order\Basket\BasketGuest; -use QUI\ERP\Coupons\Handler as CouponsHandler; -use QUI\ERP\Discount\EventHandling as DiscountEvents; -use QUI\ERP\Coupons\Products\DigitalCouponProductType; -use QUI\ERP\Coupons\Products\PhysicalCouponProductType; -use QUI\ERP\Coupons\Products\CouponProductException; -use QUI\ERP\Accounting\Calc as ErpCalc; -use QUI\ERP\Coupons\Products\Handler as CouponProductsHandler; /** * Class Events @@ -39,6 +39,14 @@ public static function onPackageSetup(QUI\Package\Package $Package) } } + /** + * event : on admin load footer + */ + public static function onAdminLoadFooter() + { + echo '<script src="' . URL_OPT_DIR . 'quiqqer/coupons/bin/backend/load.js"></script>'; + } + /** * Template event quiqqer/order: onQuiqqer::order::orderProcessBasketEnd * @@ -290,7 +298,9 @@ public static function onQuiqqerOrderBasketToOrder( ); $isUnique = $Discount->getAttribute('scope') === QUI\ERP\Discount\Handler::DISCOUNT_SCOPE_UNIQUE; - $everyProduct = $Discount->getAttribute('scope') === QUI\ERP\Discount\Handler::DISCOUNT_SCOPE_EVERY_PRODUCT; + $everyProduct = $Discount->getAttribute( + 'scope' + ) === QUI\ERP\Discount\Handler::DISCOUNT_SCOPE_EVERY_PRODUCT; if ($everyProduct || $isUnique) { // add to the product @@ -443,10 +453,10 @@ protected static function createProductFields() ], 'description' => [ 'de' => 'Übertragbare Gutscheine sind auch von anderen Personen als dem Käufer einlösbar.' - .' Nicht übertragbare Gutscheine können nur vom Käufer eingelöst werden, wenn dieser' - .' eingeloggt ist.', + . ' Nicht übertragbare Gutscheine können nur vom Käufer eingelöst werden, wenn dieser' + . ' eingeloggt ist.', 'en' => 'Transferable coupons are also redeemable by persons other than the buyer.' - .' Non-transferable vouchers can only be redeemed by the buyer when logged in.' + . ' Non-transferable vouchers can only be redeemed by the buyer when logged in.' ], 'type' => Fields::TYPE_BOOL, 'public' => false, @@ -460,11 +470,11 @@ protected static function createProductFields() ], 'description' => [ 'de' => 'Der Gutschein-Code wird dem Käufer per E-Mail gesendet. Gilt nicht, wenn der Benutzer zw.' - .' Post- und Mail-Versand wählen kann und den Postversand auswählt.' - .' Wird der Gutschein auch als PDF-Datei generiert, wird die PDF-Datei an diese E-Mail angehanden.', + . ' Post- und Mail-Versand wählen kann und den Postversand auswählt.' + . ' Wird der Gutschein auch als PDF-Datei generiert, wird die PDF-Datei an diese E-Mail angehanden.', 'en' => 'The coupon code is sent to the buyer via email. It is not sent if the customer is able to' - .' choose between email and mail delivery type and chooses delivery by mail.' - .' If the coupon is also generated as a PDF file, the file is attached to this email.' + . ' choose between email and mail delivery type and chooses delivery by mail.' + . ' If the coupon is also generated as a PDF file, the file is attached to this email.' ], 'type' => Fields::TYPE_BOOL, 'public' => false, @@ -478,11 +488,11 @@ protected static function createProductFields() ], 'description' => [ 'de' => 'Der Gutschein wird auch als PDF-Datei erstellt und dem Käufer (je nach Wahl) per E-Mail gesendet.' - .' Zusätzlich wird die PDF-Datei dem Käufer in seinem Frontend-Profil (sofern eingerichtet)' - .' bereitgestellt.', + . ' Zusätzlich wird die PDF-Datei dem Käufer in seinem Frontend-Profil (sofern eingerichtet)' + . ' bereitgestellt.', 'en' => 'The coupon is also generated as a PDF file and is sent to the customer (depending on choice)' - .' via email. Additionally, the PDF file is made available via the customers frontend profile' - .' (if set up).' + . ' via email. Additionally, the PDF file is made available via the customers frontend profile' + . ' (if set up).' ], 'type' => Fields::TYPE_BOOL, 'public' => false, @@ -530,13 +540,13 @@ protected static function createProductFields() ], 'description' => [ 'de' => 'Einzweck-Gutscheine sind solche, bei denen die Besteuerung und der Leistungsort bereits' - .' beim Gutschein-Kauf feststehen. Beispiel: Gutschein für eine Massage in einem Spa.' - .' Alles andere (wie z.B. Wertgutscheine für den Einsatz unabhängig vom Artikel) sind' - .' Mehrzweck-Gutscheine und werden bei Einkauf nicht besteuert.', + . ' beim Gutschein-Kauf feststehen. Beispiel: Gutschein für eine Massage in einem Spa.' + . ' Alles andere (wie z.B. Wertgutscheine für den Einsatz unabhängig vom Artikel) sind' + . ' Mehrzweck-Gutscheine und werden bei Einkauf nicht besteuert.', 'en' => 'Single-purpose coupons are those for which the taxation and place of performance are already' - .' determined at the time of coupon purchase. Example: voucher for a massage in a spa.' - .' Everything else (such as money value coupons for use regardless of the item) are' - .' multi-purpose coupons and are not taxed at the time of purchase.' + . ' determined at the time of coupon purchase. Example: voucher for a massage in a spa.' + . ' Everything else (such as money value coupons for use regardless of the item) are' + . ' multi-purpose coupons and are not taxed at the time of purchase.' ], 'type' => Fields::TYPE_BOOL, 'public' => false, @@ -584,9 +594,9 @@ protected static function createProductFields() ], 'description' => [ 'de' => 'Ist diese Funktion aktiviert, kann der Kunde beim Artikel im Shop wählen, ob der Gutschein' - .' per E - Mail oder Post versandt werden soll.', + . ' per E - Mail oder Post versandt werden soll.', 'en' => 'if this option is enabled, the customer can choose at the article in the store whether the' - .' coupon should be sent by e - mail or by(physical) mail.' + . ' coupon should be sent by e - mail or by(physical) mail.' ], 'type' => Fields::TYPE_BOOL, 'public' => false, @@ -705,7 +715,9 @@ public static function onQuiqqerProductsProductActivate(ProductInterface $Produc return; } - $isSinglePurposeCoupon = $Product->getFieldValue(CouponProductsHandler::PRODUCT_FIELD_ID_IS_SINGLE_PURPOSE_COUPON); + $isSinglePurposeCoupon = $Product->getFieldValue( + CouponProductsHandler::PRODUCT_FIELD_ID_IS_SINGLE_PURPOSE_COUPON + ); if (!empty($isSinglePurposeCoupon)) { return;