workarea-gift_cards 3.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.editorconfig +20 -0
- data/.eslintignore +2 -0
- data/.eslintrc +24 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +15 -0
- data/.scss-lint.yml +188 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +485 -0
- data/CODE_OF_CONDUCT.md +3 -0
- data/CONTRIBUTING.md +3 -0
- data/Gemfile +7 -0
- data/LICENSE +52 -0
- data/README.md +119 -0
- data/Rakefile +53 -0
- data/app/assets/images/workarea/admin/payment_icons/gift_card.svg +1 -0
- data/app/assets/images/workarea/storefront/payment_icons/gift_card.svg +1 -0
- data/app/controllers/workarea/admin/data_file_exports_controller.decorator +28 -0
- data/app/controllers/workarea/admin/payment_gift_cards_controller.rb +78 -0
- data/app/controllers/workarea/api/admin/payment_gift_cards_controller.rb +49 -0
- data/app/controllers/workarea/api/storefront/checkouts_controller.decorator +10 -0
- data/app/controllers/workarea/api/storefront/gift_cards_controller.rb +26 -0
- data/app/controllers/workarea/storefront/checkouts_controller.decorator +24 -0
- data/app/controllers/workarea/storefront/gift_cards_controller.rb +24 -0
- data/app/mailers/workarea/storefront/gift_card_mailer.rb +28 -0
- data/app/models/workarea/catalog/customizations/gift_card.rb +9 -0
- data/app/models/workarea/catalog/product.decorator +11 -0
- data/app/models/workarea/order/item.decorator +7 -0
- data/app/models/workarea/payment/authorize/gift_card.rb +43 -0
- data/app/models/workarea/payment/capture/gift_card.rb +25 -0
- data/app/models/workarea/payment/gift_card/redemption.rb +23 -0
- data/app/models/workarea/payment/gift_card.rb +186 -0
- data/app/models/workarea/payment/purchase/gift_card.rb +7 -0
- data/app/models/workarea/payment/refund/gift_card.rb +35 -0
- data/app/models/workarea/payment/tender/gift_card.rb +30 -0
- data/app/models/workarea/payment.decorator +19 -0
- data/app/models/workarea/search/admin/order.decorator +9 -0
- data/app/models/workarea/search/admin/payment_gift_card.rb +46 -0
- data/app/queries/workarea/admin_redemptions_export.rb +84 -0
- data/app/queries/workarea/order_item_details.decorator +11 -0
- data/app/queries/workarea/search/admin_gift_cards.rb +20 -0
- data/app/seeds/workarea/gift_card_seeds.rb +44 -0
- data/app/services/workarea/checkout/steps/gift_card.rb +49 -0
- data/app/view_models/workarea/admin/payment_gift_card_view_model.rb +11 -0
- data/app/view_models/workarea/storefront/checkout/payment_view_model.decorator +32 -0
- data/app/view_models/workarea/storefront/checkout/summary_view_model.decorator +11 -0
- data/app/view_models/workarea/storefront/gift_card_order_pricing.rb +36 -0
- data/app/view_models/workarea/storefront/order_view_model.decorator +27 -0
- data/app/view_models/workarea/storefront/product_templates/gift_card_view_model.rb +4 -0
- data/app/views/workarea/admin/activities/_payment_gift_card_create.html.haml +12 -0
- data/app/views/workarea/admin/activities/_payment_gift_card_destroy.html.haml +10 -0
- data/app/views/workarea/admin/activities/_payment_gift_card_update.html.haml +14 -0
- data/app/views/workarea/admin/orders/tenders/_gift_card.html.haml +5 -0
- data/app/views/workarea/admin/payment_gift_cards/_aux_navigation.html.haml +4 -0
- data/app/views/workarea/admin/payment_gift_cards/_cards.html.haml +74 -0
- data/app/views/workarea/admin/payment_gift_cards/_menu.html.haml +1 -0
- data/app/views/workarea/admin/payment_gift_cards/_summary.html.haml +11 -0
- data/app/views/workarea/admin/payment_gift_cards/edit.html.haml +37 -0
- data/app/views/workarea/admin/payment_gift_cards/index.html.haml +95 -0
- data/app/views/workarea/admin/payment_gift_cards/new.html.haml +43 -0
- data/app/views/workarea/admin/payment_gift_cards/redemptions.html.haml +29 -0
- data/app/views/workarea/admin/payment_gift_cards/show.html.haml +19 -0
- data/app/views/workarea/api/storefront/checkouts/steps/_gift_card.json.jbuilder +6 -0
- data/app/views/workarea/api/storefront/gift_cards/balance.json.jbuilder +3 -0
- data/app/views/workarea/api/storefront/orders/tenders/_gift_card.json.jbuilder +3 -0
- data/app/views/workarea/storefront/checkouts/_gift_card_error.html.haml +6 -0
- data/app/views/workarea/storefront/checkouts/_gift_card_payment.html.haml +28 -0
- data/app/views/workarea/storefront/checkouts/_gift_card_summary.html.haml +6 -0
- data/app/views/workarea/storefront/gift_card_mailer/created.html.haml +15 -0
- data/app/views/workarea/storefront/gift_cards/index.html.haml +17 -0
- data/app/views/workarea/storefront/order_mailer/_gift_card_summary.html.haml +5 -0
- data/app/views/workarea/storefront/order_mailer/tenders/_gift_card.html.haml +5 -0
- data/app/views/workarea/storefront/orders/_gift_card_summary.html.haml +6 -0
- data/app/views/workarea/storefront/orders/tenders/_gift_card.html.haml +9 -0
- data/app/views/workarea/storefront/products/templates/_gift_card.html.haml +77 -0
- data/app/workers/workarea/create_ordered_gift_cards.rb +47 -0
- data/app/workers/workarea/log_gift_card_redemption.rb +32 -0
- data/app/workers/workarea/send_gift_card_notifications.rb +20 -0
- data/bin/rails +18 -0
- data/config/initializers/append_points.rb +37 -0
- data/config/initializers/configuration.rb +8 -0
- data/config/initializers/jump_to_navigation.rb +3 -0
- data/config/locales/en.yml +82 -0
- data/config/routes.rb +31 -0
- data/lib/workarea/gift_cards/engine.rb +19 -0
- data/lib/workarea/gift_cards/version.rb +5 -0
- data/lib/workarea/gift_cards.rb +11 -0
- data/lib/workarea/mailer_previews/storefront/gift_card_mailer_preview.rb +18 -0
- data/test/documentation/workarea/api/admin/gift_cards_documentation_test.rb +82 -0
- data/test/documentation/workarea/api/storefront/gift_cards_documentation_test.rb +107 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/jobs/application_job.rb +2 -0
- data/test/dummy/app/mailers/application_mailer.rb +4 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
- data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +34 -0
- data/test/dummy/bin/update +29 -0
- data/test/dummy/config/application.rb +24 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/cable.yml +9 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +54 -0
- data/test/dummy/config/environments/production.rb +86 -0
- data/test/dummy/config/environments/test.rb +43 -0
- data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/workarea.rb +5 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/puma.rb +47 -0
- data/test/dummy/config/routes.rb +6 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config/spring.rb +6 -0
- data/test/dummy/config.ru +5 -0
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/test/dummy/public/apple-touch-icon.png +0 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/factories/gift_cards.rb +27 -0
- data/test/integration/workarea/admin/gift_card_integration_test.rb +53 -0
- data/test/integration/workarea/admin/gift_card_redemptions_export_integration_test.rb +104 -0
- data/test/integration/workarea/api/admin/gift_card_integration_test.rb +57 -0
- data/test/integration/workarea/api/storefront/balance_integration_test.rb +40 -0
- data/test/integration/workarea/api/storefront/checkout_integration_test.rb +161 -0
- data/test/integration/workarea/storefront/gift_card_integration_test.rb +222 -0
- data/test/models/workarea/catalog/gift_card_product_test.rb +15 -0
- data/test/models/workarea/gift_card_payment_test.rb +12 -0
- data/test/models/workarea/payment/gift_card_test.rb +127 -0
- data/test/models/workarea/payment/purchase/gift_card_test.rb +52 -0
- data/test/models/workarea/payment/refund/gift_card_test.rb +19 -0
- data/test/queries/workarea/admin_redemptions_export_test.rb +52 -0
- data/test/queries/workarea/gift_card_order_item_details_test.rb +11 -0
- data/test/services/workarea/checkout/steps/gift_card_test.rb +87 -0
- data/test/system/workarea/admin/gift_cards_system_test.rb +89 -0
- data/test/system/workarea/storefront/gift_cards_system_test.rb +400 -0
- data/test/test_helper.rb +10 -0
- data/test/view_models/workarea/storefront/checkout/gift_card_payment_view_model_test.rb +65 -0
- data/test/workers/workarea/create_ordered_gift_cards_test.rb +39 -0
- data/test/workers/workarea/log_gift_card_redemption_test.rb +19 -0
- data/workarea-gift_cards.gemspec +21 -0
- metadata +227 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
begin
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
rescue LoadError
|
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
require 'rdoc/task'
|
|
9
|
+
|
|
10
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
11
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
12
|
+
rdoc.title = 'Tasker'
|
|
13
|
+
rdoc.options << '--line-numbers'
|
|
14
|
+
rdoc.rdoc_files.include('README.md')
|
|
15
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
APP_RAKEFILE = File.expand_path('../test/dummy/Rakefile', __FILE__)
|
|
19
|
+
load 'rails/tasks/engine.rake'
|
|
20
|
+
load 'rails/tasks/statistics.rake'
|
|
21
|
+
load 'workarea/changelog.rake'
|
|
22
|
+
|
|
23
|
+
require 'rake/testtask'
|
|
24
|
+
|
|
25
|
+
Rake::TestTask.new(:test) do |t|
|
|
26
|
+
t.libs << 'lib'
|
|
27
|
+
t.libs << 'test'
|
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
|
29
|
+
t.verbose = false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
task default: :test
|
|
33
|
+
|
|
34
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
|
35
|
+
require 'workarea/gift_cards/version'
|
|
36
|
+
|
|
37
|
+
desc "Release version #{Workarea::GiftCards::VERSION} of the gem"
|
|
38
|
+
task :release do
|
|
39
|
+
host = "https://#{ENV['BUNDLE_GEMS__WEBLINC__COM']}@gems.weblinc.com"
|
|
40
|
+
|
|
41
|
+
#Rake::Task['workarea:changelog'].execute
|
|
42
|
+
#system 'git add CHANGELOG.md'
|
|
43
|
+
#system 'git commit -m "Update CHANGELOG"'
|
|
44
|
+
#system 'git push origin HEAD'
|
|
45
|
+
|
|
46
|
+
system "git tag -a v#{Workarea::GiftCards::VERSION} -m 'Tagging #{Workarea::GiftCards::VERSION}'"
|
|
47
|
+
system 'git push --tags'
|
|
48
|
+
|
|
49
|
+
system 'gem build workarea-gift_cards.gemspec'
|
|
50
|
+
system "gem push workarea-gift_cards-#{Workarea::GiftCards::VERSION}.gem"
|
|
51
|
+
system "gem push workarea-gift_cards-#{Workarea::GiftCards::VERSION}.gem --host #{host}"
|
|
52
|
+
system "rm workarea-gift_cards-#{Workarea::GiftCards::VERSION}.gem"
|
|
53
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-243 353.9 125 85.3" enable-background="new -243 353.9 125 85.3"><path d="m-229.7 402h-13.3v-37.6c0-5.8 4.7-10.5 10.5-10.5h24v34c-.2-.2-.3-.4-.5-.6-6.4-6.5-15.6-7.7-20.6-2.7-4.3 4.1-4.1 11.3-.1 17.4m9.8 29.9l-10.9-11.5 5.1-4.6h-17.4v12.9c0 5.8 4.7 10.5 10.5 10.5h24v-17.9l-11.3 10.6zm26.3-44.6c6.4-6.5 15.6-7.7 20.6-2.7 4.2 4.2 4.1 11.4.1 17.4h54.9v-37.6c0-5.8-4.7-10.5-10.5-10.5h-65.6v34c.2-.3.3-.4.5-.6m21.7 33.7l-11.5 10.9-10.7-11.3v18.6h65.6c5.8 0 10.5-4.7 10.5-10.5v-12.9h-59.1l5.2 5.2zm-18.5-28.1c-3.3 3.3-3.9 13.2-3.9 13.2s9.9-.7 13.2-4c3.3-3.3 3.9-8 1.3-10.6-2.6-2.5-7.3-1.9-10.6 1.4m-32.4-1.4c-2.6 2.5-2 7.3 1.3 10.6 3.3 3.3 13.2 4 13.2 4s-.6-9.9-3.9-13.2c-3.3-3.3-8-3.9-10.6-1.4"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-243 353.9 125 85.3" enable-background="new -243 353.9 125 85.3"><path d="m-229.7 402h-13.3v-37.6c0-5.8 4.7-10.5 10.5-10.5h24v34c-.2-.2-.3-.4-.5-.6-6.4-6.5-15.6-7.7-20.6-2.7-4.3 4.1-4.1 11.3-.1 17.4m9.8 29.9l-10.9-11.5 5.1-4.6h-17.4v12.9c0 5.8 4.7 10.5 10.5 10.5h24v-17.9l-11.3 10.6zm26.3-44.6c6.4-6.5 15.6-7.7 20.6-2.7 4.2 4.2 4.1 11.4.1 17.4h54.9v-37.6c0-5.8-4.7-10.5-10.5-10.5h-65.6v34c.2-.3.3-.4.5-.6m21.7 33.7l-11.5 10.9-10.7-11.3v18.6h65.6c5.8 0 10.5-4.7 10.5-10.5v-12.9h-59.1l5.2 5.2zm-18.5-28.1c-3.3 3.3-3.9 13.2-3.9 13.2s9.9-.7 13.2-4c3.3-3.3 3.9-8 1.3-10.6-2.6-2.5-7.3-1.9-10.6 1.4m-32.4-1.4c-2.6 2.5-2 7.3 1.3 10.6 3.3 3.3 13.2 4 13.2 4s-.6-9.9-3.9-13.2c-3.3-3.3-8-3.9-10.6-1.4"/></svg>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
decorate Admin::DataFileExportsController, with: 'gift_cards' do
|
|
3
|
+
def set_export
|
|
4
|
+
super
|
|
5
|
+
|
|
6
|
+
if @export.model_class == Workarea::Payment::GiftCard::Redemption
|
|
7
|
+
convert_export_ids_to_query if @export.ids.present?
|
|
8
|
+
convert_query_to_redemptions_query
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def convert_export_ids_to_query
|
|
13
|
+
tokens = GlobalID::Locator.locate_many(@export.ids).map(&:token)
|
|
14
|
+
@export.query_id = Search::AdminGiftCards.new(q: tokens.join(' ')).to_gid_param
|
|
15
|
+
@export.ids = []
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def convert_query_to_redemptions_query
|
|
19
|
+
current_query = GlobalID.find(@export.query_id)
|
|
20
|
+
|
|
21
|
+
unless current_query.blank? || current_query.is_a?(AdminRedemptionsExport)
|
|
22
|
+
@export.query_id = AdminRedemptionsExport
|
|
23
|
+
.new(gift_cards_query_id: @export.query_id)
|
|
24
|
+
.to_gid_param
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
module Admin
|
|
3
|
+
class PaymentGiftCardsController < Admin::ApplicationController
|
|
4
|
+
required_permissions :orders
|
|
5
|
+
before_action :find_gift_card, except: :index
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
search = Search::AdminGiftCards.new(params)
|
|
9
|
+
@search = Admin::SearchViewModel.new(search, view_model_options)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def show; end
|
|
13
|
+
|
|
14
|
+
def new; end
|
|
15
|
+
|
|
16
|
+
def create
|
|
17
|
+
if @gift_card.save
|
|
18
|
+
flash[:success] = 'Gift card has been created.'
|
|
19
|
+
redirect_to payment_gift_card_path(@gift_card)
|
|
20
|
+
else
|
|
21
|
+
render :new
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def edit; end
|
|
26
|
+
|
|
27
|
+
def update
|
|
28
|
+
if @gift_card.update_attributes(gift_card_params)
|
|
29
|
+
flash[:success] = 'Gift card has been saved.'
|
|
30
|
+
redirect_to payment_gift_card_path(@gift_card)
|
|
31
|
+
else
|
|
32
|
+
render :edit
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def destroy
|
|
37
|
+
@gift_card.destroy
|
|
38
|
+
flash[:success] = "Gift card #{@gift_card.token} has been removed."
|
|
39
|
+
redirect_to payment_gift_cards_path
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def redemptions
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def find_gift_card
|
|
48
|
+
gift_card =
|
|
49
|
+
if params[:id].present?
|
|
50
|
+
Payment::GiftCard.find(params[:id])
|
|
51
|
+
elsif params[:payment_gift_card_id].present?
|
|
52
|
+
Payment::GiftCard.find(params[:payment_gift_card_id])
|
|
53
|
+
else
|
|
54
|
+
Payment::GiftCard.new(gift_card_params)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
@gift_card =
|
|
58
|
+
Admin::PaymentGiftCardViewModel.new(
|
|
59
|
+
gift_card,
|
|
60
|
+
view_model_options
|
|
61
|
+
)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def gift_card_params
|
|
65
|
+
return {} if params[:gift_card].blank?
|
|
66
|
+
params[:gift_card].permit(
|
|
67
|
+
:token,
|
|
68
|
+
:to,
|
|
69
|
+
:from,
|
|
70
|
+
:message,
|
|
71
|
+
:expires_at,
|
|
72
|
+
:amount,
|
|
73
|
+
:notify
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
if Plugin.installed?(:api)
|
|
3
|
+
module Api
|
|
4
|
+
module Admin
|
|
5
|
+
class PaymentGiftCardsController < Admin::ApplicationController
|
|
6
|
+
before_action :find_gift_card, except: [:index, :create]
|
|
7
|
+
|
|
8
|
+
def index
|
|
9
|
+
@gift_cards = Payment::GiftCard
|
|
10
|
+
.all
|
|
11
|
+
.order_by(sort_field => sort_direction)
|
|
12
|
+
.page(params[:page])
|
|
13
|
+
|
|
14
|
+
respond_with gift_cards: @gift_cards
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def show
|
|
18
|
+
respond_with gift_card: @gift_card
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def update
|
|
22
|
+
@gift_card.update_attributes!(params[:gift_card])
|
|
23
|
+
respond_with gift_card: @gift_card
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def create
|
|
27
|
+
@gift_card = Payment::GiftCard.create!(params[:gift_card])
|
|
28
|
+
respond_with(
|
|
29
|
+
{ gift_card: @gift_card },
|
|
30
|
+
{ status: :created,
|
|
31
|
+
location: payment_gift_card_path(@gift_card) }
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def destroy
|
|
36
|
+
@gift_card.destroy
|
|
37
|
+
head :no_content
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def find_gift_card
|
|
43
|
+
@gift_card = Payment::GiftCard.find(params[:id])
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
if Plugin.installed?(:api)
|
|
3
|
+
module Api
|
|
4
|
+
module Storefront
|
|
5
|
+
class GiftCardsController < Api::Storefront::ApplicationController
|
|
6
|
+
def balance
|
|
7
|
+
email = params.fetch(:email, nil)
|
|
8
|
+
token = params.fetch(:token, nil)
|
|
9
|
+
|
|
10
|
+
if email.present? && token.present?
|
|
11
|
+
@gift_card = Payment::GiftCard.find_by_token_and_email(token, email)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
if @gift_card.blank?
|
|
15
|
+
raise Mongoid::Errors::DocumentNotFound.new(
|
|
16
|
+
Payment::GiftCard,
|
|
17
|
+
email: email,
|
|
18
|
+
token: token
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
decorate Storefront::CheckoutsController, with: 'gift_cards' do
|
|
3
|
+
def add_gift_card
|
|
4
|
+
step = Checkout::Steps::GiftCard.new(current_checkout)
|
|
5
|
+
|
|
6
|
+
if step.update(params)
|
|
7
|
+
flash[:success] = 'Your gift card has been applied.'
|
|
8
|
+
redirect_to checkout_payment_path
|
|
9
|
+
else
|
|
10
|
+
flash[:error] = <<-string
|
|
11
|
+
We couldn't add this gift card number.
|
|
12
|
+
Please ensure you have entered the correct number.
|
|
13
|
+
string
|
|
14
|
+
|
|
15
|
+
@step = Storefront::Checkout::PaymentViewModel.new(
|
|
16
|
+
step,
|
|
17
|
+
view_model_options
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
render :payment
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
class Storefront::GiftCardsController < Storefront::ApplicationController
|
|
3
|
+
def index
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def lookup
|
|
7
|
+
email = params.fetch(:email, nil)
|
|
8
|
+
token = params.fetch(:token, nil)
|
|
9
|
+
|
|
10
|
+
if email.present? && token.present?
|
|
11
|
+
@gift_card = Workarea::Payment::GiftCard
|
|
12
|
+
.find_by_token_and_email(token, email)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
if @gift_card.present?
|
|
16
|
+
flash[:success] = "Your balance is #{@gift_card.balance.format}"
|
|
17
|
+
else
|
|
18
|
+
flash[:error] = 'Invalid card number or email.'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
redirect_to gift_cards_balance_path
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
module Storefront
|
|
3
|
+
class GiftCardMailer < Storefront::ApplicationMailer
|
|
4
|
+
def created(card_id)
|
|
5
|
+
@card = Payment::GiftCard.find(card_id)
|
|
6
|
+
@from = from(@card.from, @card.order_id)
|
|
7
|
+
|
|
8
|
+
mail(
|
|
9
|
+
to: @card.to,
|
|
10
|
+
from: Workarea.config.email_from,
|
|
11
|
+
subject: t('workarea.storefront.email.gift_card_created.subject')
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def from(card_from, order_id)
|
|
18
|
+
card_from || card_order_email(order_id) || Workarea.config.email_from
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def card_order_email(order_id)
|
|
22
|
+
return unless order_id.present?
|
|
23
|
+
order = Order.find(order_id)
|
|
24
|
+
order.email
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
class Workarea::Catalog::Customizations::GiftCard < Workarea::Catalog::Customizations
|
|
2
|
+
customized_fields :email, :from, :message
|
|
3
|
+
|
|
4
|
+
validates :email, presence: true,
|
|
5
|
+
email: true
|
|
6
|
+
|
|
7
|
+
validates :from, length: { maximum: 100 }
|
|
8
|
+
validates :message, length: { maximum: 500 }
|
|
9
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
class Payment
|
|
3
|
+
module Authorize
|
|
4
|
+
class GiftCard
|
|
5
|
+
include OperationImplementation
|
|
6
|
+
|
|
7
|
+
def complete!
|
|
8
|
+
Payment::GiftCard.purchase(tender.number, transaction.amount.cents)
|
|
9
|
+
|
|
10
|
+
transaction.response = ActiveMerchant::Billing::Response.new(
|
|
11
|
+
true,
|
|
12
|
+
I18n.t(
|
|
13
|
+
'workarea.gift_cards.debit',
|
|
14
|
+
amount: transaction.amount,
|
|
15
|
+
number: tender.number
|
|
16
|
+
)
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
rescue Payment::InsufficientFunds
|
|
20
|
+
transaction.response = ActiveMerchant::Billing::Response.new(
|
|
21
|
+
false,
|
|
22
|
+
I18n.t('workarea.gift_cards.insufficient_funds')
|
|
23
|
+
)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def cancel!
|
|
27
|
+
return unless transaction.success?
|
|
28
|
+
|
|
29
|
+
Payment::GiftCard.refund(tender.number, transaction.amount.cents)
|
|
30
|
+
|
|
31
|
+
transaction.cancellation = ActiveMerchant::Billing::Response.new(
|
|
32
|
+
true,
|
|
33
|
+
I18n.t(
|
|
34
|
+
'workarea.gift_cards.credit',
|
|
35
|
+
amount: transaction.amount,
|
|
36
|
+
number: tender.number
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
class Payment
|
|
3
|
+
class Capture
|
|
4
|
+
class GiftCard
|
|
5
|
+
include OperationImplementation
|
|
6
|
+
|
|
7
|
+
def complete!
|
|
8
|
+
# noop, authorization does the capture
|
|
9
|
+
transaction.response = ActiveMerchant::Billing::Response.new(
|
|
10
|
+
true,
|
|
11
|
+
I18n.t('workarea.gift_cards.capture')
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def cancel!
|
|
16
|
+
# noop, nothing to cancel
|
|
17
|
+
transaction.response = ActiveMerchant::Billing::Response.new(
|
|
18
|
+
true,
|
|
19
|
+
I18n.t('workarea.gift_cards.capture')
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
class Payment
|
|
3
|
+
class GiftCard
|
|
4
|
+
class Redemption
|
|
5
|
+
include ApplicationDocument
|
|
6
|
+
|
|
7
|
+
field :redeemed_at, type: DateTime
|
|
8
|
+
field :order_id, type: String
|
|
9
|
+
|
|
10
|
+
field :amount, type: Money
|
|
11
|
+
|
|
12
|
+
belongs_to :gift_card, class_name: 'Workarea::Payment::GiftCard'
|
|
13
|
+
|
|
14
|
+
validates_presence_of :amount
|
|
15
|
+
validates_presence_of :redeemed_at
|
|
16
|
+
|
|
17
|
+
index(redeemed_at: 1)
|
|
18
|
+
index(order_id: 1)
|
|
19
|
+
index(gift_card_id: 1)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
class Payment
|
|
3
|
+
class GiftCard
|
|
4
|
+
include ApplicationDocument
|
|
5
|
+
include Commentable
|
|
6
|
+
|
|
7
|
+
field :token, type: String
|
|
8
|
+
field :to, type: String
|
|
9
|
+
field :from, type: String
|
|
10
|
+
field :message, type: String
|
|
11
|
+
field :expires_at, type: DateTime
|
|
12
|
+
field :notify, type: Boolean
|
|
13
|
+
field :purchased, type: Boolean
|
|
14
|
+
|
|
15
|
+
# Order id if this card was created
|
|
16
|
+
# by a customer purchasing it.
|
|
17
|
+
field :order_id, type: String
|
|
18
|
+
|
|
19
|
+
field :amount, type: Money, default: 0.to_m
|
|
20
|
+
field :used, type: Money, default: 0.to_m
|
|
21
|
+
field :balance, type: Money, default: 0.to_m
|
|
22
|
+
|
|
23
|
+
has_many :redemptions, class_name: 'Workarea::Payment::GiftCard::Redemption'
|
|
24
|
+
|
|
25
|
+
index({ token: 1 }, { unique: true })
|
|
26
|
+
index(to: 1)
|
|
27
|
+
index('balance.cents' => 1)
|
|
28
|
+
index(expires_at: 1)
|
|
29
|
+
index(created_at: 1)
|
|
30
|
+
|
|
31
|
+
alias number token
|
|
32
|
+
|
|
33
|
+
validates :token, presence: true
|
|
34
|
+
validates :amount, presence: true
|
|
35
|
+
validates :to, email: true
|
|
36
|
+
|
|
37
|
+
scope :not_expired, -> {
|
|
38
|
+
any_of({ :expires_at.exists => false },
|
|
39
|
+
{ expires_at: nil },
|
|
40
|
+
{ :expires_at.gte => Time.now })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
before_validation :assign_token
|
|
44
|
+
|
|
45
|
+
# Sorts available for this class.
|
|
46
|
+
#
|
|
47
|
+
# @return [Array<Workarea::Sort>]
|
|
48
|
+
#
|
|
49
|
+
def self.sorts
|
|
50
|
+
[Workarea::Sort.newest, Workarea::Sort.modified]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Find gift cards whose token or recipient matches the
|
|
54
|
+
# given string. Used in admin filtering.
|
|
55
|
+
#
|
|
56
|
+
# @param [String]
|
|
57
|
+
# @return [Mongoid::Criteria]
|
|
58
|
+
#
|
|
59
|
+
def self.search_by_token_or_recipient(string)
|
|
60
|
+
regex = /^#{::Regexp.quote(string)}/i
|
|
61
|
+
any_of({ token: regex }, { to: regex })
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Performs purchase of the gift card that matches the given token.
|
|
65
|
+
# Purchase is for the amount in cents.
|
|
66
|
+
#
|
|
67
|
+
# @param [String] token Representing Payment::GiftCard#token
|
|
68
|
+
# @param [Integer] cents Amount of purchase
|
|
69
|
+
# @return [Payment::GiftCard]
|
|
70
|
+
#
|
|
71
|
+
def self.purchase(token, cents)
|
|
72
|
+
not_expired.find_by_token(token).purchase(cents)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Performs refund of the gift card that matches the given token.
|
|
76
|
+
# Refund is for the amount in cents.
|
|
77
|
+
#
|
|
78
|
+
# @param [String] token Representing Payment::GiftCard#token
|
|
79
|
+
# @param [Integer] cents Amount to refund
|
|
80
|
+
# @return [Payment::GiftCard]
|
|
81
|
+
#
|
|
82
|
+
def self.refund(token, cents)
|
|
83
|
+
find_by_token(token).refund(cents)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Gift card balance for the given token. If the Gift card does
|
|
87
|
+
# not exist, $0 is returned.
|
|
88
|
+
#
|
|
89
|
+
# @param [String] token Representing Payment::GiftCard#token
|
|
90
|
+
# @return [Money]
|
|
91
|
+
#
|
|
92
|
+
def self.find_balance(token)
|
|
93
|
+
card = not_expired.find_by_token(token)
|
|
94
|
+
card ? card.balance : 0.to_m
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.find_by_token(token)
|
|
98
|
+
where(token: token.downcase).first
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def self.find_by_token_and_email(token, email)
|
|
102
|
+
where(token: token, to: email.downcase).not_expired.first
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def to=(val)
|
|
106
|
+
if val.nil?
|
|
107
|
+
super(val)
|
|
108
|
+
else
|
|
109
|
+
super(val.to_s.downcase)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def valid?(*)
|
|
114
|
+
super.tap do |result|
|
|
115
|
+
self.balance = amount if result && !persisted?
|
|
116
|
+
self.token = token.downcase if token.present?
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# This is for compatibility with the admin, all models must implement this
|
|
121
|
+
#
|
|
122
|
+
# @return [String]
|
|
123
|
+
#
|
|
124
|
+
def name
|
|
125
|
+
I18n.t('workarea.payment_gift_card.name', token: token)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Whether the gift card has expired.
|
|
129
|
+
#
|
|
130
|
+
# @return [Boolean]
|
|
131
|
+
#
|
|
132
|
+
def expired?
|
|
133
|
+
!!(expires_at && Time.now >= expires_at)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# The date of the last redemption.
|
|
137
|
+
#
|
|
138
|
+
# @return [DateTime]
|
|
139
|
+
#
|
|
140
|
+
def last_redeemed_at
|
|
141
|
+
redemptions.asc(:redeemed_at).last.try(:redeemed_at)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Performs purchase for the amount in cents.
|
|
145
|
+
#
|
|
146
|
+
# @param [Integer] cents Amount of purchase
|
|
147
|
+
# @return [Payment::GiftCard]
|
|
148
|
+
#
|
|
149
|
+
# @raise [Payment::InsufficientFunds]
|
|
150
|
+
# the balance of the gift card does not cover the cents
|
|
151
|
+
#
|
|
152
|
+
def purchase(cents)
|
|
153
|
+
raise(Workarea::Payment::InsufficientFunds) if balance.cents < cents
|
|
154
|
+
inc('balance.cents' => 0 - cents, 'used.cents' => cents)
|
|
155
|
+
self
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Performs refund for the amount in cents.
|
|
159
|
+
#
|
|
160
|
+
# @param [Integer] cents Amount of purchase
|
|
161
|
+
# @return [Payment::GiftCard]
|
|
162
|
+
#
|
|
163
|
+
def refund(cents)
|
|
164
|
+
inc('balance.cents' => cents, 'used.cents' => 0 - cents)
|
|
165
|
+
self
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def reset_token!
|
|
169
|
+
update_attribute(:token, generate_token)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def generate_token
|
|
173
|
+
loop do
|
|
174
|
+
tmp = SecureRandom.hex(Workarea.config.gift_card_token_length / 2).downcase
|
|
175
|
+
break tmp unless self.class.where(token: tmp).exists?
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
private
|
|
180
|
+
|
|
181
|
+
def assign_token
|
|
182
|
+
self.token = generate_token if token.blank?
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Workarea
|
|
2
|
+
class Payment
|
|
3
|
+
class Refund
|
|
4
|
+
class GiftCard
|
|
5
|
+
include OperationImplementation
|
|
6
|
+
|
|
7
|
+
def complete!
|
|
8
|
+
Payment::GiftCard.refund(tender.number, transaction.amount.cents)
|
|
9
|
+
transaction.response = ActiveMerchant::Billing::Response.new(
|
|
10
|
+
true,
|
|
11
|
+
I18n.t(
|
|
12
|
+
'workarea.gift_cards.credit',
|
|
13
|
+
amount: transaction.amount,
|
|
14
|
+
number: tender.number
|
|
15
|
+
)
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def cancel!
|
|
20
|
+
return unless transaction.success?
|
|
21
|
+
|
|
22
|
+
Payment::GiftCard.purchase(tender.number, transaction.amount.cents)
|
|
23
|
+
transaction.cancellation = ActiveMerchant::Billing::Response.new(
|
|
24
|
+
true,
|
|
25
|
+
I18n.t(
|
|
26
|
+
'workarea.gift_cards.debit',
|
|
27
|
+
amount: transaction.amount,
|
|
28
|
+
number: tender.number
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|