diff --git a/app/assets/javascripts/controllers/admin/coupons.coffee b/app/assets/javascripts/controllers/admin/coupons.coffee index 30d0f1451..8617218b2 100644 --- a/app/assets/javascripts/controllers/admin/coupons.coffee +++ b/app/assets/javascripts/controllers/admin/coupons.coffee @@ -1,3 +1,9 @@ +### COMMON CODE ### + +# The validity per user defines how many time a user may ba able to use the same coupon +# Here are the various options for this parameter +userValidities = ['once', 'forever'] + ## # Controller used in the coupon creation page @@ -9,6 +15,9 @@ Application.Controllers.controller "NewCouponController", ["$scope", "$state",'C $scope.coupon = active: true + ## Options for the validity per user + $scope.validities = userValidities + ## Default parameters for AngularUI-Bootstrap datepicker (used for coupon validity limit selection) $scope.datePicker = format: Fablab.uibDateFormat @@ -37,7 +46,7 @@ Application.Controllers.controller "NewCouponController", ["$scope", "$state",'C Coupon.save coupon: $scope.coupon, (coupon) -> $state.go('app.admin.pricing') , (err)-> - growl.error(_t('unable_to_create_the_coupon_an_error_occurred')) + growl.error(_t('unable_to_create_the_coupon_check_code_already_used')) console.error(err) ] @@ -58,6 +67,10 @@ Application.Controllers.controller "EditCouponController", ["$scope", "$state", ## Coupon to edit $scope.coupon = couponPromise + + ## Options for the validity per user + $scope.validities = userValidities + ## Default parameters for AngularUI-Bootstrap datepicker (used for coupon validity limit selection) $scope.datePicker = format: Fablab.uibDateFormat diff --git a/app/assets/templates/admin/coupons/_form.html.erb b/app/assets/templates/admin/coupons/_form.html.erb index f9a1f97fd..bcb045b54 100644 --- a/app/assets/templates/admin/coupons/_form.html.erb +++ b/app/assets/templates/admin/coupons/_form.html.erb @@ -36,6 +36,20 @@ {{ 'percentage_must_be_between_0_and_100' }} +
+ + + {{ 'validity_per_user_is_required' }} +
+
diff --git a/app/controllers/api/coupons_controller.rb b/app/controllers/api/coupons_controller.rb index 430b7bc7f..3b2c6e148 100644 --- a/app/controllers/api/coupons_controller.rb +++ b/app/controllers/api/coupons_controller.rb @@ -19,6 +19,21 @@ class API::CouponsController < API::ApiController end end + def validate + @coupon = Coupon.find_by_code(params[:code]) + if @coupon.nil? + render json: {status: 'rejected'}, status: :not_found + elsif not @coupon.active? + render json: {status: 'disabled'}, status: :unauthorized + elsif @coupon.valid_until.is < DateTime.now + render json: {status: 'expired'}, status: :unauthorized + elsif @coupon.max_usages >= @coupon.invoices.size + render json: {status: 'sold_out'}, status: :unauthorized + else + render :validate, status: :ok, location: @coupon + end + end + def update authorize Coupon if @coupon.update(coupon_params) @@ -43,6 +58,6 @@ class API::CouponsController < API::ApiController end def coupon_params - params.require(:coupon).permit(:name, :code, :percent_off, :valid_until, :max_usages, :active) + params.require(:coupon).permit(:name, :code, :percent_off, :validity_per_user, :valid_until, :max_usages, :active) end end diff --git a/app/models/coupon.rb b/app/models/coupon.rb index 7705a4d26..6d35d3a4b 100644 --- a/app/models/coupon.rb +++ b/app/models/coupon.rb @@ -1,9 +1,13 @@ class Coupon < ActiveRecord::Base has_many :invoices + after_commit :create_stripe_coupon, on: [:create] + after_commit :delete_stripe_coupon, on: [:destroy] + validates :name, presence: true validates :code, presence: true validates :code, format: { with: /\A[A-Z0-9]+\z/ ,message: 'only caps letters and numbers'} + validates :code, uniqueness: true validates :percent_off, presence: true validates :percent_off, :inclusion => 0..100 @@ -15,4 +19,12 @@ class Coupon < ActiveRecord::Base end end + def create_stripe_coupon + StripeWorker.perform_async(:create_stripe_coupon, id) + end + + def delete_stripe_coupon + StripeWorker.perform_async(:delete_stripe_coupon, code) + end + end diff --git a/app/views/api/coupons/_coupon.json.jbuilder b/app/views/api/coupons/_coupon.json.jbuilder index 2289953b5..0c45ae718 100644 --- a/app/views/api/coupons/_coupon.json.jbuilder +++ b/app/views/api/coupons/_coupon.json.jbuilder @@ -1,2 +1,2 @@ -json.extract! coupon, :id, :name, :code, :percent_off, :valid_until, :max_usages, :active, :created_at +json.extract! coupon, :id, :name, :code, :percent_off, :valid_until, :validity_per_user, :max_usages, :active, :created_at json.usages coupon.invoices.count \ No newline at end of file diff --git a/app/views/api/coupons/validate.json.jbuilder b/app/views/api/coupons/validate.json.jbuilder new file mode 100644 index 000000000..8bbc46ccd --- /dev/null +++ b/app/views/api/coupons/validate.json.jbuilder @@ -0,0 +1 @@ +json.extract! @coupon, :id, :code, :percent_off, :stp_coupon_id \ No newline at end of file diff --git a/app/workers/stripe_worker.rb b/app/workers/stripe_worker.rb index feff2281e..9dc090438 100644 --- a/app/workers/stripe_worker.rb +++ b/app/workers/stripe_worker.rb @@ -14,4 +14,20 @@ class StripeWorker ) user.update_columns(stp_customer_id: customer.id) end + + def create_stripe_coupon(coupon_id) + coupon = Coupon.find(coupon_id) + Stripe::Coupon.create( + id: coupon.code, + duration: coupon.validity_per_user, + percent_off: coupon.percent_off, + redeem_by: coupon.valid_until.to_i, + max_redemptions: coupon.max_usages, + ) + end + + def delete_stripe_coupon(coupon_code) + cpn = Stripe::Coupon.retrieve(coupon_code) + cpn.delete + end end diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index 0fdaafbdd..84e44cfc0 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -161,7 +161,7 @@ en: coupons_new: # ajouter un code promotionnel add_a_coupon: "Add a coupon" - unable_to_create_the_coupon_an_error_occurred: "Unable to create the coupon: an error occurred." + unable_to_create_the_coupon_check_code_already_used: "Unable to create the coupon. Please check that the code is not already used" coupons_edit: # mettre à jour un code promotionnel diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 14b5cc7a3..f41475129 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -161,7 +161,7 @@ fr: coupons_new: # ajouter un code promotionnel add_a_coupon: "Ajouter un code promotionnel" - unable_to_create_the_coupon_an_error_occurred: "Impossible de créer le code promotionnel : une erreur est survenue." + unable_to_create_the_coupon_check_code_already_used: "Impossible de créer le code promotionnel. Vérifiez que le code n'est pas utilisé." coupons_edit: # mettre à jour un code promotionnel diff --git a/config/locales/app.shared.en.yml b/config/locales/app.shared.en.yml index 394235f6c..a5137b029 100644 --- a/config/locales/app.shared.en.yml +++ b/config/locales/app.shared.en.yml @@ -307,6 +307,7 @@ en: private_profile: "Private profile" wallet: + # wallet wallet: 'Wallet' your_wallet_amount: 'Your amount available' wallet_amount: 'Amount available' @@ -333,12 +334,17 @@ en: debit_reservation_event: "Debit by reservation of event" coupon: + # promotional coupon (creation/edition form) code: "Code" code_is_required: "Code is required." code_must_be_composed_of_capital_letters_and_or_digits: "The code must be composed of capital letters and/or digits." percent_off: "Percentage off" percent_off_is_required: "Percentage off is required." percentage_must_be_between_0_and_100: "Percentage must be between 0 and 100." + validity_per_user: "Validity per user" + once: "Once" + forever: "Forever" + validity_per_user_is_required: "Validity per user is required." valid_until: "Valid until (included)" max_usages: "Maximum usages allowed" max_usages_must_be_equal_or_greater_than_0: "The maximum usages allowed must be greater than 0." diff --git a/config/locales/app.shared.fr.yml b/config/locales/app.shared.fr.yml index 6c0ccc02a..15837e6d8 100644 --- a/config/locales/app.shared.fr.yml +++ b/config/locales/app.shared.fr.yml @@ -307,6 +307,7 @@ fr: private_profile: "Profil privé" wallet: + # porte-monnaie wallet: 'Porte-monnaie' your_wallet_amount: 'Votre montant disponible' wallet_amount: 'Montant disponible' @@ -333,12 +334,17 @@ fr: debit_reservation_event: "Payer un reservation d'évenement" coupon: + # code promotionnel (formulaire de création/édition) code: "Code" code_is_required: "Le code est requis." code_must_be_composed_of_capital_letters_and_or_digits: "Le code doit être composé de lettres majuscules et/ou de chiffres." percent_off: "Pourcentage de réduction" percent_off_is_required: "Le pourcentage de réduction est requis." percentage_must_be_between_0_and_100: "Le pourcentage doit être compris entre 0 et 100." + validity_per_user: "Validité par utilisateur" + once: "Une seule fois" + forever: "À chaque utilisation" + validity_per_user_is_required: "La validité par utilisateur est requise." valid_until: "Valable jusqu'au (inclus)" max_usages: "Nombre maximum d'utilisations autorisées" max_usages_must_be_equal_or_greater_than_0: "Le nombre d'utilisations maximum doit être supérieur ou égal à 0." diff --git a/config/routes.rb b/config/routes.rb index 9a112414e..a298accd6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -63,13 +63,15 @@ Rails.application.routes.draw do get '/last_subscribed/:last' => "members#last_subscribed" get '/feeds/twitter_timelines' => "feeds#twitter_timelines" - get 'pricing' => "pricing#index" - put 'pricing' => "pricing#update" + get 'pricing' => 'pricing#index' + put 'pricing' => 'pricing#update' resources :prices, only: [:index, :update] do post 'compute', on: :collection end - resources :coupons + resources :coupons do + post 'validate' => 'coupons#validate' + end resources :trainings_pricings, only: [:index, :update] diff --git a/db/migrate/20160808113850_remove_stp_coupon_id_from_coupons.rb b/db/migrate/20160808113850_remove_stp_coupon_id_from_coupons.rb new file mode 100644 index 000000000..180e49bef --- /dev/null +++ b/db/migrate/20160808113850_remove_stp_coupon_id_from_coupons.rb @@ -0,0 +1,5 @@ +class RemoveStpCouponIdFromCoupons < ActiveRecord::Migration + def change + remove_column :coupons, :stp_coupon_id, :string + end +end diff --git a/db/migrate/20160808113930_add_validity_per_user_to_coupon.rb b/db/migrate/20160808113930_add_validity_per_user_to_coupon.rb new file mode 100644 index 000000000..1172f100c --- /dev/null +++ b/db/migrate/20160808113930_add_validity_per_user_to_coupon.rb @@ -0,0 +1,5 @@ +class AddValidityPerUserToCoupon < ActiveRecord::Migration + def change + add_column :coupons, :validity_per_user, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 31d8da9eb..6f09fd851 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160804073558) do +ActiveRecord::Schema.define(version: 20160808113930) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -111,9 +111,9 @@ ActiveRecord::Schema.define(version: 20160804073558) do t.datetime "valid_until" t.integer "max_usages" t.boolean "active" - t.string "stp_coupon_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "validity_per_user" end create_table "credits", force: :cascade do |t|