diff --git a/ajax/create.php b/ajax/create.php index 4ec050cbf6a41d9622b05d91fe626dab0dfe872a..092c3b245b0204edf0c44024a124dce740af860b 100644 --- a/ajax/create.php +++ b/ajax/create.php @@ -8,7 +8,7 @@ use QUI\Utils\Security\Orthos; /** - * Create new InviteCode(s) + * Create new CouponCode(s) * * @param array $attributes * @return bool - success @@ -27,18 +27,26 @@ function ($attributes) { unset($attributes['amount']); } + $discountIds = []; + + if (!empty($attributes['discountIds'])) { + $discountIds = explode(',', $attributes['discountIds']); + } + for ($i = 0; $i < $amount; $i++) { - $couponCodes[] = Handler::createCouponCode($attributes); + $couponCodes[] = Handler::createCouponCode($discountIds, $attributes); } + // @todo TEST-CODE - REMOVE LATER! /** @var \QUI\ERP\Coupons\CouponCode $Code */ foreach ($couponCodes as $Code) { $Code->redeem(); } + //********************************************* } catch (\QUI\ERP\Coupons\CouponCodeException $Exception) { QUI::getMessagesHandler()->addError( QUI::getLocale()->get( - 'quiqqer/invitecode', + 'quiqqer/coupons', 'message.ajax.create.error', [ 'error' => $Exception->getMessage() @@ -54,7 +62,7 @@ function ($attributes) { QUI::getMessagesHandler()->addError( QUI::getLocale()->get( - 'quiqqer/invitecode', + 'quiqqer/coupons', 'message.ajax.general_error' ) ); @@ -64,7 +72,7 @@ function ($attributes) { QUI::getMessagesHandler()->addSuccess( QUI::getLocale()->get( - 'quiqqer/invitecode', + 'quiqqer/coupons', 'message.ajax.create.success' ) ); diff --git a/ajax/delete.php b/ajax/delete.php index b6da82b9865f4cf93ca3d1882d051fb780a7fe1f..4e4581588391112a169beef44ab5f685768a6efd 100644 --- a/ajax/delete.php +++ b/ajax/delete.php @@ -8,9 +8,9 @@ use QUI\Utils\Security\Orthos; /** - * Delete InviteCodes + * Delete CouponCodes * - * @param array $ids - InviteCode IDs + * @param array $ids - CouponCode IDs * @return bool - success */ QUI::$Ajax->registerFunction( @@ -26,7 +26,7 @@ function ($ids) { } catch (\QUI\ERP\Coupons\CouponCodeException $Exception) { QUI::getMessagesHandler()->addError( QUI::getLocale()->get( - 'quiqqer/invitecode', + 'quiqqer/coupons', 'message.ajax.delete.error', array( 'error' => $Exception->getMessage() @@ -42,7 +42,7 @@ function ($ids) { QUI::getMessagesHandler()->addError( QUI::getLocale()->get( - 'quiqqer/invitecode', + 'quiqqer/coupons', 'message.ajax.general_error' ) ); @@ -52,7 +52,7 @@ function ($ids) { QUI::getMessagesHandler()->addSuccess( QUI::getLocale()->get( - 'quiqqer/invitecode', + 'quiqqer/coupons', 'message.ajax.delete.success' ) ); diff --git a/ajax/edit.php b/ajax/edit.php new file mode 100644 index 0000000000000000000000000000000000000000..02f1dd621452b8d13610495af96fd7953be41e2f --- /dev/null +++ b/ajax/edit.php @@ -0,0 +1,72 @@ +<?php + +/** + * This file contains package_quiqqer_coupons_ajax_create + */ + +use QUI\ERP\Coupons\Handler; +use QUI\Utils\Security\Orthos; + +/** + * Edit a CouponCode + * + * @param array $attributes + * @return bool - success + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_coupons_ajax_edit', + function ($id, $attributes) { + $id = (int)$id; + $attributes = Orthos::clearArray(json_decode($attributes, true)); + + try { + $discountIds = []; + + if (!empty($attributes['discountIds'])) { + $discountIds = explode(',', $attributes['discountIds']); + } + + $couponCodes[] = Handler::editCouponCode($id, $discountIds, $attributes); + } catch (\QUI\ERP\Coupons\CouponCodeException $Exception) { + QUI::getMessagesHandler()->addError( + QUI::getLocale()->get( + 'quiqqer/coupons', + 'message.ajax.edit.error', + [ + 'id' => $id, + 'error' => $Exception->getMessage() + ] + ) + ); + + return false; + } catch (QUI\Permissions\Exception $Exception) { + throw $Exception; + } catch (\Exception $Exception) { + QUI\System\Log::writeException($Exception); + + QUI::getMessagesHandler()->addError( + QUI::getLocale()->get( + 'quiqqer/coupons', + 'message.ajax.general_error' + ) + ); + + return false; + } + + QUI::getMessagesHandler()->addSuccess( + QUI::getLocale()->get( + 'quiqqer/coupons', + 'message.ajax.edit.success', + [ + 'id' => $id + ] + ) + ); + + return true; + }, + ['id', 'attributes'], + 'Permission::checkAdminUser' +); diff --git a/ajax/getList.php b/ajax/getList.php index 9f730c890963a42e2965d22cd8bb719cc176909c..395ff7ae949e39d3c30fd697f41746fd4a760358 100644 --- a/ajax/getList.php +++ b/ajax/getList.php @@ -21,32 +21,32 @@ function ($searchParams) { Permission::hasPermission(Handler::PERMISSION_VIEW); $searchParams = Orthos::clearArray(json_decode($searchParams, true)); - $inviteCodes = []; + $couponCodes = []; $Users = QUI::getUsers(); $L = QUI::getLocale(); try { - foreach (Handler::search($searchParams) as $InviteCode) { - $inviteCode = $InviteCode->toArray(); + foreach (Handler::search($searchParams) as $CouponCode) { + $couponCode = $CouponCode->toArray(); - foreach ($inviteCode['usages'] as $k => $usage) { + foreach ($couponCode['usages'] as $k => $usage) { // User $User = $Users->get($usage['userId']); - $inviteCode['usages'][$k]['userName'] = $User->getUsername(); + $couponCode['usages'][$k]['userName'] = $User->getUsername(); // Date $Date = new DateTime($usage['date']); - $inviteCode['usages'][$k]['date'] = $L->formatDate($Date->getTimestamp()); + $couponCode['usages'][$k]['date'] = $L->formatDate($Date->getTimestamp()); } - $inviteCodes[] = $inviteCode; + $couponCodes[] = $couponCode; } } catch (\Exception $Exception) { QUI\System\Log::writeException($Exception); QUI::getMessagesHandler()->addSuccess( QUI::getLocale()->get( - 'quiqqer/invitecode', + 'quiqqer/coupons', 'message.ajax.general_error' ) ); @@ -57,7 +57,7 @@ function ($searchParams) { $Grid = new Grid($searchParams); return $Grid->parseResult( - $inviteCodes, + $couponCodes, Handler::search($searchParams, true) ); }, diff --git a/bin/classes/CouponCodes.js b/bin/classes/CouponCodes.js index 54241c086e05f36ceace0806fdd90c63ed6903df..88a3f6dfee400bca7248b3535cb1d2ec0e578ed8 100644 --- a/bin/classes/CouponCodes.js +++ b/bin/classes/CouponCodes.js @@ -20,7 +20,7 @@ define('package/quiqqer/coupons/bin/classes/CouponCodes', [ Type: 'package/quiqqer/coupons/bin/classes/CouponCodes', /** - * Create new InviteCode + * Create new CouponCode * * @param {Object} Attributes * @return {Promise} @@ -35,6 +35,24 @@ define('package/quiqqer/coupons/bin/classes/CouponCodes', [ }); }, + /** + * Edit a CouponCode + * + * @param {Number} id + * @param {Object} Attributes + * @return {Promise} + */ + edit: function (id, Attributes) { + return new Promise(function (resolve, reject) { + QUIAjax.post('package_quiqqer_coupons_ajax_edit', resolve, { + 'package' : pkg, + id : id, + attributes: JSON.encode(Attributes), + onError : reject + }); + }); + }, + /** * Delete Invite Codes * diff --git a/bin/controls/Manager.Create.html b/bin/controls/Manager.Create.html index 906a68b15b3be3459260b138b3f0192c0a92e852..23c82ac559932f35a21835a36f9fffdda1d35c6f 100644 --- a/bin/controls/Manager.Create.html +++ b/bin/controls/Manager.Create.html @@ -1,32 +1,39 @@ <div class="quiqqer-coupons-manager-create"> <form> <label> - <span>{{labelTitle}}</span> - <input type="text" name="title"/> - </label> - <label> - <span>{{labelCode}}</span> - <input type="text" name="code"/> - </label> - <label> - <span>{{labelUsers}}</span> - <input type="hidden" name="userIds" data-qui="controls/users/Select"/> - </label> - <label> - <span>{{labelUsers}}</span> - <input type="hidden" name="groupIds" data-qui="controls/groups/Select"/> - </label> - <label> - <span>{{labelReusable}}</span> - <input type="checkbox" name="reusable"/> - </label> - <label> - <span>{{labelDate}}</span> - <input type="date" placeholder="YYYY-MM-DD HH:MM" name="validUntil"/> - </label> - <label> - <span>{{labelAmount}}</span> - <input type="number" name="amount" min="1" value="1"/> + <span>{{labelDiscount}}</span> + <input type="hidden" name="discountIds" data-qui="package/quiqqer/discount/bin/controls/Select"/> </label> + <div class="quiqqer-coupons-manager-create-settings-btn"></div> + <div class="quiqqer-coupons-manager-create-settings"> + <label> + <span>{{labelTitle}}</span> + <input type="text" name="title"/> + </label> + <label> + <span>{{labelCode}}</span> + <input type="text" name="code"/> + </label> + <label> + <span>{{labelUsers}}</span> + <input type="hidden" name="userIds" data-qui="controls/users/Select"/> + </label> + <label> + <span>{{labelUsers}}</span> + <input type="hidden" name="groupIds" data-qui="controls/groups/Select"/> + </label> + <label> + <span>{{labelReusable}}</span> + <input type="checkbox" name="reusable"/> + </label> + <label> + <span>{{labelDate}}</span> + <input type="date" placeholder="YYYY-MM-DD HH:MM" name="validUntilDate"/> + </label> + <label> + <span>{{labelAmount}}</span> + <input type="number" name="amount" min="1" value="1"/> + </label> + </div> </form> </div> \ No newline at end of file diff --git a/bin/controls/Manager.Usages.html b/bin/controls/Manager.Usages.html index 2cab532b17aac905ef3079f21e8c09d93adc762f..5a3b5ec5004f500acc16960276d2a9106f727d26 100644 --- a/bin/controls/Manager.Usages.html +++ b/bin/controls/Manager.Usages.html @@ -2,7 +2,7 @@ <table> <thead> <tr> - <th> + <th class="quiqqer-coupons-manager-usages-tbl-date"> {{headerDate}} </th> <th> diff --git a/bin/controls/Manager.css b/bin/controls/Manager.css index feaa18e00ba8835789f7de4f8ddf641f1673e073..63977b11469e8a721630359c2e3b1c5b6138cfb5 100644 --- a/bin/controls/Manager.css +++ b/bin/controls/Manager.css @@ -10,6 +10,10 @@ width: 100%; } +/**** + * CREATE + ****/ + .quiqqer-coupons-manager-create label { float: left; width: 100%; @@ -36,6 +40,20 @@ width: 100%; } +.quiqqer-coupons-manager-create-settings { + display: none; +} + +.quiqqer-coupons-manager-create-settings-btn { + float: left; + margin: 15px 0; + width: 100%; +} + +.quiqqer-coupons-manager-create-settings-btn button { + width: 100%; +} + .quiqqer-coupons-manager-tbl-status-unused { color: #bb252a; } @@ -61,4 +79,8 @@ .quiqqer-coupons-manager-tbl-user-not_exist { color: #999; font-style: italic; +} + +.quiqqer-coupons-manager-usages-tbl-date { + width: 150px; } \ No newline at end of file diff --git a/bin/controls/Manager.js b/bin/controls/Manager.js index 0c4dde050fb403a82c394ac6897de0da1fce84c0..1d138ea9c3a26b6df4238213935f93351417f058 100644 --- a/bin/controls/Manager.js +++ b/bin/controls/Manager.js @@ -46,7 +46,7 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ '$onRefresh', '$load', '$setGridData', - '$create', + '$showDetails', '$toggleActiveStatus', '$managePackages', '$delete', @@ -90,24 +90,24 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ textimage: 'fa fa-plus', events : { onClick: function () { - self.$create(); + self.$showDetails(); } } }); + this.addButton(new QUISeparator()); + this.addButton({ - name : 'quickcreate', - text : QUILocale.get(lg, 'controls.manager.tbl.btn.quickcreate'), - textimage: 'fa fa-plus', + name : 'edit', + text : QUILocale.get(lg, 'controls.manager.tbl.btn.edit'), + textimage: 'fa fa-edit', events : { onClick: function () { - self.$create(true); + self.$showDetails(Object.clone(self.$Grid.getSelectedData()[0])); } } }); - this.addButton(new QUISeparator()); - this.addButton({ name : 'delete', text : QUILocale.get(lg, 'controls.manager.tbl.btn.delete'), @@ -178,12 +178,12 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ className: 'clickable' }, { header : QUILocale.get(lg, 'controls.manager.tbl.header.validUntilDate'), - dataIndex: 'validUntilDate', + dataIndex: 'validUntilDateText', dataType : 'string', width : 150 }, { header : QUILocale.get(lg, 'controls.manager.tbl.header.reusable'), - dataIndex: 'reusable', + dataIndex: 'reusableStatus', dataType : 'node', width : 150 }, { @@ -200,16 +200,19 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ this.$Grid.addEvents({ onDblClick: function () { - // @todo - //self.$managePackages( - // self.$Grid.getSelectedData()[0].id - //); + self.$showDetails(Object.clone(self.$Grid.getSelectedData()[0])); }, onClick : function (event) { var selected = self.$Grid.getSelectedData(); self.getButtons('delete').enable(); + if (selected.length === 1) { + self.getButtons('edit').enable(); + } else { + self.getButtons('edit').disable(); + } + if (!event.cell.hasClass('clickable')) { return; } @@ -246,6 +249,7 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ var self = this; self.getButtons('delete').disable(); + self.getButtons('edit').disable(); var GridParams = { sortOn : Grid.getAttribute('sortOn'), @@ -306,7 +310,9 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ Row.status = StatusElm; if (!Row.validUntilDate) { - Row.validUntilDate = textUnlimited; + Row.validUntilDateText = textUnlimited; + } else { + Row.validUntilDateText = Row.validUntilDate; } if (!Row.title) { @@ -317,39 +323,27 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ 'class': 'fa' }); - if (!Row.isReusable) { + if (!Row.reusable) { ReusableElm.addClass('fa-close'); } else { ReusableElm.addClass('fa-check'); } - Row.reusable = ReusableElm; + Row.reusableStatus = ReusableElm; } this.$Grid.setData(GridData); }, /** - * Create new InviteCode + * Create new CouponCode or edit an existing one * - * @param {Boolean} [quickCreate] + * @param {Object} [CouponData] - If omitted create new CouponCode */ - $create: function (quickCreate) { + $showDetails: function (CouponData) { var self = this; - quickCreate = quickCreate || false; - - if (quickCreate) { - CouponCodes.create({}).then(function (inviteCodeId) { - if (!inviteCodeId) { - return; - } - - self.refresh(); - }); - - return; - } + CouponData = CouponData || false; var FuncSubmit = function () { var Content = Popup.getContent(); @@ -357,8 +351,22 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ Popup.Loader.show(); - CouponCodes.create(QUIFormUtils.getFormData(Form)).then(function (inviteCodeId) { - if (!inviteCodeId) { + if (CouponData) { + CouponCodes.edit(CouponData.id, QUIFormUtils.getFormData(Form)).then(function (couponCodeId) { + if (!couponCodeId) { + Popup.Loader.hide(); + return; + } + + self.refresh(); + Popup.close(); + }); + + return; + } + + CouponCodes.create(QUIFormUtils.getFormData(Form)).then(function (couponCodeId) { + if (!couponCodeId) { Popup.Loader.hide(); return; } @@ -373,26 +381,95 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ var Popup = new QUIPopup({ icon : 'fa fa-plus', - title : QUILocale.get( - lg, 'controls.manager.create.popup.title' - ), - maxHeight : 800, + title : CouponData ? + QUILocale.get(lg, 'controls.manager.details.popup.title_edit', {code: CouponData.code}) : + QUILocale.get(lg, 'controls.manager.details.popup.title_new'), + maxHeight : 335, maxWidth : 450, events : { onOpen: function () { - var Content = Popup.getContent(); - var Form = Content.getElement('form'); + var Content = Popup.getContent(); + var Form = Content.getElement('form'); + var SubmitBtn = Popup.getButton('submit'); Form.addEvent('submit', function (event) { event.stop(); FuncSubmit(); }); - Content.getElement('input[name="title"]').focus(); + var Settings = Content.getElement('.quiqqer-coupons-manager-create-settings'); + var Amount = Content.getElement('input[name="amount"]'); + var Code = Content.getElement('input[name="code"]'); + + Code.addEvent('keyup', function () { + if (Code.value !== '') { + Amount.disabled = true; + Amount.value = 1; + } else { + Amount.disabled = false; + } + }); + + new QUIButton({ + textimage: 'fa fa-cogs', + text : QUILocale.get(lg, 'controls.Manager.create.settings_btn.show'), + events : { + onClick: function (Btn) { + if (Settings.getStyle('display') === 'none') { + Settings.setStyle('display', 'block'); + + Btn.setAttribute( + 'text', + QUILocale.get(lg, 'controls.Manager.create.settings_btn.hide') + ); + + Content.getElement('input[name="title"]').focus(); + + Popup.setAttribute('maxHeight', 850); + Popup.resize(); + } else { + Settings.setStyle('display', 'none'); + + Btn.setAttribute( + 'text', + QUILocale.get(lg, 'controls.Manager.create.settings_btn.show') + ); + + Popup.setAttribute('maxHeight', 335); + Popup.resize(); + } + } + } + }).inject(Content.getElement( + '.quiqqer-coupons-manager-create-settings-btn' + )); + + if (CouponData) { + + console.log(CouponData); + + CouponData.discountIds = CouponData.discountIds.join(','); + + QUIFormUtils.setDataToForm(CouponData, Form); + } Popup.Loader.show(); QUI.parse(Content).then(function () { + var DiscountSelect = QUI.Controls.getById( + Content.getElement('input[name="discountIds"]').get('data-quiid') + ); + + DiscountSelect.addEvents({ + onChange: function () { + if (DiscountSelect.getValue() === '') { + SubmitBtn.disable(); + } else { + SubmitBtn.enable(); + } + } + }); + Popup.Loader.hide(); }); } @@ -405,17 +482,26 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ labelGroups : QUILocale.get(lg, lgPrefix + 'labelGroups'), labelDate : QUILocale.get(lg, lgPrefix + 'labelDate'), labelAmount : QUILocale.get(lg, lgPrefix + 'labelAmount'), - labelReusable: QUILocale.get(lg, lgPrefix + 'labelReusable') + labelReusable: QUILocale.get(lg, lgPrefix + 'labelReusable'), + labelDiscount: QUILocale.get(lg, lgPrefix + 'labelDiscount') }) }); Popup.open(); Popup.addButton(new QUIButton({ - text : QUILocale.get(lg, 'controls.manager.create.popup.btn.confirm_text'), - alt : QUILocale.get(lg, 'controls.manager.create.popup.btn.confirm'), - title : QUILocale.get(lg, 'controls.manager.create.popup.btn.confirm'), - events: { + name : 'submit', + disabled: true, + text : CouponData ? + QUILocale.get(lg, 'controls.manager.details.popup.btn.confirm_text_edit') : + QUILocale.get(lg, 'controls.manager.details.popup.btn.confirm_text_new'), + alt : CouponData ? + QUILocale.get(lg, 'controls.manager.details.popup.btn.confirm_edit') : + QUILocale.get(lg, 'controls.manager.details.popup.btn.confirm_new'), + title : CouponData ? + QUILocale.get(lg, 'controls.manager.details.popup.btn.confirm_edit') : + QUILocale.get(lg, 'controls.manager.details.popup.btn.confirm_new'), + events : { onClick: FuncSubmit } })); @@ -498,11 +584,14 @@ define('package/quiqqer/coupons/bin/controls/Manager', [ cancel_button: false, ok_button : { - text : false, + text : QUILocale.get(lg, 'controls.Manager.usages.btn_ok'), textimage: 'icon-ok fa fa-check' }, events : { - onOpen: function (Popup) { + onSubmit: function (Popup) { + Popup.close(); + }, + onOpen : function (Popup) { var lgPrefix = 'controls.Manager.usages.template.'; Popup.setContent(Mustache.render(templateUsages, { diff --git a/database.xml b/database.xml index fb3120b5f946c2b3505a2fe21826674a9b88e452..c2ca7ec5fb5e1bc1da297dda6f111303e768ed8c 100644 --- a/database.xml +++ b/database.xml @@ -4,10 +4,11 @@ <global> <table name="quiqqer_coupons"> <field type="BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY">id</field> + <field type="MEDIUMTEXT NULL">discountIds</field> <field type="VARCHAR(255) NOT NULL">code</field> <field type="VARCHAR(255) NULL">title</field> - <field type="VARCHAR(255) NULL">userIds</field> - <field type="VARCHAR(255) NULL">groupIds</field> + <field type="MEDIUMTEXT NULL">userIds</field> + <field type="MEDIUMTEXT NULL">groupIds</field> <field type="DATETIME NOT NULL">createDate</field> <field type="DATETIME NULL">validUntilDate</field> <field type="MEDIUMTEXT NULL">usages</field> diff --git a/locale.xml b/locale.xml index 4c8d0081e726910233c09ad3a73e6fbd142870e7..92cf892f3a0aba8e167b73b28a2b3b6fb89b10be 100644 --- a/locale.xml +++ b/locale.xml @@ -83,6 +83,14 @@ <de><![CDATA[Die Coupon-Codes wurden erfolgreich erstellt.]]></de> <en><![CDATA[The Coupon codes have been successfully created.]]></en> </locale> + <locale name="message.ajax.edit.error" html="true"> + <de><![CDATA[Der Coupon-Code #[id] konnte nicht bearbeitet werden:<br><br>[error]]]></de> + <en><![CDATA[The Coupon code #[id] could not be edited:<br><br>[error]]]></en> + </locale> + <locale name="message.ajax.edit.success"> + <de><![CDATA[Der Coupon-Code #[id] wurde erfolgreich bearbeitet.]]></de> + <en><![CDATA[The Coupon code #[id] has been successfully edited.]]></en> + </locale> <locale name="message.ajax.delete.error" html="true"> <de><![CDATA[Beim Löschen der Coupon-Codes ist ein Fehler aufgetreten:<br><br>[error]]]></de> <en><![CDATA[An error occurred while deleting the Coupon codes:<br><br>[error].]]></en> @@ -113,6 +121,14 @@ <de><![CDATA[Dieser Coupon-Code ist nicht für diesen Benutzer gültig.]]></de> <en><![CDATA[This coupon code is not valid for this user.]]></en> </locale> + <locale name="exception.CouponCode.discount_invalid"> + <de><![CDATA[Dieser Coupon-Code kann leider nicht verwendet werden: [reason]]]></de> + <en><![CDATA[Unforuntately, this Coupon code cannot be used: [reason]]]></en> + </locale> + <locale name="exception.CouponCode.discounts_invalid"> + <de><![CDATA[Dieser Coupon-Code kann leider nicht verwendet werden.]]></de> + <en><![CDATA[Unforuntately, this Coupon code cannot be used.]]></en> + </locale> <!-- Class: Handler --> <locale name="exception.Handler.code_already_exists"> @@ -120,12 +136,16 @@ <en><![CDATA[The Coupon code "[code]" already exists. Please use a differenct code or leave the code field empty to generate a random one.]]></en> </locale> <locale name="exception.Handler.code_not_found"> - <de><![CDATA[]]></de> - <en><![CDATA[]]></en> + <de><![CDATA[Der Coupon-Code "[code]" wurde nicht gefunden.]]></de> + <en><![CDATA[The Coupon code "[code]" could not be found.]]></en> </locale> - <locale name="exception.invitecode.no_registration_site"> - <de><![CDATA[Es wurde noch keine Registrierungs-Seite festgelegt, auf die in der Coupon-Code E-Mail verwiesen wird.]]></de> - <en><![CDATA[No registration page has yet been specified for the Coupon code email.]]></en> + <locale name="exception.Handler.discount_error"> + <de><![CDATA[Der Rabatt #[discountId] kann nicht verwendet werden: [error]]]></de> + <en><![CDATA[The discount #[discountId] cannot be used: [error]]]></en> + </locale> + <locale name="exception.Handler.no_discounts_linked"> + <de><![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> </groups> @@ -163,22 +183,42 @@ <de><![CDATA[Wiederverwendbar (Coupon-Code kann mehrfach verwendet werden)]]></de> <en><![CDATA[Reusable (Coupon code can be used multiple times)]]></en> </locale> - <locale name="controls.manager.create.popup.title"> + <locale name="controls.manager.create.template.labelDiscount"> + <de><![CDATA[Verknüpfter Rabatt]]></de> + <en><![CDATA[Linked discount]]></en> + </locale> + <locale name="controls.manager.details.popup.title_new"> <de><![CDATA[Neuen Coupon-Code erstellen]]></de> <en><![CDATA[Create new Coupon code]]></en> </locale> - <locale name="controls.manager.create.popup.btn.confirm_text"> + <locale name="controls.manager.details.popup.title_edit"> + <de><![CDATA[Coupon-Code "[code]" bearbeiten]]></de> + <en><![CDATA[Edit Coupon code "[code]"]]></en> + </locale> + <locale name="controls.manager.details.popup.btn.confirm_text_new"> <de><![CDATA[Coupon-Code erstellen]]></de> <en><![CDATA[Create Coupon code]]></en> </locale> - <locale name="controls.manager.create.popup.btn.confirm"> + <locale name="controls.manager.details.popup.btn.confirm_text_edit"> + <de><![CDATA[Änderungen speichern]]></de> + <en><![CDATA[Save changes]]></en> + </locale> + <locale name="controls.manager.details.popup.btn.confirm_new"> <de><![CDATA[Hier klicken, um neuen Coupon-Code erstellen]]></de> <en><![CDATA[Click here to create a new Coupon code]]></en> </locale> + <locale name="controls.manager.details.popup.btn.confirm_edit"> + <de><![CDATA[Hier klicken, um die Änderungen am Coupon-Code zu speichern]]></de> + <en><![CDATA[Click here to save the changes made to the Coupon code]]></en> + </locale> <locale name="controls.manager.tbl.btn.create"> <de><![CDATA[Erstellen]]></de> <en><![CDATA[Create]]></en> </locale> + <locale name="controls.manager.tbl.btn.edit"> + <de><![CDATA[Markierten bearbeiten]]></de> + <en><![CDATA[Edit marked]]></en> + </locale> <locale name="controls.manager.tbl.btn.quickcreate"> <de><![CDATA[Schnelles Erstellen]]></de> <en><![CDATA[Quick Create]]></en> @@ -252,7 +292,7 @@ <en><![CDATA[Delete Coupon codes]]></en> </locale> <locale name="controls.manager.sendmail.popup.info"> - <de><![CDATA[Sind Sie sicher, dass die markierten Coupon-Codes per E-Mail versandt werden sollen? InviteCodes, die keine zugewiesene E-Mail-Adresse haben, werden nicht versandt.]]></de> + <de><![CDATA[Sind Sie sicher, dass die markierten Coupon-Codes per E-Mail versandt werden sollen? CouponCodes, die keine zugewiesene E-Mail-Adresse haben, werden nicht versandt.]]></de> <en><![CDATA[Are you sure that the marked Invite codes should be sent by e-mail? Coupon codes that do not have an assigned e-mail address will not be sent.]]></en> </locale> <locale name="controls.manager.sendmail.popup.title"> @@ -275,5 +315,17 @@ <de><![CDATA[Datum]]></de> <en><![CDATA[Date]]></en> </locale> + <locale name="controls.Manager.usages.btn_ok"> + <de><![CDATA[OK]]></de> + <en><![CDATA[OK]]></en> + </locale> + <locale name="controls.Manager.create.settings_btn.show"> + <de><![CDATA[Erweiterte Einstellungen anzeigen]]></de> + <en><![CDATA[Show advanced settings]]></en> + </locale> + <locale name="controls.Manager.create.settings_btn.hide"> + <de><![CDATA[Erweiterte Einstellungen ausblenden]]></de> + <en><![CDATA[Hide advanced settings]]></en> + </locale> </groups> </locales> diff --git a/permissions.xml b/permissions.xml index 9326e4cd0b81628ca643447d96ef34c19158507e..673e41baf4debcde1b63abebe5bfb45be00e1925 100644 --- a/permissions.xml +++ b/permissions.xml @@ -7,6 +7,9 @@ <permission name="quiqqer.coupons.create" type="bool"> <defaultvalue>0</defaultvalue> </permission> + <permission name="quiqqer.coupons.edit" type="bool"> + <defaultvalue>0</defaultvalue> + </permission> <permission name="quiqqer.coupons.delete" type="bool"> <defaultvalue>0</defaultvalue> </permission> diff --git a/src/QUI/ERP/Coupons/CodeGenerators/SimpleString.php b/src/QUI/ERP/Coupons/CodeGenerators/SimpleString.php index b7147fce886af4eec1d65ba7e21646b20c1032a9..2d167995ba70895129b47527ae1841a2117caca7 100644 --- a/src/QUI/ERP/Coupons/CodeGenerators/SimpleString.php +++ b/src/QUI/ERP/Coupons/CodeGenerators/SimpleString.php @@ -2,8 +2,8 @@ namespace QUI\ERP\Coupons\CodeGenerators; -use QUI\InviteCode\CodeGeneratorInterface; -use QUI\InviteCode\Handler; +use QUI\ERP\Coupons\CodeGeneratorInterface; +use QUI\ERP\Coupons\Handler; class SimpleString implements CodeGeneratorInterface { @@ -14,6 +14,7 @@ class SimpleString implements CodeGeneratorInterface * * @param string $prefix (optional) * @return string + * @throws \Exception */ public static function generate($prefix = '') { diff --git a/src/QUI/ERP/Coupons/CodeGenerators/Uuid.php b/src/QUI/ERP/Coupons/CodeGenerators/Uuid.php index e1b43b5cb8ce48d0c3559d4cf71faff9d2385216..26e76f802ce30c8faafa9dd3b738ece02dbff178 100644 --- a/src/QUI/ERP/Coupons/CodeGenerators/Uuid.php +++ b/src/QUI/ERP/Coupons/CodeGenerators/Uuid.php @@ -2,7 +2,7 @@ namespace QUI\ERP\Coupons\CodeGenerators; -use QUI\InviteCode\CodeGeneratorInterface; +use QUI\ERP\Coupons\CodeGeneratorInterface; use Ramsey\Uuid\Uuid as UuidCreator; class Uuid implements CodeGeneratorInterface diff --git a/src/QUI/ERP/Coupons/CouponCode.php b/src/QUI/ERP/Coupons/CouponCode.php index 7eec7b25a31924d88657a2354dce3e13782bb95f..78d489de7c641361b62b36f05cdd419873be2601 100644 --- a/src/QUI/ERP/Coupons/CouponCode.php +++ b/src/QUI/ERP/Coupons/CouponCode.php @@ -4,6 +4,7 @@ use QUI; use QUI\Permissions\Permission; +use QUI\ERP\Discount\Handler as DiscountHandler; /** * Class CouponCode @@ -27,17 +28,24 @@ class CouponCode /** * IDs of users that this CouponCode is restricted to * - * @var array + * @var int[] */ protected $userIds = []; /** * IDs of groups that this CouponCode is restricted to * - * @var array + * @var int[] */ protected $groupIds = []; + /** + * IDs of all linked discounts + * + * @var int[] + */ + protected $discountIds = []; + /** * List of usages of this CouponCode * @@ -127,6 +135,10 @@ public function __construct($id) $this->reusable = true; } + if (!empty($data['discountIds'])) { + $this->discountIds = json_decode($data['discountIds'], true); + } + $this->CreateDate = new \DateTime($data['createDate']); if (!empty($data['validUntilDate'])) { @@ -163,7 +175,7 @@ public function getCreateDate() /** * Get usage data * - * @return [] + * @return array */ public function getUsages() { @@ -186,6 +198,14 @@ public function getTitle() return $this->title; } + /** + * @return int[] + */ + public function getDiscountIds() + { + return $this->discountIds; + } + /** * Redeems this CouponCode * @@ -240,6 +260,42 @@ public function redeem($User = null) */ protected function checkRedemption($User) { + $DiscountHandler = DiscountHandler::getInstance(); + $discountsValid = false; + $discountError = false; + + foreach ($this->discountIds as $discountId) { + try { + /** @var QUI\ERP\Discount\Discount $Discount */ + $Discount = $DiscountHandler->getChild($discountId); + } catch (\Exception $Exception) { + $discountError = $Exception->getMessage(); + continue; + } + + if ($Discount->canUsedBy($User)) { + $discountsValid = true; + break; + } + } + + if (!$discountsValid) { + if (count($this->discountIds) === 1) { + throw new CouponCodeException([ + 'quiqqer/coupons', + 'exception.CouponCode.discount_invalid', + [ + 'reason' => $discountError + ] + ]); + } else { + throw new CouponCodeException([ + 'quiqqer/coupons', + 'exception.CouponCode.discounts_invalid' + ]); + } + } + if (!$this->isValid()) { throw new CouponCodeException([ 'quiqqer/coupons', @@ -339,6 +395,7 @@ public function hasUserRedeemed($User) * Permanently delete this CouponCode * * @return void + * @throws \QUI\Permissions\Exception */ public function delete() { @@ -369,13 +426,14 @@ public function toArray() 'validUntilDate' => false, 'title' => $this->getTitle() ?: false, 'isValid' => $this->isValid(), - 'isReusable' => $this->reusable + 'reusable' => $this->reusable, + 'discountIds' => $this->discountIds ]; $ValidUntilDate = $this->getValidUntilDate(); if ($ValidUntilDate) { - $data['validUntilDate'] = $ValidUntilDate->format('Y-m-d H:i:s'); + $data['validUntilDate'] = $ValidUntilDate->format('Y-m-d'); } return $data; @@ -422,6 +480,9 @@ protected function checkValidity() $this->valid = false; return; } + } elseif (!empty($this->usages)) { + $this->valid = false; + return; } } } diff --git a/src/QUI/ERP/Coupons/Handler.php b/src/QUI/ERP/Coupons/Handler.php index 445dc348e40d47ad7eefc855110c987dc5848cf1..b920021fe3d21abaf3e93c736c8938a39ee4d997 100644 --- a/src/QUI/ERP/Coupons/Handler.php +++ b/src/QUI/ERP/Coupons/Handler.php @@ -5,6 +5,7 @@ use QUI; use QUI\Utils\Grid; use QUI\Utils\Security\Orthos; +use QUI\ERP\Discount\Handler as DiscountHandler; /** * Class Handler @@ -18,6 +19,7 @@ class Handler */ const PERMISSION_VIEW = 'quiqqer.couponcode.view'; const PERMISSION_CREATE = 'quiqqer.couponcode.create'; + const PERMISSION_EDIT = 'quiqqer.couponcode.edit'; const PERMISSION_DELETE = 'quiqqer.couponcode.delete'; /** @@ -68,7 +70,7 @@ public static function getCouponCodeByCode($code) if (empty($result)) { throw new CouponCodeException([ - 'quiqqer/invitecode', + 'quiqqer/coupons', 'exception.Handler.code_not_found', [ 'code' => $code @@ -82,49 +84,76 @@ public static function getCouponCodeByCode($code) /** * Create new CouponCode * - * @param array $data + * @param array $discountIds - IDs of the discounts that are linked to this CouponCode + * @param array $settings (optional) - If omitted a random default CouponCode is generated * @return CouponCode * * @throws \Exception */ - public static function createCouponCode($data) + public static function createCouponCode($discountIds, $settings = []) { + $DiscountHandler = DiscountHandler::getInstance(); + + if (empty($discountIds)) { + throw new CouponCodeException([ + 'quiqqer/coupons', + 'exception.Handler.no_discounts_linked' + ]); + } + + // check if all given discounts exist + foreach ($discountIds as $discountId) { + try { + $DiscountHandler->getChild($discountId); + } catch (\Exception $Exception) { + throw new CouponCodeException([ + 'quiqqer/coupons', + 'exception.Handler.discount_error', + [ + 'discountId' => $discountId, + 'error' => $Exception->getMessage() + ] + ]); + } + } + $Now = new \DateTime(); - if (!empty($data['code'])) { - if (self::existsCode($data['code'])) { + if (!empty($settings['code'])) { + if (self::existsCode($settings['code'])) { throw new CouponCodeException([ 'quiqqer/coupons', 'exception.Handler.code_already_exists', [ - 'code' => $data['code'] + 'code' => $settings['code'] ] ]); } - $code = $data['code']; + $code = $settings['code']; } else { $code = CodeGenerator::generate(); } $couponCode = [ - 'title' => empty($data['title']) ? '' : $data['title'], - 'createDate' => $Now->format('Y-m-d H:i:s'), - 'code' => $code, - 'isReusable' => !empty($data['reusable']) + 'title' => empty($settings['title']) ? null : $settings['title'], + 'createDate' => $Now->format('Y-m-d H:i:s'), + 'code' => $code, + 'isReusable' => !empty($settings['reusable']), + 'discountIds' => json_encode($discountIds) ]; - if (!empty($data['validUntil'])) { - $ValidUntil = new \DateTime($data['validUntil']); + if (!empty($settings['validUntilDate'])) { + $ValidUntil = new \DateTime($settings['validUntilDate']); $couponCode['validUntilDate'] = $ValidUntil->format('Y-m-d H:i:s'); } - if (!empty($data['userIds'])) { - $couponCode['userIds'] = json_encode($data['userIds']); + if (!empty($settings['userIds'])) { + $couponCode['userIds'] = json_encode($settings['userIds']); } - if (!empty($data['groupIds'])) { - $couponCode['groupIds'] = json_encode($data['groupIds']); + if (!empty($settings['groupIds'])) { + $couponCode['groupIds'] = json_encode($settings['groupIds']); } QUI::getDataBase()->insert( @@ -135,6 +164,106 @@ public static function createCouponCode($data) return self::getCouponCode(QUI::getPDO()->lastInsertId()); } + /** + * Edit a CouponCode + * + * @param int $id - CouponCode ID + * @param array $discountIds - IDs of the discounts that are linked to this CouponCode + * @param array $settings (optional) - If omitted a random default CouponCode is generated + * @return CouponCode + * + * @throws \Exception + */ + public static function editCouponCode($id, $discountIds, $settings = []) + { + QUI\Permissions\Permission::checkPermission(self::PERMISSION_EDIT); + + // check if CouponCode exists + $CouponCode = self::getCouponCode($id); + + // Check settings + $DiscountHandler = DiscountHandler::getInstance(); + + if (empty($discountIds)) { + throw new CouponCodeException([ + 'quiqqer/coupons', + 'exception.Handler.no_discounts_linked' + ]); + } + + // check if all given discounts exist + foreach ($discountIds as $discountId) { + try { + $DiscountHandler->getChild($discountId); + } catch (\Exception $Exception) { + throw new CouponCodeException([ + 'quiqqer/coupons', + 'exception.Handler.discount_error', + [ + 'discountId' => $discountId, + 'error' => $Exception->getMessage() + ] + ]); + } + } + + $Now = new \DateTime(); + + if (!empty($settings['code'])) { + if ($CouponCode->getCode() !== $settings['code'] + && self::existsCode($settings['code'])) { + throw new CouponCodeException([ + 'quiqqer/coupons', + 'exception.Handler.code_already_exists', + [ + 'code' => $settings['code'] + ] + ]); + } + + $code = $settings['code']; + } else { + $code = CodeGenerator::generate(); + } + + $couponCode = [ + 'title' => empty($settings['title']) ? null : $settings['title'], + 'createDate' => $Now->format('Y-m-d H:i:s'), + 'code' => $code, + 'isReusable' => !empty($settings['reusable']), + 'discountIds' => json_encode($discountIds) + ]; + + if (!empty($settings['validUntilDate'])) { + $ValidUntil = new \DateTime($settings['validUntilDate']); + $couponCode['validUntilDate'] = $ValidUntil->format('Y-m-d H:i:s'); + } else { + $couponCode['validUntilDate'] = null; + } + + if (!empty($settings['userIds'])) { + $couponCode['userIds'] = json_encode($settings['userIds']); + } else { + $couponCode['userIds'] = null; + } + + if (!empty($settings['groupIds'])) { + $couponCode['groupIds'] = json_encode($settings['groupIds']); + } else { + $couponCode['groupIds'] = null; + } + + QUI::getDataBase()->update( + self::getTable(), + $couponCode, + [ + 'id' => $id + ] + ); + + return self::getCouponCode($id); + } + /** * Search CouponCodes * @@ -274,7 +403,7 @@ public static function existsCode($code) */ public static function getRegistrationSite() { - $Conf = QUI::getPackage('quiqqer/invitecode')->getConfig(); + $Conf = QUI::getPackage('quiqqer/coupons')->getConfig(); $regSite = $Conf->get('settings', 'registrationSite'); if (empty($regSite)) {