1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

create/delete coupons on stripe + adjust schema to match stripe requirements

This commit is contained in:
Sylvain 2016-08-08 14:42:17 +02:00
parent 35b324e108
commit a6ded12ee9
15 changed files with 107 additions and 12 deletions

View File

@ -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

View File

@ -36,6 +36,20 @@
<span class="help-block error" ng-show="couponForm['coupon[percent_off]'].$dirty && (couponForm['coupon[percent_off]'].$error.min || couponForm['coupon[percent_off]'].$error.max)" translate>{{ 'percentage_must_be_between_0_and_100' }}</span>
</div>
<div class="form-group" ng-class="{'has-error': couponForm['coupon[validity_per_user]'].$dirty && couponForm['coupon[validity_per_user]'].$invalid}">
<label for="coupon[validity_per_user]">{{ 'validity_per_user' | translate }} *</label>
<select id="coupon[validity_per_user]"
name="coupon[validity_per_user]"
class="form-control"
ng-model="coupon.validity_per_user"
required="required"
ng-disabled="method == 'PATCH'"
ng-options="( validity | translate ) for validity in validities"
required>
</select>
<span class="help-block error" ng-show="couponForm['coupon[validity_per_user]'].$dirty && couponForm['coupon[validity_per_user]'].$error.required" translate>{{ 'validity_per_user_is_required' }}</span>
</div>
<div class="form-group">
<label for="coupon[valid_until]" translate>{{ 'valid_until' }}</label>
<div class="input-group">

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
json.extract! @coupon, :id, :code, :percent_off, :stp_coupon_id

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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."

View File

@ -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."

View File

@ -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]

View File

@ -0,0 +1,5 @@
class RemoveStpCouponIdFromCoupons < ActiveRecord::Migration
def change
remove_column :coupons, :stp_coupon_id, :string
end
end

View File

@ -0,0 +1,5 @@
class AddValidityPerUserToCoupon < ActiveRecord::Migration
def change
add_column :coupons, :validity_per_user, :string
end
end

View File

@ -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|