From ee03f1a79cc06d3e51542d7cbfe9a31eaf280ff3 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 4 Aug 2016 14:26:07 +0200 Subject: [PATCH] admin interface to list coupons --- .../controllers/admin/pricing.coffee.erb | 74 ++++++++++++++++--- app/assets/javascripts/router.coffee.erb | 24 ++++++ app/assets/javascripts/services/coupon.coffee | 8 ++ .../templates/admin/coupons/_coupon.html.erb | 0 .../templates/admin/coupons/edit.html.erb | 1 + .../templates/admin/coupons/new.html.erb | 1 + .../templates/admin/pricing/coupons.html.erb | 24 ++++++ .../templates/admin/pricing/index.html.erb | 4 + config/locales/app.admin.en.yml | 14 +++- config/locales/app.admin.fr.yml | 12 +++ config/routes.rb | 1 + 11 files changed, 152 insertions(+), 11 deletions(-) create mode 100644 app/assets/javascripts/services/coupon.coffee create mode 100644 app/assets/templates/admin/coupons/_coupon.html.erb create mode 100644 app/assets/templates/admin/coupons/edit.html.erb create mode 100644 app/assets/templates/admin/coupons/new.html.erb create mode 100644 app/assets/templates/admin/pricing/coupons.html.erb diff --git a/app/assets/javascripts/controllers/admin/pricing.coffee.erb b/app/assets/javascripts/controllers/admin/pricing.coffee.erb index 99f6b9475..151ca90c1 100644 --- a/app/assets/javascripts/controllers/admin/pricing.coffee.erb +++ b/app/assets/javascripts/controllers/admin/pricing.coffee.erb @@ -3,8 +3,8 @@ ## # Controller used in the prices edition page ## -Application.Controllers.controller "EditPricingController", ["$scope", "$state", '$uibModal', 'TrainingsPricing', '$filter', 'Credit', 'Pricing', 'Plan', 'plans', 'groups', 'growl', 'machinesPricesPromise', 'Price', 'dialogs', 'trainingsPricingsPromise', 'trainingsPromise', 'machineCreditsPromise', 'machinesPromise', 'trainingCreditsPromise', '_t' -, ($scope, $state, $uibModal, TrainingsPricing, $filter, Credit, Pricing, Plan, plans, groups, growl, machinesPricesPromise, Price, dialogs, trainingsPricingsPromise, trainingsPromise, machineCreditsPromise, machinesPromise, trainingCreditsPromise, _t) -> +Application.Controllers.controller "EditPricingController", ["$scope", "$state", '$uibModal', 'TrainingsPricing', '$filter', 'Credit', 'Pricing', 'Plan', 'plans', 'groups', 'growl', 'machinesPricesPromise', 'Price', 'dialogs', 'trainingsPricingsPromise', 'trainingsPromise', 'machineCreditsPromise', 'machinesPromise', 'trainingCreditsPromise', 'couponsPromise', '_t' +, ($scope, $state, $uibModal, TrainingsPricing, $filter, Credit, Pricing, Plan, plans, groups, growl, machinesPricesPromise, Price, dialogs, trainingsPricingsPromise, trainingsPromise, machineCreditsPromise, machinesPromise, trainingCreditsPromise, couponsPromise, _t) -> ### PUBLIC SCOPE ### ## List of machines prices (not considering any plan) @@ -34,6 +34,9 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state", ## List of machines $scope.machines = machinesPromise + ## List of coupons + $scope.coupons = couponsPromise + ## The plans list ordering. Default: by group $scope.orderPlans = 'group_id' @@ -275,7 +278,7 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state", ## $scope.deletePlan = (plans, id) -> if typeof id != 'number' - console.error('[editPricingController::deletePlan] Error: invalid id parameter') + console.error('[EditPricingController::deletePlan] Error: invalid id parameter') else # open a confirmation dialog dialogs.confirm @@ -287,10 +290,10 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state", # the admin has confirmed, delete the plan Plan.delete {id: id}, (res) -> growl.success(_t('subscription_plan_was_successfully_deleted')) - $scope.plans.splice(findPlanIdxById(plans, id), 1) + $scope.plans.splice(findItemIdxById(plans, id), 1) , (error) -> - console.error('[editPricingController::deletePlan] Error: '+error.statusText) if error.statusText + console.error('[EditPricingController::deletePlan] Error: '+error.statusText) if error.statusText growl.error(_t('unable_to_delete_the_specified_subscription_an_error_occurred')) @@ -308,12 +311,50 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state", - ### PRIVATE SCOPE ### + ## + # Return a textual status concerning the given coupon + # @param coupon {Object} + # @return {string} + ## + $scope.getCouponStatus = (coupon) -> + unless coupon.active + return _t('disabled') + unless moment(coupon.valid).isSameOrBefore() + return _t('expired') + unless coupon.usages <= coupon.max_usages + return _t('sold_out') + return _t('active') - findPlanIdxById = (plans, id)-> - (plans.map (plan)-> - plan.id - ).indexOf(id) + + + ## + # Delete a coupon from the server's database and, in case of success, from the list in memory + # @param coupons {Array} should be called with $scope.coupons + # @param id {number} ID of the coupon to delete + ## + $scope.deleteCoupon = (coupons, id) -> + if typeof id != 'number' + console.error('[EditPricingController::deleteCoupon] Error: invalid id parameter') + else + # open a confirmation dialog + dialogs.confirm + resolve: + object: -> + title: _t('confirmation_required') + msg: _t('do_you_really_want_to_delete_this_coupon') + , -> + # the admin has confirmed, delete the coupon + Coupon.delete {id: id}, (res) -> + growl.success(_t('coupon_was_successfully_deleted')) + $scope.coupons.splice(findItemIdxById(coupons, id), 1) + + , (error) -> + console.error('[EditPricingController::deleteCoupon] Error: '+error.statusText) if error.statusText + growl.error(_t('unable_to_delete_the_specified_coupon_an_error_occurred')) + + + + ### PRIVATE SCOPE ### ## # Kind of constructor: these actions will be realized first when the controller is loaded @@ -329,6 +370,19 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state", + ## + # Retrieve an item index by its ID from the given array of objects + # @param items {Array<{id:number}>} + # @param id {number} + # @returns {number} item index in the provided array + ## + findItemIdxById = (items, id)-> + (items.map (item)-> + item.id + ).indexOf(id) + + + ## # Group the given credits array into a map associating the plan ID with its associated trainings/machines # @return {Object} the association map diff --git a/app/assets/javascripts/router.coffee.erb b/app/assets/javascripts/router.coffee.erb index 025864982..247b3899a 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -742,6 +742,9 @@ angular.module('application.router', ['ui.router']). trainingCreditsPromise: ['Credit', (Credit) -> Credit.query({creditable_type: 'Training'}).$promise ] + couponsPromise: ['Coupon', (Coupon) -> + Coupon.query().$promise + ] # plans .state 'app.admin.plans', @@ -786,6 +789,27 @@ angular.module('application.router', ['ui.router']). Translations.query(['app.admin.plans.edit', 'app.shared.plan']).$promise ] + # coupons + .state 'app.admin.coupons.new', + url: '/admin/coupons/new' + views: + 'main@': + templateUrl: '<%= asset_path "admin/coupons/new.html" %>' + controller: 'NewCouponController' + resolve: + translations: [ 'Translations', (Translations) -> + Translations.query(['app.admin.coupons.new', 'app.shared.coupon']).$promise + ] + .state 'app.admin.coupons.edit', + url: '/admin/coupons/:id/edit' + views: + 'main@': + templateUrl: '<%= asset_path "admin/coupons/edit.html" %>' + controller: 'EditCouponController' + resolve: + translations: [ 'Translations', (Translations) -> + Translations.query(['app.admin.coupons.edit', 'app.shared.coupon']).$promise + ] diff --git a/app/assets/javascripts/services/coupon.coffee b/app/assets/javascripts/services/coupon.coffee new file mode 100644 index 000000000..8c13f0b21 --- /dev/null +++ b/app/assets/javascripts/services/coupon.coffee @@ -0,0 +1,8 @@ +'use strict' + +Application.Services.factory 'Coupon', ["$resource", ($resource)-> + $resource "/api/coupons/:id", + {id: "@id"}, + update: + method: 'PUT' +] diff --git a/app/assets/templates/admin/coupons/_coupon.html.erb b/app/assets/templates/admin/coupons/_coupon.html.erb new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/templates/admin/coupons/edit.html.erb b/app/assets/templates/admin/coupons/edit.html.erb new file mode 100644 index 000000000..324e1dfe7 --- /dev/null +++ b/app/assets/templates/admin/coupons/edit.html.erb @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/templates/admin/coupons/new.html.erb b/app/assets/templates/admin/coupons/new.html.erb new file mode 100644 index 000000000..324e1dfe7 --- /dev/null +++ b/app/assets/templates/admin/coupons/new.html.erb @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/templates/admin/pricing/coupons.html.erb b/app/assets/templates/admin/pricing/coupons.html.erb new file mode 100644 index 000000000..3c177b303 --- /dev/null +++ b/app/assets/templates/admin/pricing/coupons.html.erb @@ -0,0 +1,24 @@ +

{{ 'list_of_the_coupons' }}

+ + + + + + + + + + + + + + + + + + + +
{{ 'name' | translate }}{{ 'percentage_off' | translate }}{{ 'status' | translate }}
{{coupon.name}}{{coupon.percent_off}} %{{getCouponStatus(coupon)}} + + +
\ No newline at end of file diff --git a/app/assets/templates/admin/pricing/index.html.erb b/app/assets/templates/admin/pricing/index.html.erb index 850790d42..df110a925 100644 --- a/app/assets/templates/admin/pricing/index.html.erb +++ b/app/assets/templates/admin/pricing/index.html.erb @@ -36,6 +36,10 @@ + + + + diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index df0d6cadd..cfc2a75bf 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -142,8 +142,20 @@ en: changes_have_been_successfully_saved: "Changes have been successfully saved." credit_was_successfully_saved: "Credit was successfully saved." do_you_really_want_to_delete_this_subscription_plan: "Do you really want to delete this subscription plan?" - subscription_plan_was_successfully_deleted: "Subscription plan was successfully delete." + subscription_plan_was_successfully_deleted: "Subscription plan was successfully deleted." unable_to_delete_the_specified_subscription_an_error_occurred: "Unable to delete the specified subscription, an error occurred." + coupons: "Coupons" + list_of_the_coupons: "List of the coupons" + percentage_off: "Percentage off" + status: "Status" + add_a_new_coupon: "Add a new coupon" + disabled: "Disabled" + expired: "Expired" + sold_out: "Sold out" + active: "Active" + do_you_really_want_to_delete_this_coupon: "Do you really want to delete this coupon?" + coupon_was_successfully_deleted: "Coupon was successfully deleted." + unable_to_delete_the_specified_coupon_an_error_occurred: "Unable to delete the specified coupon, an error occurred." plans: new: diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 7bf6309d8..12849c404 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -144,6 +144,18 @@ fr: do_you_really_want_to_delete_this_subscription_plan: "Êtes-vous sûr(e) de vouloir supprimer cette formule d'abonnement ?" subscription_plan_was_successfully_deleted: "La formule d'abonnement a bien été supprimée." unable_to_delete_the_specified_subscription_an_error_occurred: "Impossible de supprimer l'abonnement spécifié, une erreur s'est produite." + coupons: "Codes promotionnels" + list_of_the_coupons: "Liste des codes promotionnels" + percentage_off: "Pourcentage de réduction" + status: "Statut" + add_a_new_coupon: "Ajouter un code promotionnel" + disabled: "Désactivé" + expired: "Expiré" + sold_out: "Épuisé" + active: "Actif" + do_you_really_want_to_delete_this_coupon: "Êtes-vous sûr(e) de vouloir supprimer ce code promotionnel ?" + coupon_was_successfully_deleted: "Le code promotionnel a bien été supprimé." + unable_to_delete_the_specified_coupon_an_error_occurred: "Impossible de supprimer le code promotionnel, une erreur s'est produite." plans: new: diff --git a/config/routes.rb b/config/routes.rb index d0c1be896..9a112414e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -69,6 +69,7 @@ Rails.application.routes.draw do resources :prices, only: [:index, :update] do post 'compute', on: :collection end + resources :coupons resources :trainings_pricings, only: [:index, :update]