From 564ecd5227621a2ab0d985bf5802daea9e728ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20M=C3=BCller?= <p.mueller@pcsg.de> Date: Thu, 22 Jun 2017 18:30:17 +0200 Subject: [PATCH] refactor: temp commit --- ajax/memberships/users/get.php | 54 +++++++ ajax/memberships/users/getHistory.php | 42 +++++ ajax/memberships/users/update.php | 89 ++++++++++ bin/classes/MembershipUsers.js | 56 ++++++- bin/controls/users/MembershipUserEdit.css | 9 ++ bin/controls/users/MembershipUserEdit.html | 39 +++++ bin/controls/users/MembershipUserEdit.js | 153 ++++++++++++++++++ bin/controls/users/MembershipUserHistory.css | 44 +++++ bin/controls/users/MembershipUserHistory.html | 9 ++ bin/controls/users/MembershipUserHistory.js | 149 +++++++++++++++++ .../users/MembershipUserHistoryPopup.js | 61 +++++++ bin/controls/users/MembershipUsers.js | 95 +++++++++-- bin/controls/users/MembershipUsersArchive.js | 79 ++------- locale.xml | 98 +++++++++++ src/QUI/Memberships/Cron.php | 47 +++--- src/QUI/Memberships/Users/MembershipUser.php | 82 ++++++++-- templates/mail_autoextend.html | 4 +- templates/mail_confirmcancel.html | 5 +- templates/mail_expired.html | 4 +- 19 files changed, 1002 insertions(+), 117 deletions(-) create mode 100644 ajax/memberships/users/get.php create mode 100644 ajax/memberships/users/getHistory.php create mode 100644 ajax/memberships/users/update.php create mode 100644 bin/controls/users/MembershipUserEdit.css create mode 100644 bin/controls/users/MembershipUserEdit.html create mode 100644 bin/controls/users/MembershipUserEdit.js create mode 100644 bin/controls/users/MembershipUserHistory.css create mode 100644 bin/controls/users/MembershipUserHistory.html create mode 100644 bin/controls/users/MembershipUserHistory.js create mode 100644 bin/controls/users/MembershipUserHistoryPopup.js diff --git a/ajax/memberships/users/get.php b/ajax/memberships/users/get.php new file mode 100644 index 0000000..4bd21bb --- /dev/null +++ b/ajax/memberships/users/get.php @@ -0,0 +1,54 @@ +<?php + +use QUI\Memberships\Users\Handler as MembershipUsersHandler; +use QUI\Memberships\Users\MembershipUser; + +/** + * Get general data of a MembershipUser + * + * @param int $membershipUserId + * @return array|false - history data or false on error + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_memberships_ajax_memberships_users_get', + function ($membershipUserId) { + try { + $MembershipUsers = MembershipUsersHandler::getInstance(); + /** @var MembershipUser $MembershipUser */ + $MembershipUser = $MembershipUsers->getChild((int)$membershipUserId); + $QuiqqerUser = $MembershipUser->getUser(); + $Membership = $MembershipUser->getMembership(); + + return array( + 'id' => $MembershipUser->getId(), + 'userId' => $QuiqqerUser->getId(), + 'membershipId' => $Membership->getId(), + 'membershipTitle' => $Membership->getTitle(), + 'username' => $QuiqqerUser->getUsername(), + 'fullName' => $QuiqqerUser->getName(), + 'addedDate' => $MembershipUser->getAttribute('addedDate'), + 'beginDate' => $MembershipUser->getAttribute('beginDate'), + 'endDate' => $MembershipUser->getAttribute('endDate'), + 'archived' => $MembershipUser->isArchived(), + 'archiveReason' => $MembershipUser->getAttribute('archiveReason') + ); + } catch (\Exception $Exception) { + QUI\System\Log::addError('AJAX :: package_quiqqer_memberships_ajax_memberships_users_getHistory'); + QUI\System\Log::writeException($Exception); + + QUI::getMessagesHandler()->addError( + QUI::getLocale()->get( + 'quiqqer/memberships', + 'message.ajax.general.error', + array( + 'error' => $Exception->getMessage() + ) + ) + ); + + return false; + } + }, + array('membershipUserId'), + 'Permission::checkAdminUser' +); diff --git a/ajax/memberships/users/getHistory.php b/ajax/memberships/users/getHistory.php new file mode 100644 index 0000000..3bae571 --- /dev/null +++ b/ajax/memberships/users/getHistory.php @@ -0,0 +1,42 @@ +<?php + +use QUI\Memberships\Users\Handler as MembershipUsersHandler; +use QUI\Memberships\Users\MembershipUser; + +/** + * Get history of a MembershipUser + * + * @param int $membershipUserId + * @return array|false - history data or false on error + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_memberships_ajax_memberships_users_getHistory', + function ($membershipUserId) { + try { + $MembershipUsers = MembershipUsersHandler::getInstance(); + /** @var MembershipUser $MembershipUser */ + $MembershipUser = $MembershipUsers->getChild((int)$membershipUserId); + $history = $MembershipUser->getHistory(); + + // reverse history entries so the latest entries come first + return array_reverse($history); + } catch (\Exception $Exception) { + QUI\System\Log::addError('AJAX :: package_quiqqer_memberships_ajax_memberships_users_getHistory'); + QUI\System\Log::writeException($Exception); + + QUI::getMessagesHandler()->addError( + QUI::getLocale()->get( + 'quiqqer/memberships', + 'message.ajax.general.error', + array( + 'error' => $Exception->getMessage() + ) + ) + ); + + return false; + } + }, + array('membershipUserId'), + 'Permission::checkAdminUser' +); diff --git a/ajax/memberships/users/update.php b/ajax/memberships/users/update.php new file mode 100644 index 0000000..fba1389 --- /dev/null +++ b/ajax/memberships/users/update.php @@ -0,0 +1,89 @@ +<?php + +use QUI\Memberships\Users\Handler as MembershipUsersHandler; +use QUI\Memberships\Utils; + +/** + * Update a MembershipUser + * + * @param int $membershipUserId + * @param array $attributes - Update attributes + * @return bool - success + */ +QUI::$Ajax->registerFunction( + 'package_quiqqer_memberships_ajax_memberships_users_update', + function ($membershipUserId, $attributes) { + try { + $MembershipUsers = MembershipUsersHandler::getInstance(); + /** @var \QUI\Memberships\Users\MembershipUser $MembershipUser */ + $MembershipUser = $MembershipUsers->getChild((int)$membershipUserId); + $attributes = json_decode($attributes, true); + $updated = array(); + + foreach ($attributes as $k => $v) { + switch ($k) { + case 'beginDate': + case 'endDate': + $v = Utils::getFormattedTimestamp(strtotime($v)); + $updated[$k] = $v; + break; + + default: + // do not update un-updatable attributes + continue 2; + } + + $MembershipUser->setAttribute($k, $v); + } + + $MembershipUser->addHistoryEntry( + MembershipUsersHandler::HISTORY_TYPE_UPDATED, + json_encode($updated) + ); + + $MembershipUser->update(); + } catch (QUI\Memberships\Exception $Exception) { + QUI::getMessagesHandler()->addError( + QUI::getLocale()->get( + 'quiqqer/memberships', + 'message.ajax.memberships.users.update.error', + array( + 'error' => $Exception->getMessage() + ) + ) + ); + + return false; + } catch (\Exception $Exception) { + QUI\System\Log::addError('AJAX :: package_quiqqer_memberships_ajax_memberships_users_update'); + QUI\System\Log::writeException($Exception); + + QUI::getMessagesHandler()->addError( + QUI::getLocale()->get( + 'quiqqer/memberships', + 'message.ajax.general.error', + array( + 'error' => $Exception->getMessage() + ) + ) + ); + + return false; + } + + QUI::getMessagesHandler()->addSuccess( + QUI::getLocale()->get( + 'quiqqer/memberships', + 'message.ajax.memberships.users.update.success', + array( + 'membershipUserId' => $MembershipUser->getId(), + 'membershipUserName' => $MembershipUser->getUser()->getName() + ) + ) + ); + + return true; + }, + array('membershipUserId', 'attributes'), + 'Permission::checkAdminUser' +); diff --git a/bin/classes/MembershipUsers.js b/bin/classes/MembershipUsers.js index 2a4e2b5..d4cf6d6 100644 --- a/bin/classes/MembershipUsers.js +++ b/bin/classes/MembershipUsers.js @@ -46,9 +46,9 @@ define('package/quiqqer/memberships/bin/classes/MembershipUsers', [ deleteMembershipUsers: function (userIds) { return new Promise(function (resolve, reject) { QUIAjax.post('package_quiqqer_memberships_ajax_memberships_users_delete', resolve, { - 'package' : pkg, - userIds : JSON.encode(userIds), - onError : reject + 'package': pkg, + userIds : JSON.encode(userIds), + onError : reject }) }); }, @@ -71,6 +71,56 @@ define('package/quiqqer/memberships/bin/classes/MembershipUsers', [ }); }, + /** + * Update MembershipUser + * + * @param {Integer} membershipUserId + * @param {Object} Attributes + * @return {Promise} + */ + update: function (membershipUserId, Attributes) { + return new Promise(function (resolve, reject) { + QUIAjax.post('package_quiqqer_memberships_ajax_memberships_users_update', resolve, { + 'package' : pkg, + membershipUserId: membershipUserId, + attributes : JSON.encode(Attributes), + onError : reject + }) + }); + }, + + /** + * Get MembershipUser data (some general attribues) + * + * @param {Integer} membershipUserId + * @return {Promise} + */ + get: function (membershipUserId) { + return new Promise(function (resolve, reject) { + QUIAjax.get('package_quiqqer_memberships_ajax_memberships_users_get', resolve, { + 'package' : pkg, + membershipUserId: membershipUserId, + onError : reject + }) + }); + }, + + /** + * Get MembershipUser history + * + * @param {Integer} membershipUserId + * @return {Promise} + */ + getHistory: function (membershipUserId) { + return new Promise(function (resolve, reject) { + QUIAjax.get('package_quiqqer_memberships_ajax_memberships_users_getHistory', resolve, { + 'package' : pkg, + membershipUserId: membershipUserId, + onError : reject + }) + }); + }, + /** * Get/Search memberships (archived) * diff --git a/bin/controls/users/MembershipUserEdit.css b/bin/controls/users/MembershipUserEdit.css new file mode 100644 index 0000000..faa3262 --- /dev/null +++ b/bin/controls/users/MembershipUserEdit.css @@ -0,0 +1,9 @@ +.quiqqer-memberships-membershipuseredit { + float: left; + width: 100%; +} + +.quiqqer-memberships-membershipuseredit-submit { + float: left; + width: 100%; +} \ No newline at end of file diff --git a/bin/controls/users/MembershipUserEdit.html b/bin/controls/users/MembershipUserEdit.html new file mode 100644 index 0000000..78c89d0 --- /dev/null +++ b/bin/controls/users/MembershipUserEdit.html @@ -0,0 +1,39 @@ +<form name="quiqqer-memberships-membershipuseredit"> + <table class="data-table data-table-flexbox quiqqer-memberships-membershipuseredit-table"> + <thead> + <tr> + <th> + {{header}} + </th> + </tr> + </thead> + + <tbody> + <tr> + <td> + <label class="field-container"> + <span class="field-container-item"> + {{labelBeginDate}} + </span> + <input type="datetime" + class="field-container-field quiqqer-memberships-membershipuseredit-attribute" + name="beginDate" placeholder="YYYY-MM-DD"> + </label> + </td> + </tr> + <tr> + <td> + <label class="field-container"> + <span class="field-container-item"> + {{labelEndDate}} + </span> + <input type="datetime" + class="field-container-field quiqqer-memberships-membershipuseredit-attribute" + name="endDate" placeholder="YYYY-MM-DD"> + </label> + </td> + </tr> + </tbody> + </table> + <div class="quiqqer-memberships-membershipuseredit-submit"></div> +</form> \ No newline at end of file diff --git a/bin/controls/users/MembershipUserEdit.js b/bin/controls/users/MembershipUserEdit.js new file mode 100644 index 0000000..a865c48 --- /dev/null +++ b/bin/controls/users/MembershipUserEdit.js @@ -0,0 +1,153 @@ +/** + * MembershipUserEdit JavaScript Control + * + * Edit a MembershipUser + * + * @module package/quiqqer/memberships/bin/controls/users/MembershipUserEdit + * @author www.pcsg.de (Patrick Müller) + * + * @require qui/controls/Control + * @require qui/controls/loader/Loader + * @require qui/controls/buttons/Button + * @require qui/utils/Form + * @require package/quiqqer/memberships/bin/MembershipUsers + * @require Locale + * @require Ajax + * @require Mustache + * @require text!package/quiqqer/memberships/bin/controls/users/MembershipUserEdit.html + * @require css!package/quiqqer/memberships/bin/controls/users/MembershipUserEdit.css + */ +define('package/quiqqer/memberships/bin/controls/users/MembershipUserEdit', [ + + 'qui/controls/Control', + 'qui/controls/loader/Loader', + 'qui/controls/buttons/Button', + 'qui/utils/Form', + + 'package/quiqqer/memberships/bin/MembershipUsers', + + 'Locale', + 'Ajax', + 'Mustache', + + 'text!package/quiqqer/memberships/bin/controls/users/MembershipUserEdit.html', + 'css!package/quiqqer/memberships/bin/controls/users/MembershipUserEdit.css' + +], function (QUIControl, QUILoader, QUIButton, QUIFormUtils, MembershipUsersHandler, + QUILocale, QUIAjax, Mustache, template) { + "use strict"; + + var lg = 'quiqqer/memberships'; + + return new Class({ + + Extends: QUIControl, + Type : 'package/quiqqer/memberships/bin/controls/users/MembershipUserEdit', + + Binds: [ + '$onInject', + '$load', + '$onCreate', + '$submit' + ], + + options: { + membershipUserId: false // ID of MembershipUser (this is NOT the QUIQQER User ID!) + }, + + initialize: function (options) { + this.parent(options); + + this.Loader = new QUILoader(); + this.$MembershipUser = null; + + this.addEvents({ + onCreate: this.$onCreate, + onInject: this.$onInject + }); + }, + + /** + * Event: onCreate + */ + $onCreate: function () { + this.$Elm.addClass('quiqqer-memberships-membershipuseredit'); + }, + + /** + * Event: onImport + */ + $onInject: function () { + this.Loader.inject(this.$Elm); + this.refresh(); + }, + + /** + * Refresh data + */ + refresh: function () { + var self = this; + this.Loader.show(); + + var mUid = this.getAttribute('membershipUserId'); + + MembershipUsersHandler.get(mUid).then(function (MembershipUser) { + self.Loader.hide(); + self.$MembershipUser = MembershipUser; + self.$load(); + }); + }, + + /** + * Create elements + */ + $load: function () { + var lgPrefix = 'controls.users.membershipuseredit.template.'; + + this.$Elm.set('html', Mustache.render(template, { + header : QUILocale.get(lg, lgPrefix + 'header', { + id : this.$MembershipUser.id, + name: this.$MembershipUser.fullName + }), + labelBeginDate: QUILocale.get(lg, 'controls.membershipusers.tbl.header.beginDate'), + labelEndDate : QUILocale.get(lg, 'controls.membershipusers.tbl.header.endDate') + })); + + new QUIButton({ + textimage: 'fa fa-save', + text : QUILocale.get(lg, 'controls.users.membershipuseredit.btn.save'), + events : { + onClick: this.$submit + } + }).inject( + this.$Elm.getElement('.quiqqer-memberships-membershipuseredit-submit') + ); + + var Form = this.$Elm.getElement('form'); + + QUIFormUtils.setDataToForm(this.$MembershipUser, Form); + }, + + /** + * Submit MembershipUser data + */ + $submit: function () { + var self = this; + var Form = this.$Elm.getElement('form'); + + this.Loader.show(); + + MembershipUsersHandler.update( + this.$MembershipUser.id, + QUIFormUtils.getFormData(Form) + ).then(function (success) { + if (success) { + self.fireEvent('submit', [self]); + } + + self.Loader.hide(); + self.refresh(); + }); + } + }); +}); diff --git a/bin/controls/users/MembershipUserHistory.css b/bin/controls/users/MembershipUserHistory.css new file mode 100644 index 0000000..9f8bcdc --- /dev/null +++ b/bin/controls/users/MembershipUserHistory.css @@ -0,0 +1,44 @@ +.quiqqer-memberships-membershipuserhistory { + float: left; + height: 100%; + width: 100% +} + +.quiqqer-memberships-membershipuserhistory-history { + float: left; + margin-top: 20px; + width: 100%; +} + +.quiqqer-memberships-membershipuserhistory-history-entry { + float: left; + width: 100%; +} + +.quiqqer-memberships-membershipuserhistory-history-entry:not(:last-of-type) { + margin-bottom: 10px; +} + +.quiqqer-memberships-membershipuserhistory-history-entry-header-action { + float: left; + font-weight: 900; +} + +.quiqqer-memberships-membershipuserhistory-history-entry-header-date { + float: right; + font-size: 10px; +} + +.quiqqer-memberships-membershipuserhistory-history-entry-header { + background-color: #dedede; + float: left; + padding: 2px 5px; + width: 100%; +} + +.quiqqer-memberships-membershipuserhistory-history-entry-body { + background-color: #ededed; + float: left; + padding: 10px; + width: 100%; +} \ No newline at end of file diff --git a/bin/controls/users/MembershipUserHistory.html b/bin/controls/users/MembershipUserHistory.html new file mode 100644 index 0000000..6452871 --- /dev/null +++ b/bin/controls/users/MembershipUserHistory.html @@ -0,0 +1,9 @@ +<div class="quiqqer-memberships-membershipuserhistory-user"> + <span class="quiqqer-memberships-membershipuserhistory-user-name"> + {{userLabel}}: {{user}} + </span><br> + <span class="quiqqer-memberships-membershipuserhistory-user-name"> + {{membershipLabel}}: {{membership}} + </span> +</div> +<div class="quiqqer-memberships-membershipuserhistory-history"></div> \ No newline at end of file diff --git a/bin/controls/users/MembershipUserHistory.js b/bin/controls/users/MembershipUserHistory.js new file mode 100644 index 0000000..8288aa5 --- /dev/null +++ b/bin/controls/users/MembershipUserHistory.js @@ -0,0 +1,149 @@ +/** + * MembershipUserHistory JavaScript Control + * + * View the history log of a specific MembershipUser + * + * @module package/quiqqer/memberships/bin/controls/users/MembershipUserHistory + * @author www.pcsg.de (Patrick Müller) + * + * @require qui/controls/Control + * @require qui/controls/loader/Loader + * @require package/quiqqer/memberships/bin/MembershipUsers + * @require Locale + * @require Ajax + * @require Mustache + * @require text!package/quiqqer/memberships/bin/controls/users/MembershipUserHistory.html + * @require css!package/quiqqer/memberships/bin/controls/users/MembershipUserHistory.css + */ +define('package/quiqqer/memberships/bin/controls/users/MembershipUserHistory', [ + + 'qui/controls/Control', + 'qui/controls/loader/Loader', + + 'package/quiqqer/memberships/bin/MembershipUsers', + + 'Locale', + 'Ajax', + 'Mustache', + + 'text!package/quiqqer/memberships/bin/controls/users/MembershipUserHistory.html', + 'css!package/quiqqer/memberships/bin/controls/users/MembershipUserHistory.css' + +], function (QUIControl, QUILoader, MembershipUsersHandler, + QUILocale, QUIAjax, Mustache, template) { + "use strict"; + + var lg = 'quiqqer/memberships'; + + return new Class({ + + Extends: QUIControl, + Type : 'package/quiqqer/memberships/bin/controls/users/MembershipUserHistory', + + Binds: [ + '$onInject', + '$onCreate', + '$load' + ], + + options: { + membershipUserId: false // ID of MembershipUser (this is NOT the QUIQQER User ID!) + }, + + initialize: function (options) { + this.parent(options); + + this.Loader = new QUILoader(); + this.$MembershipUser = null; + this.$history = []; + + this.addEvents({ + onCreate: this.$onCreate, + onInject: this.$onInject + }); + }, + + /** + * Event: onCreate + */ + $onCreate: function () { + this.$Elm.addClass('quiqqer-memberships-membershipuserhistory'); + }, + + /** + * Event: onImport + */ + $onInject: function () { + var self = this; + + this.Loader.inject(this.$Elm); + this.Loader.show(); + + var mUid = this.getAttribute('membershipUserId'); + + Promise.all([ + MembershipUsersHandler.get(mUid), + MembershipUsersHandler.getHistory(mUid) + ]).then(function (result) { + self.Loader.hide(); + self.$MembershipUser = result[0]; + self.$history = result[1]; + self.$load(); + }); + }, + + /** + * Create elements + */ + $load: function () { + var lgPrefix = 'controls.users.membershipuserhistory.template.'; + var username = this.$MembershipUser.fullName; + + if (this.$MembershipUser.username !== this.$MembershipUser.fullName) { + username += ' (' + this.$MembershipUser.username + ')'; + } + + username += ' [' + this.$MembershipUser.userId + ']'; + + this.$Elm.set('html', Mustache.render(template, { + userLabel : QUILocale.get(lg, lgPrefix + 'userLabel'), + membershipLabel: QUILocale.get(lg, lgPrefix + 'membershipLabel'), + user : username, + membership : this.$MembershipUser.membershipTitle + + ' [' + this.$MembershipUser.membershipId + ']' + })); + + var HistoryElm = this.$Elm.getElement( + '.quiqqer-memberships-membershipuserhistory-history' + ); + + var i = this.$history.length; + + this.$history.forEach(function (Entry) { + var EntryElm = new Element('div', { + 'class': 'quiqqer-memberships-membershipuserhistory-history-entry' + }).inject(HistoryElm); + + // header + new Element('div', { + 'class': 'quiqqer-memberships-membershipuserhistory-history-entry-header', + html : '<span class="quiqqer-memberships-membershipuserhistory-history-entry-header-action">' + + ' #' + i-- + ' ' + + QUILocale.get(lg, 'controls.users.membershipuserhistory.entry.type.' + Entry.type) + + '</span>' + + '<span class="quiqqer-memberships-membershipuserhistory-history-entry-header-date">' + + Entry.time + '<br>' + Entry.user + + '</span>' + }).inject(EntryElm); + + // body + if (Entry.msg !== '') { + new Element('div', { + 'class': 'quiqqer-memberships-membershipuserhistory-history-entry-body', + html : Entry.msg + }).inject(EntryElm); + } + }); + } + }); +}); diff --git a/bin/controls/users/MembershipUserHistoryPopup.js b/bin/controls/users/MembershipUserHistoryPopup.js new file mode 100644 index 0000000..c0c90e5 --- /dev/null +++ b/bin/controls/users/MembershipUserHistoryPopup.js @@ -0,0 +1,61 @@ +/** + * MembershipUserHistoryPopup JavaScript Control + * + * Popup vor viewing the history log of a specific MembershipUser + * + * @module package/quiqqer/memberships/bin/controls/users/MembershipUserHistoryPopup + * @author www.pcsg.de (Patrick Müller) + * + * @require qui/controls/windows/Popup + * @require Locale + */ +define('package/quiqqer/memberships/bin/controls/users/MembershipUserHistoryPopup', [ + + 'qui/controls/windows/Popup', + 'package/quiqqer/memberships/bin/controls/users/MembershipUserHistory', + 'Locale' + +], function (QUIPopup, MembershipUserHistory, QUILocale) { + "use strict"; + + var lg = 'quiqqer/memberships'; + + return new Class({ + + Extends: QUIPopup, + Type : 'package/quiqqer/memberships/bin/controls/users/MembershipUserHistoryPopup', + + Binds: [ + '$onOpen' + ], + + options: { + membershipUserId: false, // ID of MembershipUser (this is NOT the QUIQQER User ID!) + maxWidth : 550, + maxHeight : 500, + icon : 'fa fa-history', + title : QUILocale.get(lg, 'controls.users.membershipuserhistorypopup.title'), + 'class' : 'quiqqer-memberships-membershipuserhistorypopup', + + // buttons + closeButtonText: QUILocale.get('qui/controls/windows/Popup', 'btn.close') + }, + + initialize: function (options) { + this.parent(options); + + this.addEvents({ + onOpen: this.$onOpen + }); + }, + + /** + * Event: onOpen + */ + $onOpen: function () { + new MembershipUserHistory({ + membershipUserId: this.getAttribute('membershipUserId') + }).inject(this.getContent()); + } + }); +}); diff --git a/bin/controls/users/MembershipUsers.js b/bin/controls/users/MembershipUsers.js index 6ceb782..3c80771 100644 --- a/bin/controls/users/MembershipUsers.js +++ b/bin/controls/users/MembershipUsers.js @@ -36,6 +36,7 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ 'package/quiqqer/memberships/bin/Memberships', 'package/quiqqer/memberships/bin/MembershipUsers', + 'package/quiqqer/memberships/bin/controls/users/MembershipUserEdit', 'Locale', 'Ajax', @@ -46,7 +47,7 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ ], function (QUIControl, QUILoader, QUIPopup, QUIConfirm, QUIButton, QUIFormUtils, QUIControlUtils, Grid, UserSearchWindow, Memberships, MembershipUsersHandler, - QUILocale, QUIAjax, Mustache, template) { + MembershipUserEdit, QUILocale, QUIAjax, Mustache, template) { "use strict"; var lg = 'quiqqer/memberships'; @@ -66,7 +67,8 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ '$removeUser', 'refresh', '$removeUsers', - '$openUserPanel' + '$showHistory', + '$editUser' ], options: { @@ -146,6 +148,20 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ events : { onClick: this.$addUser } + }, { + name : 'edit', + text : QUILocale.get(lg, 'controls.membershipusers.tbl.btn.edit'), + textimage: 'fa fa-edit', + events : { + onClick: this.$editUser + } + }, { + name : 'history', + text : QUILocale.get(lg, 'controls.users.membershipusersarchive.tbl.btn.history'), + textimage: 'fa fa-history', + events : { + onClick: this.$showHistory + } }, { name : 'removeuser', text : QUILocale.get(lg, 'controls.membershipusers.tbl.btn.removeuser'), @@ -156,6 +172,11 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ }], columnModel : [{ header : QUILocale.get('quiqqer/system', 'id'), + dataIndex: 'id', + dataType : 'number', + width : 100 + }, { + header : QUILocale.get(lg, 'controls.membershipusers.tbl.header.userId'), dataIndex: 'userId', dataType : 'number', width : 100 @@ -189,10 +210,6 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ dataIndex: 'extendCounter', dataType : 'number', width : 75 - }, { - dataIndex: 'id', - dataType : 'number', - hidden : true }], pagination : true, serverSort : true, @@ -201,11 +218,20 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ }); this.$Grid.addEvents({ - onDblClick: self.$openUserPanel, + onDblClick: self.$editUser, onClick : function () { var TableButtons = self.$Grid.getAttribute('buttons'); + var selected = self.$Grid.getSelectedData().length; TableButtons.removeuser.enable(); + + if (selected === 1) { + TableButtons.history.enable(); + TableButtons.edit.enable(); + } else { + TableButtons.history.disable(); + TableButtons.edit.disable(); + } }, onRefresh : this.$listRefresh }); @@ -242,6 +268,8 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ var TableButtons = this.$Grid.getAttribute('buttons'); TableButtons.removeuser.disable(); + TableButtons.history.disable(); + TableButtons.edit.disable(); var GridParams = { sortOn : Grid.getAttribute('sortOn'), @@ -334,6 +362,42 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ AddUsersWindow.open(); }, + /** + * Edit MembershipUser + */ + $editUser: function () { + var membershipUserId = this.$Grid.getSelectedData()[0].id; + + // open popup + var Popup = new QUIPopup({ + 'maxHeight': 275, + maxWidth : 500, + 'autoclose': true, + 'title' : QUILocale.get(lg, 'controls.membershipusers.edit.popup.title'), + 'texticon' : 'fa fa-edit', + 'icon' : 'fa fa-edit', + + buttons: false, + events : { + onOpen: function () { + new MembershipUserEdit({ + membershipUserId: membershipUserId, + events: { + onSubmit: function() { + Popup.close(); + self.refresh(); + } + } + }).inject( + Popup.getContent() + ); + } + } + }); + + Popup.open(); + }, + /** * Remove all selected licenses */ @@ -395,17 +459,18 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsers', [ }, /** - * Opens a panel for a single location + * Show history */ - $openUserPanel: function () { - var userId = this.$Grid.getSelectedData()[0].userId; + $showHistory: function () { + var membershipUserId = this.$Grid.getSelectedData()[0].id; require([ - 'controls/users/User', - 'utils/Panels' - ], function (UserPanel, Utils) { - Utils.openPanelInTasks(new UserPanel(userId)); + 'package/quiqqer/memberships/bin/controls/users/MembershipUserHistoryPopup' + ], function (MembershipUserHistoryPopup) { + new MembershipUserHistoryPopup({ + membershipUserId: membershipUserId + }).open(); }); - }, + } }); }); diff --git a/bin/controls/users/MembershipUsersArchive.js b/bin/controls/users/MembershipUsersArchive.js index 171e786..e5658a3 100644 --- a/bin/controls/users/MembershipUsersArchive.js +++ b/bin/controls/users/MembershipUsersArchive.js @@ -36,6 +36,7 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsersArchive', 'package/quiqqer/memberships/bin/Memberships', 'package/quiqqer/memberships/bin/MembershipUsers', + 'package/quiqqer/memberships/bin/controls/users/MembershipUserHistory', 'Locale', 'Ajax', @@ -46,7 +47,7 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsersArchive', ], function (QUIControl, QUILoader, QUIPopup, QUIConfirm, QUIButton, QUIFormUtils, QUIControlUtils, Grid, UserSearchWindow, Memberships, MembershipUsersHandler, - QUILocale, QUIAjax, Mustache, template) { + MembershipUserHistory, QUILocale, QUIAjax, Mustache, template) { "use strict"; var lg = 'quiqqer/memberships'; @@ -145,6 +146,11 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsersArchive', }], columnModel : [{ header : QUILocale.get('quiqqer/system', 'id'), + dataIndex: 'id', + dataType : 'number', + width : 100 + }, { + header : QUILocale.get(lg, 'controls.membershipusers.tbl.header.userId'), dataIndex: 'userId', dataType : 'number', width : 100 @@ -173,10 +179,6 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsersArchive', dataIndex: 'archiveReason', dataType : 'string', width : 200 - }, { - dataIndex: 'id', - dataType : 'number', - hidden : true }], pagination : true, serverSort : true, @@ -185,7 +187,7 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsersArchive', }); this.$Grid.addEvents({ - onDblClick: self.$openUserPanel, + onDblClick: self.$showHistory, onClick : function () { var TableButtons = self.$Grid.getAttribute('buttons'); var selected = self.$Grid.getSelectedData().length; @@ -253,8 +255,6 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsersArchive', * @param {Object} GridData */ $setGridData: function (GridData) { - var self = this; - for (var i = 0, len = GridData.data.length; i < len; i++) { var Row = GridData.data[i]; @@ -271,63 +271,18 @@ define('package/quiqqer/memberships/bin/controls/users/MembershipUsersArchive', }, /** - * Remove all selected licenses + * Show history */ $showHistory: function () { - var self = this; - var deleteData = []; - var deleteIds = []; - var rows = this.$Grid.getSelectedData(); - - for (var i = 0, len = rows.length; i < len; i++) { - deleteData.push( - rows[i].username + ' (ID: #' + rows[i].id + ')' - ); - - deleteIds.push(rows[i].id); - } - - // open popup - var Popup = new QUIConfirm({ - 'maxHeight': 300, - 'autoclose': true, - - 'information': QUILocale.get( - lg, - 'controls.membershipusersarchive.delete.popup.info', { - users: deleteData.join('<br/>') - } - ), - 'title' : QUILocale.get(lg, 'controls.membershipusersarchive.delete.popup.title'), - 'texticon' : 'fa fa-trash', - 'icon' : 'fa fa-trash', - - cancel_button: { - text : false, - textimage: 'icon-remove fa fa-remove' - }, - ok_button : { - text : false, - textimage: 'icon-ok fa fa-check' - }, - events : { - onSubmit: function () { - Popup.Loader.show(); - - MembershipUsersArchiveHandler.deleteMembershipUsersArchive(deleteIds).then(function (success) { - if (!success) { - Popup.Loader.hide(); - return; - } - - Popup.close(); - self.refresh(); - }); - } - } + var membershipUserId = this.$Grid.getSelectedData()[0].id; + + require([ + 'package/quiqqer/memberships/bin/controls/users/MembershipUserHistoryPopup' + ], function (MembershipUserHistoryPopup) { + new MembershipUserHistoryPopup({ + membershipUserId: membershipUserId + }).open(); }); - - Popup.open(); } }); }); diff --git a/locale.xml b/locale.xml index 8bd5017..9e09460 100644 --- a/locale.xml +++ b/locale.xml @@ -255,6 +255,14 @@ <de><![CDATA[Benutzer entfernen]]></de> <en><![CDATA[Remove user(s)]]></en> </locale> + <locale name="controls.membershipusers.tbl.btn.edit"> + <de><![CDATA[Benutzer bearbeiten]]></de> + <en><![CDATA[Edit user]]></en> + </locale> + <locale name="controls.membershipusers.tbl.header.userId"> + <de><![CDATA[User ID]]></de> + <en><![CDATA[User ID]]></en> + </locale> <locale name="controls.membershipusers.tbl.header.username"> <de><![CDATA[Benutzername]]></de> <en><![CDATA[Username]]></en> @@ -287,6 +295,10 @@ <de><![CDATA[Benutzer aus Mitgliedschaft entfernen]]></de> <en><![CDATA[Remove user(s) from membership]]></en> </locale> + <locale name="controls.membershipusers.edit.popup.title"> + <de><![CDATA[Mitgliedschafts-Benutzer bearbeiten]]></de> + <en><![CDATA[Edit membership user]]></en> + </locale> <!-- Controls: users/MembershipUsersArchive --> <locale name="controls.users.membershipusersarchive.tbl.btn.history"> @@ -314,6 +326,72 @@ <en><![CDATA[Membership expired]]></en> </locale> + <!-- Controls: users/MembershipUserHistory --> + <locale name="controls.users.membershipuserhistory.template.userLabel"> + <de><![CDATA[Benutzer]]></de> + <en><![CDATA[User]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.template.membershipLabel"> + <de><![CDATA[Mitgliedschaft]]></de> + <en><![CDATA[Membership]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.footer"> + <de><![CDATA[ausgeführt von [user]]]></de> + <en><![CDATA[executed by [user]]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.created"> + <de><![CDATA[Zur Mitgliedschaft hinzugefügt]]></de> + <en><![CDATA[Added to the membership]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.updated"> + <de><![CDATA[Mitgliedschafts-Daten aktualisiert]]></de> + <en><![CDATA[Updated membership data]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.cancel_start"> + <de><![CDATA[Kündigungs-Anfrage gestellt]]></de> + <en><![CDATA[Termination requested]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.cancel_confirm"> + <de><![CDATA[Kündigung bestätigt]]></de> + <en><![CDATA[Termination confirmed]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.cancelled"> + <de><![CDATA[Mitgliedschaft gekündigt]]></de> + <en><![CDATA[Membership terminated]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.expired"> + <de><![CDATA[Mitgliedschafts-Zeit abgelaufen]]></de> + <en><![CDATA[Membership expired]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.deleted"> + <de><![CDATA[Aus Mitgliedschaft gelöscht]]></de> + <en><![CDATA[Deleted from membership]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.archived"> + <de><![CDATA[Mitgliedschafts-Benutzer archiviert]]></de> + <en><![CDATA[Membership user archived]]></en> + </locale> + <locale name="controls.users.membershipuserhistory.entry.type.extended"> + <de><![CDATA[Mitgliedschafts-Zeit verlängert]]></de> + <en><![CDATA[Membership extended]]></en> + </locale> + + <!-- Controls: users/MembershipUserHistoryPopup --> + <locale name="controls.users.membershipuserhistorypopup.title"> + <de><![CDATA[Mitgliedschafts-Benutzer History]]></de> + <en><![CDATA[Membership user history]]></en> + </locale> + + <!-- Controls: users/MembershipUserEdit --> + <locale name="controls.users.membershipuseredit.template.header"> + <de><![CDATA[Mitgliedschafts-Benutzer [name] (#[id])]]></de> + <en><![CDATA[Membership user [name] (#[id])]]></en> + </locale> + <locale name="controls.users.membershipuseredit.btn.save"> + <de><![CDATA[Benutzerdaten speichern]]></de> + <en><![CDATA[Save user data]]></en> + </locale> + </groups> <groups name="quiqqer/memberships" datatype="php"> @@ -373,6 +451,14 @@ <de><![CDATA[Die Benutzer wurden erfolgreich aus der Mitgliedschaft gelöscht.]]></de> <en><![CDATA[The users have been removed successfully from the membership.]]></en> </locale> + <locale name="message.ajax.memberships.users.update.error" html="true"> + <de><![CDATA[Der Mitgliedschaftsbenutzer konnte nicht bearbeitet werden:<br><br>[error]]]></de> + <en><![CDATA[The membership user could not be updated:<br><br>[error]]]></en> + </locale> + <locale name="message.ajax.memberships.users.update.success" html="true"> + <de><![CDATA[Der Mitgliedschafts-Benutzer <b>[membershipUserName]</b> (#[membershipUserId]) wurde erfolgreich aktualisiert.]]></de> + <en><![CDATA[The membership user <b>[membershipUserName]</b> (#[membershipUserId]) was successfully updated.]]></en> + </locale> <!-- Class: Membership --> <locale name="exception.membership.cannot.update.when.locked"> @@ -419,6 +505,18 @@ <de><![CDATA[Der Prüf-Hash für die Mitgliedschafts-Kündigung ist fehlerhaft.]]></de> <en><![CDATA[The cancel check hash for this membership cancellation is wrong.]]></en> </locale> + <locale name="exception.users.membershipuser.wrong.dates"> + <de><![CDATA[Die Datumsangaben für den Start- oder Endzeitpunkt sind in einem inkorrekten Format.]]></de> + <en><![CDATA[The dates for the start or end time are in an incorrect format.]]></en> + </locale> + <locale name="exception.users.membershipuser.begin.after.end"> + <de><![CDATA[Der Startzeitpunkt darf nicht nach dem Endzeitpunkt liegen.]]></de> + <en><![CDATA[The start time must not be after the end time.]]></en> + </locale> + <locale name="exception.users.membershipuser.no.email"> + <de><![CDATA[Es können keine E-Mails an den Mitgliedschafts-Benutzer gesendet werden, da er keine eingetragene E-Mail-Adresse hat.]]></de> + <en><![CDATA[No e-mails can be sent to the membership user, since he does not have a registered e-mail address.]]></en> + </locale> <!-- Templates --> <locale name="templates.mail.greeting"> diff --git a/src/QUI/Memberships/Cron.php b/src/QUI/Memberships/Cron.php index c551433..780c71e 100644 --- a/src/QUI/Memberships/Cron.php +++ b/src/QUI/Memberships/Cron.php @@ -30,33 +30,40 @@ public static function checkMembershipUsers() $now = time(); foreach ($result as $row) { - /** @var MembershipUser $MembershipUser */ - $MembershipUser = $MembershipUsers->getChild($row['id']); - $Membership = $MembershipUser->getMembership(); + try { + /** @var MembershipUser $MembershipUser */ + $MembershipUser = $MembershipUsers->getChild($row['id']); + $Membership = $MembershipUser->getMembership(); - // @todo prüfen, ob benutzer existiert und ggf. löschen + // @todo prüfen, ob benutzer existiert und ggf. löschen - // check if membership has expired - $endTimestamp = strtotime($Membership->getAttribute('endDate')); + // check if membership has expired + $endTimestamp = strtotime($Membership->getAttribute('endDate')); - if ($now < $endTimestamp) { - continue; - } + if ($now < $endTimestamp) { + continue; + } - // if membership has been cancelled -> archive it immediately - if ($MembershipUser->isCancelled()) { - $MembershipUser->cancel(); - continue; - } + // if membership has been cancelled -> archive it immediately + if ($MembershipUser->isCancelled()) { + $MembershipUser->cancel(); + continue; + } + + // extend if membership is extended automatically + if ($Membership->isAutoExtend()) { + $MembershipUser->extend(); + continue; + } - // extend if membership is extended automatically - if ($Membership->isAutoExtend()) { - $MembershipUser->extend(); - continue; + // expire membership + $MembershipUser->expire(); + } catch (\Exception $Exception) { + QUI\System\Log::addError( + self::class . ' :: checkMembershipUsers() -> ' . $Exception->getMessage() + ); } - // expire membership - $MembershipUser->expire(); } } } diff --git a/src/QUI/Memberships/Users/MembershipUser.php b/src/QUI/Memberships/Users/MembershipUser.php index 98124d5..06dfd52 100644 --- a/src/QUI/Memberships/Users/MembershipUser.php +++ b/src/QUI/Memberships/Users/MembershipUser.php @@ -18,6 +18,34 @@ */ class MembershipUser extends Child { + /** + * @inheritdoc + */ + public function update() + { + // check certain attributes + $beginDate = strtotime($this->getAttribute('beginDate')); + $endDate = strtotime($this->getAttribute('endDate')); + + if ($beginDate === false + || $endDate === false + ) { + throw new QUI\Memberships\Exception(array( + 'quiqqer/memberships', + 'exception.users.membershipuser.wrong.dates' + )); + } + + if ($beginDate >= $endDate) { + throw new QUI\Memberships\Exception(array( + 'quiqqer/memberships', + 'exception.users.membershipuser.begin.after.end' + )); + } + + parent::update(); + } + /** * Extend the current membership cycle of this membership user * @@ -108,6 +136,8 @@ public function startManualCancel() 'cancelDate' => $cancelDate )); + $this->addHistoryEntry(MembershipUsersHandler::HISTORY_TYPE_CANCEL_START); + // save cancel hash and date to database $this->update(); @@ -132,6 +162,13 @@ public function startManualCancel() */ public function confirmManualCancel($confirmHash) { + if ($this->isCancelled()) { + throw new QUI\Memberships\Exception(array( + 'quiqqer/memberships', + 'exception.users.membershipuser.confirmManualCancel.already.cancelled' + )); + } + $cancelHash = $this->getAttribute('cancelHash'); // if (empty($cancelHash)) { @@ -148,18 +185,12 @@ public function confirmManualCancel($confirmHash) )); } - if ($this->isCancelled()) { - throw new QUI\Memberships\Exception(array( - 'quiqqer/memberships', - 'exception.users.membershipuser.confirmManualCancel.already.cancelled' - )); - } - $this->setAttributes(array( 'cancelled' => true )); $this->addHistoryEntry(MembershipUsersHandler::HISTORY_TYPE_CANCEL_CONFIRM); + $this->update(); // send confirm cancel mail $subject = $this->getUser()->getLocale()->get('quiqqer/memberships', 'templates.mail.confirmcancel.subject'); @@ -328,7 +359,7 @@ public function getUser() * @param string $type - History entry type (see \QUI\Memberships\Users\Handler) * @param string $msg (optional) - additional custom message */ - public function addHistoryEntry($type, $msg = null) + public function addHistoryEntry($type, $msg = "") { $history = $this->getAttribute('history'); @@ -344,12 +375,30 @@ public function addHistoryEntry($type, $msg = null) 'type' => $type, 'time' => Utils::getFormattedTimestamp(), 'user' => $User->getUsername() . ' (' . $User->getId() . ')', - 'msg' => $msg ?: '-' + 'msg' => $msg ); $this->setAttribute('history', json_encode($history)); } + /** + * Get history data of this MembershipUser + * + * @return array + */ + public function getHistory() + { + $history = $this->getAttribute('history'); + + if (empty($history)) { + $history = array(); + } else { + $history = json_decode($history, true); + } + + return $history; + } + /** * Send an email to the membership user * @@ -357,9 +406,21 @@ public function addHistoryEntry($type, $msg = null) * @param string $templateFile * @param array $templateVars (optional) - additional template variables (besides $this) * @return void + * + * @throws QUI\Memberships\Exception */ protected function sendMail($subject, $templateFile, $templateVars = array()) { + $User = $this->getUser(); + $email = $User->getAttribute('email'); + + if (empty($email)) { + throw new QUI\Memberships\Exception(array( + 'quiqqer/memberships', + 'exception.users.membershipuser.no.email' + )); + } + $Engine = QUI::getTemplateManager()->getEngine(); $Engine->assign(array_merge( @@ -374,8 +435,7 @@ protected function sendMail($subject, $templateFile, $templateVars = array()) $Mailer = new Mailer(); - // @todo E-Mail aus Benutzer holen - $Mailer->addRecipient('peat@pcsg.de', $this->getUser()->getName()); + $Mailer->addRecipient($email, $User->getName()); $Mailer->setSubject($subject); $Mailer->setBody($template); $Mailer->send(); diff --git a/templates/mail_autoextend.html b/templates/mail_autoextend.html index e8754c4..8f7662b 100644 --- a/templates/mail_autoextend.html +++ b/templates/mail_autoextend.html @@ -1,10 +1,10 @@ <h1> - {locale group="quiqqer/memberships" value="templates.mail.greeting" + {locale group="quiqqer/memberships" value="templates.mail.greeting" Locale=$Locale name=$MembershipUser->getUser()->getName()} </h1> <p> - {locale group="quiqqer/memberships" value="templates.mail.autoextend.body" + {locale group="quiqqer/memberships" value="templates.mail.autoextend.body" Locale=$Locale membershipTitle=$MembershipUser->getMembership()->getTitle() endDate=$MembershipUser->getAttribute('endDate') } diff --git a/templates/mail_confirmcancel.html b/templates/mail_confirmcancel.html index 510cd48..632fcd1 100644 --- a/templates/mail_confirmcancel.html +++ b/templates/mail_confirmcancel.html @@ -1,9 +1,10 @@ <h1> - {$Locale->get('quiqqer/memberships', 'templates.mail.greeting', array('name' => $MembershipUser->getUser()->getName()} + {locale group="quiqqer/memberships" value="templates.mail.greeting" Locale=$Locale + name=$MembershipUser->getUser()->getName()} </h1> <p> - {locale group="quiqqer/memberships" value="templates.mail.confirmcancel.body" + {locale group="quiqqer/memberships" value="templates.mail.confirmcancel.body" Locale=$Locale membershipTitle=$MembershipUser->getMembership()->getTitle() endDate=$MembershipUser->getAttribute('endDate') } diff --git a/templates/mail_expired.html b/templates/mail_expired.html index c0966b1..23e1fa5 100644 --- a/templates/mail_expired.html +++ b/templates/mail_expired.html @@ -1,10 +1,10 @@ <h1> - {locale group="quiqqer/memberships" value="templates.mail.greeting" + {locale group="quiqqer/memberships" value="templates.mail.greeting" Locale=$Locale name=$MembershipUser->getUser()->getName()} </h1> <p> - {locale group="quiqqer/memberships" value="templates.mail.expired.body" + {locale group="quiqqer/memberships" value="templates.mail.expired.body" Locale=$Locale membershipTitle=$MembershipUser->getMembership()->getTitle() endDate=$MembershipUser->getAttribute('endDate') } -- GitLab