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|