mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-28 09:24:24 +01:00
send a coupon to a user
This commit is contained in:
parent
3253290860
commit
428b2db0ea
@ -351,10 +351,26 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state",
|
||||
resolve:
|
||||
coupon: -> coupon
|
||||
size: 'md'
|
||||
controller: ['$scope', '$uibModalInstance', 'Coupon', 'coupon', ($scope, $uibModalInstance, Coupon, coupon) ->
|
||||
controller: ['$scope', '$uibModalInstance', 'Coupon', 'coupon', '_t', ($scope, $uibModalInstance, Coupon, coupon, _t) ->
|
||||
|
||||
## Member, receiver of the coupon
|
||||
$scope.ctrl =
|
||||
member: null
|
||||
|
||||
## Details of the coupon to send
|
||||
$scope.coupon = coupon
|
||||
|
||||
## Callback to validate sending of the coupon
|
||||
$scope.ok = ->
|
||||
$uibModalInstance.close(user)
|
||||
Coupon.send {coupon_code: coupon.code, user_id: $scope.ctrl.member.id}, (res) ->
|
||||
growl.success(_t('coupon_successfully_sent_to_USER', {USER: $scope.ctrl.member.name}))
|
||||
$uibModalInstance.close({user_id: $scope.ctrl.member.id})
|
||||
, (err) ->
|
||||
growl.error(_t('an_error_occurred_unable_to_send_the_coupon'))
|
||||
|
||||
## Callback to close the modal and cancel the sending process
|
||||
$scope.cancel = ->
|
||||
$uibModalInstance.dismiss('cancel')
|
||||
]
|
||||
|
||||
|
||||
|
@ -233,3 +233,28 @@ Application.Filters.filter 'toIsoDate', [ ->
|
||||
moment(date).format('YYYY-MM-DD')
|
||||
|
||||
]
|
||||
|
||||
Application.Filters.filter 'booleanFormat', [ '_t', (_t) ->
|
||||
(boolean) ->
|
||||
if boolean or boolean == 'true'
|
||||
_t('yes')
|
||||
else
|
||||
_t('no')
|
||||
]
|
||||
|
||||
Application.Filters.filter 'booleanFormat', [ '_t', (_t) ->
|
||||
(boolean) ->
|
||||
if (typeof boolean == 'boolean' and boolean) or (typeof boolean == 'string' and boolean == 'true')
|
||||
_t('yes')
|
||||
else
|
||||
_t('no')
|
||||
]
|
||||
|
||||
Application.Filters.filter 'maxCount', [ '_t', (_t) ->
|
||||
(max) ->
|
||||
if typeof max == 'undefined' or max == null or (typeof max == 'number' and max == 0)
|
||||
_t('unlimited')
|
||||
else
|
||||
max
|
||||
]
|
||||
|
||||
|
@ -8,4 +8,7 @@ Application.Services.factory 'Coupon', ["$resource", ($resource)->
|
||||
validate:
|
||||
method: 'POST'
|
||||
url: '/api/coupons/validate'
|
||||
send:
|
||||
method: 'POST'
|
||||
url: '/api/coupons/send'
|
||||
]
|
||||
|
@ -1,31 +1,30 @@
|
||||
<div class="modal-header">
|
||||
<img ng-src="{{logoBlack.custom_asset_file_attributes.attachment_url}}" alt="{{logo.custom_asset_file_attributes.attachment}}" class="modal-logo"/>
|
||||
<h1 translate>{{ 'send_a_coupon' }}</h1>
|
||||
<h3 class="text-center red" translate>{{ 'send_a_coupon' }}</h3>
|
||||
</div>
|
||||
<div class="">
|
||||
|
||||
<div class="well m-b-n">
|
||||
<select-member></select-member>
|
||||
<div class="widget panel b-a m">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 class="panel-title" translate>{{ 'coupon' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th style="width:60%"></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td translate>{{'code'}}</td><td>{{coupon.code}}</td></tr>
|
||||
<tr><td translate>{{'percent_off'}}</td><td>{{coupon.percent_off}} %</td></tr>
|
||||
<tr><td translate>{{'validity_per_user'}}</td><td translate>{{coupon.validity_per_user}}</td></tr>
|
||||
<tr><td translate>{{'valid_until'}}</td><td>{{coupon.valid_until | amDateFormat:'L'}}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<select-member></select-member>
|
||||
<div class="widget panel b-a m">
|
||||
<div class="panel-heading b-b small">
|
||||
<h3 class="panel-title" translate>{{ 'coupon' }}</h3>
|
||||
</div>
|
||||
<div class="widget-content no-bg auto wrapper">
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th style="width:60%"></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td translate>{{'code'}}</td><td>{{coupon.code}}</td></tr>
|
||||
<tr><td translate>{{'percent_off'}}</td><td>{{coupon.percent_off}} %</td></tr>
|
||||
<tr><td translate>{{'validity_per_user'}}</td><td translate>{{coupon.validity_per_user}}</td></tr>
|
||||
<tr><td translate>{{'valid_until'}}</td><td>{{coupon.valid_until | amDateFormat:'L'}}</td></tr>
|
||||
<tr><td translate>{{'usages'}}</td><td>{{coupon.usages}} / {{coupon.max_usages | maxCount}}</td></tr>
|
||||
<tr><td translate>{{'enabled'}}</td><td>{{coupon.active | booleanFormat}}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer no-padder">
|
||||
<button class="btn btn-valid btn-warning btn-block p-l btn-lg text-u-c r-b" ng-click="ok()" translate>{{ 'confirm' }}</button>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-warning" ng-click="ok()" ng-disabled="ctrl.member == null" translate>{{ 'confirm' }}</button>
|
||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||
</div>
|
@ -57,6 +57,21 @@ class API::CouponsController < API::ApiController
|
||||
end
|
||||
end
|
||||
|
||||
def send_to
|
||||
authorize Coupon
|
||||
|
||||
@coupon = Coupon.find_by_code(params[:coupon_code])
|
||||
if @coupon.nil?
|
||||
render json: {error: "no coupon with code #{params[:coupon_code]}"}, status: :not_found
|
||||
else
|
||||
if @coupon.send_to(params[:user_id])
|
||||
render :show, status: :ok, location: @coupon
|
||||
else
|
||||
render json: @coupon.errors, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def set_coupon
|
||||
@coupon = Coupon.find(params[:id])
|
||||
|
@ -58,6 +58,12 @@ class Coupon < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def send_to(user_id)
|
||||
NotificationCenter.call type: 'notify_member_about_coupon',
|
||||
receiver: User.find(user_id),
|
||||
attached_object: self
|
||||
end
|
||||
|
||||
def create_stripe_coupon
|
||||
StripeWorker.perform_async(:create_stripe_coupon, id)
|
||||
end
|
||||
|
@ -40,5 +40,6 @@ class NotificationType
|
||||
notify_user_wallet_is_credited
|
||||
notify_admin_user_wallet_is_credited
|
||||
notify_admin_export_complete
|
||||
notify_member_about_coupon
|
||||
)
|
||||
end
|
||||
|
@ -1,5 +1,5 @@
|
||||
class CouponPolicy < ApplicationPolicy
|
||||
%w(index show create update destroy).each do |action|
|
||||
%w(index show create update destroy send_to).each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.is_admin?
|
||||
end
|
||||
|
@ -0,0 +1,5 @@
|
||||
json.title notification.notification_type
|
||||
json.description t('.enjoy_a_discount_of_PERCENT_with_code_CODE',
|
||||
PERCENT: notification.attached_object.percent_off,
|
||||
CODE: notification.attached_object.code)
|
||||
json.url notification_url(notification, format: :json)
|
@ -0,0 +1,28 @@
|
||||
<%= render 'notifications_mailer/shared/hello', recipient: @recipient %>
|
||||
|
||||
<p><%= t('.body.enjoy_a_discount_of_PERCENT_with_code_CODE',
|
||||
PERCENT: @attached_object.percent_off,
|
||||
CODE: @attached_object.code
|
||||
) %>
|
||||
</p>
|
||||
|
||||
<%
|
||||
# we must tell the use if he could use the code just once or many times (in case we won't specify)
|
||||
usages = 999 # just a number > 1
|
||||
if @attached_object.validity_per_user == 'once'
|
||||
usages = 1
|
||||
else
|
||||
unless @attached_object.max_usages.nil?
|
||||
usages = @attached_object.max_usages
|
||||
end
|
||||
end
|
||||
%>
|
||||
<p>
|
||||
<%= _t('.body.this_coupon_is_valid_USAGE_times_until_DATE_for_all_your_purchases',
|
||||
{
|
||||
USAGE: usages,
|
||||
DATE: @attached_object.valid_until.nil? ? 'NO-DATE' : I18n.l(@attached_object.valid_until.to_date)
|
||||
})
|
||||
# messageFormat
|
||||
%>
|
||||
</p>
|
@ -27,7 +27,7 @@ class StripeWorker
|
||||
end
|
||||
stp_coupon
|
||||
unless coupon.max_usages.nil?
|
||||
stp_coupon[max_redemptions] = coupon.max_usages
|
||||
stp_coupon[:max_redemptions] = coupon.max_usages
|
||||
end
|
||||
|
||||
Stripe::Coupon.create(stp_coupon)
|
||||
|
@ -160,6 +160,9 @@ en:
|
||||
unable_to_delete_the_specified_coupon_an_unexpected_error_occurred: "Unable to delete the specified coupon: an unexpected error occurred."
|
||||
send_a_coupon: "Send a coupon"
|
||||
coupon: "Coupon"
|
||||
usages: "Usages"
|
||||
coupon_successfully_sent_to_USER: "Coupon successfully sent to {{USER}}" # angular interpolation
|
||||
an_error_occurred_unable_to_send_the_coupon: "An unexpected error prevent from sending the coupon."
|
||||
|
||||
coupons_new:
|
||||
# ajouter un code promotionnel
|
||||
|
@ -160,6 +160,9 @@ fr:
|
||||
unable_to_delete_the_specified_coupon_an_unexpected_error_occurred: "Impossible de supprimer le code promotionnel : une erreur inattendue s'est produite."
|
||||
send_a_coupon: "Envoyer un code promo"
|
||||
coupon: "Code promo"
|
||||
usages: "Utilisations"
|
||||
coupon_successfully_sent_to_USER: "Le code promotionnel a bien été envoyé à {{USER}}" # angular interpolation
|
||||
an_error_occurred_unable_to_send_the_coupon: "Une erreur inattendue a empêché l'envoi du code promotionnel."
|
||||
|
||||
coupons_new:
|
||||
# ajouter un code promotionnel
|
||||
|
@ -101,6 +101,7 @@ en:
|
||||
share_on_facebook: "Share on Facebook"
|
||||
share_on_twitter: "Share on Twitter"
|
||||
incomplete_profile: "Incomplete profile"
|
||||
unlimited: "Unlimited"
|
||||
|
||||
messages:
|
||||
you_will_lose_any_unsaved_modification_if_you_quit_this_page: "You will lose any unsaved modification if you quit this page"
|
||||
|
@ -101,6 +101,7 @@ fr:
|
||||
share_on_facebook: "Partager sur Facebook"
|
||||
share_on_twitter: "Partager sur Twitter"
|
||||
incomplete_profile: "Profil incomplet"
|
||||
unlimited: "Illimité"
|
||||
|
||||
messages:
|
||||
you_will_lose_any_unsaved_modification_if_you_quit_this_page: "Vous perdrez les modifications non enregistrées si vous quittez cette page"
|
||||
|
@ -268,6 +268,8 @@ en:
|
||||
users_reservations: "of the reservations' list"
|
||||
is_over: "is over."
|
||||
download_here: "Download here"
|
||||
notify_member_about_coupon:
|
||||
enjoy_a_discount_of_PERCENT_with_code_CODE: "Enjoy a discount of %{PERCENT}% with code %{CODE}"
|
||||
|
||||
statistics:
|
||||
# statistics tools for admins
|
||||
|
@ -268,6 +268,8 @@ fr:
|
||||
users_reservations: "de la liste des réservations"
|
||||
is_over: "est terminé."
|
||||
download_here: "Téléchargez ici"
|
||||
notify_member_about_coupon:
|
||||
enjoy_a_discount_of_PERCENT_with_code_CODE: "Bénéficiez d'une remise de %{PERCENT} % avec le code %{CODE}"
|
||||
|
||||
statistics:
|
||||
# outil de statistiques pour les administrateurs
|
||||
|
@ -268,5 +268,11 @@ en:
|
||||
click_to_download: "Excel file generated successfully. To download it, click"
|
||||
here: "here"
|
||||
|
||||
notify_member_about_coupon:
|
||||
subject: "Coupon"
|
||||
body:
|
||||
enjoy_a_discount_of_PERCENT_with_code_CODE: "Enjoy a discount of %{PERCENT}% on the whole site with the code %{CODE}."
|
||||
this_coupon_is_valid_USAGE_times_until_DATE_for_all_your_purchases: "This coupon is valid {USAGE, plural, =1{just once} other{many times}}: for all your purchases, from now {DATE, select, NO-DATE{and without time limit} other{and until {DATE}}}."
|
||||
|
||||
shared:
|
||||
hello: "Hello %{user_name}"
|
||||
|
@ -268,5 +268,11 @@ fr:
|
||||
click_to_download: "La génération est terminée. Pour télécharger le fichier Excel, cliquez"
|
||||
here: "ici"
|
||||
|
||||
notify_member_about_coupon:
|
||||
subject: "Code promo"
|
||||
body:
|
||||
enjoy_a_discount_of_PERCENT_with_code_CODE: "Bénéficiez d'une remise de %{PERCENT} % sur tout le site en utilisant le code promo %{CODE}."
|
||||
this_coupon_is_valid_USAGE_times_until_DATE_for_all_your_purchases: "Ce code promo est valable {USAGE, plural, =1{une seule fois} other{plusieurs fois}} : pour tous vos achats, dès maintenant {DATE, select, NO-DATE{et sans limitation de durée} other{et jusqu'au {DATE}}}."
|
||||
|
||||
shared:
|
||||
hello: "Bonjour %{user_name}"
|
||||
|
@ -71,6 +71,7 @@ Rails.application.routes.draw do
|
||||
end
|
||||
resources :coupons
|
||||
post 'coupons/validate' => 'coupons#validate'
|
||||
post 'coupons/send' => 'coupons#send_to'
|
||||
|
||||
resources :trainings_pricings, only: [:index, :update]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user