workarea-gift_cards 3.4.11 → 4.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{.eslintrc → .eslintrc.json} +12 -1
- data/.github/workflows/ci.yml +10 -8
- data/.rubocop.yml +2 -197
- data/.stylelintrc.json +8 -0
- data/CHANGELOG.md +0 -71
- data/Gemfile +3 -5
- data/Rakefile +5 -4
- data/app/controllers/workarea/api/admin/gift_cards_controller.rb +309 -0
- data/app/controllers/workarea/api/storefront/checkouts_controller.decorator +6 -0
- data/app/controllers/workarea/api/storefront/gift_cards_controller.rb +2 -8
- data/app/controllers/workarea/storefront/checkout/gift_cards_controller.rb +32 -0
- data/app/controllers/workarea/storefront/gift_cards_controller.rb +15 -16
- data/app/models/workarea/checkout/steps/gift_card.rb +71 -0
- data/app/models/workarea/fulfillment/policies/create_gift_card.rb +30 -0
- data/app/models/workarea/payment/authorize/gift_card.rb +7 -20
- data/app/models/workarea/payment/capture/gift_card.rb +5 -7
- data/app/models/workarea/payment/gift_card.rb +1 -1
- data/app/models/workarea/payment/gift_card_operation.rb +9 -0
- data/app/models/workarea/payment/purchase/gift_card.rb +24 -1
- data/app/models/workarea/payment/refund/gift_card.rb +9 -14
- data/app/models/workarea/payment/tender/gift_card.rb +3 -10
- data/app/models/workarea/payment.decorator +25 -7
- data/app/models/workarea/search/admin/order.decorator +2 -4
- data/app/seeds/workarea/gift_card_seeds.rb +7 -7
- data/app/view_models/workarea/storefront/gift_card_order_pricing.rb +19 -20
- data/app/view_models/workarea/storefront/order_view_model.decorator +2 -22
- data/app/views/workarea/admin/payment_gift_cards/_menu.html.haml +2 -1
- data/app/views/workarea/storefront/checkouts/_gift_card_error.html.haml +8 -6
- data/app/views/workarea/storefront/checkouts/_gift_card_payment.html.haml +20 -12
- data/app/views/workarea/storefront/gift_card_mailer/created.html.haml +1 -1
- data/app/views/workarea/storefront/order_mailer/_gift_card_summary.html.haml +6 -5
- data/app/views/workarea/storefront/orders/_gift_card_summary.html.haml +2 -2
- data/app/views/workarea/storefront/products/templates/_gift_card.html.haml +5 -5
- data/app/workers/workarea/log_gift_card_redemption.rb +16 -9
- data/config/initializers/configuration.rb +7 -4
- data/config/initializers/fields.rb +14 -0
- data/config/locales/en.yml +14 -4
- data/config/routes.rb +9 -2
- data/lib/workarea/gift_cards/gateway.rb +128 -0
- data/lib/workarea/gift_cards/version.rb +1 -1
- data/lib/workarea/gift_cards.rb +9 -0
- data/test/documentation/workarea/api/admin/gift_cards_documentation_test.rb +24 -10
- data/test/documentation/workarea/api/storefront/gift_cards_documentation_test.rb +57 -50
- data/test/dummy/config/initializers/session_store.rb +1 -1
- data/test/integration/workarea/api/admin/gift_card_integration_test.rb +13 -5
- data/test/integration/workarea/api/storefront/checkout_gift_cards_integration_test.rb +120 -0
- data/test/integration/workarea/api/storefront/{balance_integration_test.rb → gift_cards_integration_test.rb} +1 -1
- data/test/integration/workarea/storefront/checkout_gift_cards_integration_test.rb +116 -0
- data/test/integration/workarea/storefront/gift_cards_integration_test.rb +48 -0
- data/test/integration/workarea/storefront/purchase_gift_cards_integration_test.rb +55 -0
- data/test/lib/workarea/gift_cards/gateway_test.rb +97 -0
- data/test/models/workarea/checkout/steps/gift_card_test.rb +104 -0
- data/test/models/workarea/fulfillment/policies/create_gift_card_test.rb +47 -0
- data/test/models/workarea/gift_card_payment_test.rb +15 -3
- data/test/models/workarea/payment/purchase/gift_card_test.rb +11 -8
- data/test/queries/workarea/admin_redemptions_export_test.rb +31 -35
- data/test/system/workarea/storefront/gift_cards_system_test.rb +8 -2
- data/test/view_models/workarea/storefront/gift_card_order_pricing_test.rb +113 -0
- data/test/workers/workarea/log_gift_card_redemption_test.rb +1 -1
- data/workarea-gift_cards.gemspec +4 -4
- metadata +26 -30
- data/.eslintignore +0 -2
- data/.scss-lint.yml +0 -188
- data/app/controllers/workarea/api/admin/payment_gift_cards_controller.rb +0 -49
- data/app/controllers/workarea/storefront/checkouts_controller.decorator +0 -24
- data/app/services/workarea/checkout/steps/gift_card.rb +0 -49
- data/app/view_models/workarea/storefront/checkout/payment_view_model.decorator +0 -32
- data/app/view_models/workarea/storefront/checkout/summary_view_model.decorator +0 -11
- data/app/workers/workarea/create_ordered_gift_cards.rb +0 -47
- data/config/initializers/jump_to_navigation.rb +0 -3
- data/test/integration/workarea/api/storefront/checkout_integration_test.rb +0 -161
- data/test/integration/workarea/storefront/gift_card_integration_test.rb +0 -226
- data/test/services/workarea/checkout/steps/gift_card_test.rb +0 -87
- data/test/view_models/workarea/storefront/checkout/gift_card_payment_view_model_test.rb +0 -65
- data/test/workers/workarea/create_ordered_gift_cards_test.rb +0 -39
@@ -12,19 +12,12 @@ module Workarea
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def amount=(amount)
|
15
|
-
if amount.blank?
|
16
|
-
|
17
|
-
elsif balance >= amount
|
18
|
-
super(amount)
|
19
|
-
else
|
20
|
-
super(balance)
|
21
|
-
end
|
15
|
+
return super(amount) if amount.blank? || balance >= amount
|
16
|
+
super(balance)
|
22
17
|
end
|
23
18
|
|
24
|
-
private
|
25
|
-
|
26
19
|
def balance
|
27
|
-
@balance ||=
|
20
|
+
@balance ||= Workarea::GiftCards.gateway.balance(number)
|
28
21
|
end
|
29
22
|
end
|
30
23
|
end
|
@@ -1,19 +1,37 @@
|
|
1
1
|
module Workarea
|
2
2
|
decorate Payment, with: 'gift_cards' do
|
3
3
|
decorated do
|
4
|
-
|
4
|
+
embeds_many :gift_cards, class_name: 'Workarea::Payment::Tender::GiftCard'
|
5
5
|
delegate :number, to: :gift_card, allow_nil: true, prefix: true
|
6
|
+
validate :gift_card_count_limit
|
6
7
|
end
|
7
8
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
9
|
+
def gift_card?
|
10
|
+
gift_cards.present?
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_gift_card(attrs)
|
14
|
+
existing = gift_cards.detect do |card|
|
15
|
+
card.number.casecmp?(attrs[:number].strip)
|
16
|
+
end
|
17
|
+
|
18
|
+
if existing.present?
|
19
|
+
existing.assign_attributes(attrs)
|
20
|
+
else
|
21
|
+
gift_cards.build(attrs)
|
22
|
+
end
|
23
|
+
|
11
24
|
save
|
12
25
|
end
|
13
26
|
|
14
|
-
|
15
|
-
|
16
|
-
|
27
|
+
private
|
28
|
+
|
29
|
+
def gift_card_count_limit
|
30
|
+
max = Workarea.config.max_gift_cards_per_order
|
31
|
+
|
32
|
+
if gift_cards.size > max
|
33
|
+
errors.add(:base, I18n.t('workarea.gift_cards.max_applied', count: max))
|
34
|
+
end
|
17
35
|
end
|
18
36
|
end
|
19
37
|
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
module Workarea
|
2
2
|
decorate Search::Admin::Order, with: 'gift_cards' do
|
3
|
-
def
|
4
|
-
|
5
|
-
result += " #{payment.gift_card.number}" if payment.gift_card.present?
|
6
|
-
result
|
3
|
+
def keywords
|
4
|
+
super + payment.gift_cards.map(&:number)
|
7
5
|
end
|
8
6
|
end
|
9
7
|
end
|
@@ -12,7 +12,6 @@ module Workarea
|
|
12
12
|
id: 'GIFT_CARD',
|
13
13
|
name: 'Gift Card',
|
14
14
|
gift_card: true,
|
15
|
-
digital: true,
|
16
15
|
template: 'gift_card',
|
17
16
|
customizations: 'gift_card',
|
18
17
|
description: Faker::Lorem.paragraph,
|
@@ -25,19 +24,20 @@ module Workarea
|
|
25
24
|
|
26
25
|
product.save!
|
27
26
|
|
28
|
-
|
27
|
+
|
28
|
+
Workarea::Fulfillment::Sku.find_or_create_by(
|
29
29
|
id: 'GIFT_CARD_10',
|
30
|
-
|
30
|
+
policy: :create_gift_card
|
31
31
|
)
|
32
32
|
|
33
|
-
Workarea::
|
33
|
+
Workarea::Fulfillment::Sku.find_or_create_by(
|
34
34
|
id: 'GIFT_CARD_25',
|
35
|
-
|
35
|
+
policy: :create_gift_card
|
36
36
|
)
|
37
37
|
|
38
|
-
Workarea::
|
38
|
+
Workarea::Fulfillment::Sku.find_or_create_by(
|
39
39
|
id: 'GIFT_CARD_50',
|
40
|
-
|
40
|
+
policy: :create_gift_card
|
41
41
|
)
|
42
42
|
end
|
43
43
|
end
|
@@ -1,35 +1,34 @@
|
|
1
1
|
module Workarea
|
2
2
|
module Storefront
|
3
3
|
module GiftCardOrderPricing
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
)
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def gift_cards
|
7
|
+
@gift_cards ||= payment.gift_cards.select(&:persisted?)
|
9
8
|
end
|
10
9
|
|
11
|
-
def
|
12
|
-
|
13
|
-
gift_card.balance
|
14
|
-
else
|
15
|
-
0.to_m
|
16
|
-
end
|
10
|
+
def gift_card?
|
11
|
+
gift_cards.present?
|
17
12
|
end
|
18
13
|
|
19
14
|
def gift_card_amount
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
15
|
+
gift_cards.sum(0.to_m, &:amount)
|
16
|
+
end
|
17
|
+
|
18
|
+
def gift_card_balance
|
19
|
+
gift_cards.sum(0.to_m, &:balance)
|
20
|
+
end
|
21
|
+
|
22
|
+
def total_before_gift_cards
|
23
|
+
order.total_price - advance_payment_amount + gift_card_amount
|
25
24
|
end
|
26
25
|
|
27
|
-
def
|
28
|
-
|
26
|
+
def advance_payment_amount
|
27
|
+
super + gift_card_amount
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
32
|
-
|
30
|
+
def failed_gift_card
|
31
|
+
@failed_gift_card ||= payment.gift_cards.reject(&:persisted?).first
|
33
32
|
end
|
34
33
|
end
|
35
34
|
end
|
@@ -1,27 +1,7 @@
|
|
1
1
|
module Workarea
|
2
|
-
decorate Storefront::OrderViewModel, with:
|
3
|
-
decorated do
|
4
|
-
delegate :gift_card?, to: :payment
|
5
|
-
end
|
6
|
-
|
7
|
-
def gift_card_tender
|
8
|
-
payment.gift_card
|
9
|
-
end
|
10
|
-
|
11
|
-
def gift_card_display_number
|
12
|
-
gift_card_tender.try(:display_number)
|
13
|
-
end
|
14
|
-
|
15
|
-
def gift_card_tender_amount
|
16
|
-
if gift_card?
|
17
|
-
gift_card_tender.amount
|
18
|
-
else
|
19
|
-
0.to_m
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
2
|
+
decorate Storefront::OrderViewModel, with: :order_gift_card do
|
23
3
|
def paid_amount
|
24
|
-
super -
|
4
|
+
super - gift_card_amount
|
25
5
|
end
|
26
6
|
end
|
27
7
|
end
|
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
- if Workarea::GiftCards.uses_system_cards?
|
2
|
+
%li{ class: "primary-nav__item" }= link_to t('workarea.admin.shared.primary_nav.gift_cards'), payment_gift_cards_path, class: navigation_link_classes(payment_gift_cards_path)
|
@@ -1,6 +1,8 @@
|
|
1
|
-
- if step.
|
2
|
-
- step.
|
3
|
-
.
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
- if step.gift_card?
|
2
|
+
- step.gift_cards.each do |gift_card|
|
3
|
+
- if gift_card.errors.any?
|
4
|
+
- gift_card.full_messages.each do |message|
|
5
|
+
.message.message--error
|
6
|
+
%p.message__type
|
7
|
+
%span.message__icon= t('workarea.storefront.messages.error')
|
8
|
+
%p.message__text= message
|
@@ -1,28 +1,36 @@
|
|
1
|
-
.checkout-payment__secondary-method{ class: step.
|
1
|
+
.checkout-payment__secondary-method{ class: step.gift_card? ? 'checkout-payment__secondary-method--visible' : nil }
|
2
2
|
|
3
|
-
- if step.
|
3
|
+
- if step.gift_card?
|
4
4
|
.message.message--info
|
5
5
|
%p.message__type
|
6
6
|
%span.message__icon= t('workarea.storefront.messages.info')
|
7
7
|
%p.message__text
|
8
|
-
#{t('workarea.storefront.gift_cards.
|
9
|
-
#{t('workarea.storefront.gift_cards.
|
8
|
+
#{t('workarea.storefront.gift_cards.balance_html', amount: number_to_currency(step.gift_card_balance))}
|
9
|
+
#{t('workarea.storefront.gift_cards.applied_to_order_html', amount: number_to_currency(step.gift_card_amount))}
|
10
10
|
|
11
|
-
- if step.order_covered_by_gift_card?
|
12
|
-
#{t('workarea.storefront.gift_cards.place_order', amount: number_to_currency(step.gift_card_amount))}
|
13
11
|
- if step.tender_required?
|
14
|
-
#{t('workarea.storefront.gift_cards.
|
12
|
+
#{t('workarea.storefront.gift_cards.tender_required_html', amount: number_to_currency(step.order_balance))}
|
13
|
+
- else
|
14
|
+
#{t('workarea.storefront.gift_cards.place_order')}
|
15
15
|
|
16
|
-
= optional_field(t('workarea.storefront.gift_cards.enter_gift_card_prompt'), step.
|
16
|
+
= optional_field(t('workarea.storefront.gift_cards.enter_gift_card_prompt'), step.gift_cards, step.failed_gift_card) do
|
17
17
|
|
18
18
|
%h2= t('workarea.storefront.gift_cards.gift_card')
|
19
19
|
|
20
|
-
= form_tag
|
20
|
+
= form_tag checkout_gift_cards_path, method: 'patch', id: 'gift_card_form', class: 'inline-form' do
|
21
21
|
|
22
22
|
.inline-form__cell
|
23
23
|
.value
|
24
|
-
= text_field_tag 'gift_card_number', step.
|
25
|
-
- if step.
|
26
|
-
%span.value__error= step.
|
24
|
+
= text_field_tag 'gift_card_number', step.failed_gift_card&.number, class: 'text-box', autocomplete: 'off', title: t('workarea.storefront.gift_cards.gift_card_number'), placeholder: t('workarea.storefront.gift_cards.gift_card_number')
|
25
|
+
- if step.failed_gift_card && step.failed_gift_card.errors[:number].present?
|
26
|
+
%span.value__error= step.failed_gift_card.errors[:number].first
|
27
27
|
.inline-form__cell
|
28
28
|
%p= button_tag t('workarea.storefront.gift_cards.apply_gift_card'), value: 'apply_gift_card', class: 'button'
|
29
|
+
|
30
|
+
.applied-gift-cards
|
31
|
+
- step.gift_cards.each do |gift_card|
|
32
|
+
%p.applied-gift-card
|
33
|
+
%strong.applied-gift-card__number= gift_card.display_number
|
34
|
+
= link_to t('workarea.storefront.gift_cards.remove'), checkout_gift_cards_path(gift_card_id: gift_card.id), data: { method: :delete, confirm: t('workarea.storefront.gift_cards.remove_confirmation') }, class: 'applied-gift-card__remove-link'
|
35
|
+
%br
|
36
|
+
%span.applied-gift-card__applied= t('workarea.storefront.gift_cards.balance_applied_html', amount: number_to_currency(gift_card.amount), balance: number_to_currency(gift_card.balance))
|
@@ -4,7 +4,7 @@
|
|
4
4
|
%p
|
5
5
|
%strong= @from
|
6
6
|
%br
|
7
|
-
= t('workarea.storefront.email.gift_card_created.message_html', link: link_to(Workarea.config.host, Workarea.config.host
|
7
|
+
= t('workarea.storefront.email.gift_card_created.message_html', link: link_to(Workarea.config.host, Workarea.config.host), amount: number_to_currency(@card.amount))
|
8
8
|
|
9
9
|
- if @card.message.present?
|
10
10
|
%p
|
@@ -1,5 +1,6 @@
|
|
1
|
-
- if order.
|
2
|
-
|
3
|
-
%
|
4
|
-
|
5
|
-
|
1
|
+
- if order.gift_card_amount > 0
|
2
|
+
- order.gift_cards.each do |gift_card|
|
3
|
+
%p
|
4
|
+
= t('workarea.storefront.gift_cards.gift_card')
|
5
|
+
= gift_card.display_number
|
6
|
+
= number_to_currency(gift_card.amount)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
- if order.
|
1
|
+
- if order.gift_card_amount > 0
|
2
2
|
%tr
|
3
3
|
%th
|
4
4
|
%span= t('workarea.storefront.gift_cards.gift_card')
|
5
5
|
%td
|
6
|
-
%strong.table__price-discount −#{number_to_currency(order.
|
6
|
+
%strong.table__price-discount −#{number_to_currency(order.gift_card_amount)}
|
@@ -2,12 +2,12 @@
|
|
2
2
|
.grid__cell.grid__cell--60-at-medium
|
3
3
|
|
4
4
|
.product-details__name
|
5
|
-
%h1.product-details__heading
|
5
|
+
%h1.product-details__heading= product.name
|
6
6
|
|
7
7
|
%p.product-details__id
|
8
|
-
%span
|
8
|
+
%span= product.id
|
9
9
|
|
10
|
-
.product-prices.product-prices--details
|
10
|
+
.product-prices.product-prices--details
|
11
11
|
= render 'workarea/storefront/products/pricing', product: product
|
12
12
|
|
13
13
|
- if product.description.present?
|
@@ -60,13 +60,13 @@
|
|
60
60
|
|
61
61
|
= append_partials('storefront.product_details', product: product)
|
62
62
|
|
63
|
-
%p.product-details__full-details=link_to t('workarea.storefront.products.view_full_details'), product_path(product, color: params[:color]), class: 'text-button'
|
63
|
+
%p.product-details__full-details=link_to t('workarea.storefront.products.view_full_details'), product_path(product, color: params[:color]), class: 'text-button'
|
64
64
|
|
65
65
|
.grid__cell.grid__cell--40-at-medium
|
66
66
|
|
67
67
|
.product-details__primary-image
|
68
68
|
= link_to(product_image_url(product.primary_image, :zoom), target: '_blank', class: 'product-details__primary-image-link', data: { dialog_button: '' }) do
|
69
|
-
= image_tag product_image_url(product.primary_image, :detail), alt: 'View Larger Image',
|
69
|
+
= image_tag product_image_url(product.primary_image, :detail), alt: 'View Larger Image', class: 'product-details__primary-image-link-image'
|
70
70
|
|
71
71
|
- if product.images.length > 1
|
72
72
|
.product-details__alt-images
|
@@ -3,7 +3,12 @@ module Workarea
|
|
3
3
|
include Sidekiq::Worker
|
4
4
|
include Sidekiq::CallbacksWorker
|
5
5
|
|
6
|
-
sidekiq_options
|
6
|
+
sidekiq_options(
|
7
|
+
enqueue_on: {
|
8
|
+
Order => :place,
|
9
|
+
only_if: -> { Workarea::GiftCards.uses_system_cards? }
|
10
|
+
}
|
11
|
+
)
|
7
12
|
|
8
13
|
def perform(order_id)
|
9
14
|
order = Order.find(order_id)
|
@@ -11,16 +16,18 @@ module Workarea
|
|
11
16
|
payment = Payment.find_or_initialize_by(id: order.id)
|
12
17
|
return unless payment.gift_card?
|
13
18
|
|
14
|
-
|
15
|
-
|
19
|
+
payment.gift_cards.each do |tender|
|
20
|
+
gift_card = Payment::GiftCard.find_by_token(tender.number)
|
21
|
+
next if redemption_already_exists?(gift_card, order.id)
|
16
22
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
23
|
+
gift_card.redemptions.create!(
|
24
|
+
redeemed_at: order.placed_at,
|
25
|
+
amount: tender.amount,
|
26
|
+
order_id: order.id
|
27
|
+
)
|
22
28
|
|
23
|
-
|
29
|
+
gift_card.touch
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
33
|
private
|
@@ -1,8 +1,11 @@
|
|
1
1
|
Workarea.configure do |config|
|
2
|
-
config.checkout_steps << 'Workarea::Checkout::Steps::GiftCard'
|
3
|
-
config.customization_types << Workarea::Catalog::Customizations::GiftCard
|
4
2
|
config.product_templates << :gift_card
|
5
|
-
config.
|
3
|
+
config.customization_types << 'Workarea::Catalog::Customizations::GiftCard'
|
4
|
+
config.fulfillment_policies << 'Workarea::Fulfillment::Policies::CreateGiftCard'
|
5
|
+
config.checkout_steps << 'Workarea::Checkout::Steps::GiftCard'
|
6
|
+
config.tender_types.prepend(:gift_cards)
|
6
7
|
config.seeds << 'Workarea::GiftCardSeeds'
|
7
|
-
config.
|
8
|
+
config.jump_to_navigation.merge!('Gift Cards' => :payment_gift_cards_path)
|
9
|
+
|
10
|
+
config.gateways.gift_card = 'Workarea::GiftCards::Gateway'
|
8
11
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
Workarea::Configuration.define_fields do
|
3
|
+
fieldset 'Gift Cards', namespaced: false do
|
4
|
+
field 'Gift Card Token Length',
|
5
|
+
type: :integer,
|
6
|
+
default: 8,
|
7
|
+
description: 'Length of digital gift card numbers generated by Workarea.'
|
8
|
+
|
9
|
+
field 'Max Gift Cards Per Order',
|
10
|
+
type: :integer,
|
11
|
+
default: 10,
|
12
|
+
description: 'How many gift cards can be applied to a single order.'
|
13
|
+
end
|
14
|
+
end
|
data/config/locales/en.yml
CHANGED
@@ -52,6 +52,7 @@ en:
|
|
52
52
|
credit: "%{amount} added to gift card %{number}"
|
53
53
|
debit: "%{amount} deducted from gift card %{number}"
|
54
54
|
insufficient_funds: This gift card doesn't not enough balance.
|
55
|
+
max_applied: You can only apply up to %{count} gift cards to an order.
|
55
56
|
payment_gift_card:
|
56
57
|
name: Gift Card %{token}
|
57
58
|
storefront:
|
@@ -62,20 +63,29 @@ en:
|
|
62
63
|
message_html: has purchased a gift certificate for you to use at %{link} in the amount of %{amount}.
|
63
64
|
says: 'says:'
|
64
65
|
subject: You've Got a Gift Certificate!
|
66
|
+
flash_messages:
|
67
|
+
gift_card_added: Your gift card has been applied.
|
68
|
+
gift_card_error: We couldn't add this gift card number.
|
69
|
+
gift_card_removed: Your gift card has been removed.
|
70
|
+
gift_card_balance: Your balance is %{balance}.
|
71
|
+
gift_card_not_found: Invalid card number or email.
|
65
72
|
gift_cards:
|
66
|
-
|
73
|
+
applied_to_order_html: "%{amount} will be applied to your order."
|
67
74
|
apply_gift_card: Apply
|
68
|
-
|
75
|
+
balance_html: Your total gift card balance is %{amount}.
|
76
|
+
balance_applied_html: '%{amount} of %{balance} balance will be applied to this order.'
|
69
77
|
check_balance: Check Your Gift Card Balance
|
70
78
|
email_to_recipient: We will email the digital gift card to the recipient.
|
71
79
|
enter_gift_card_prompt: Enter a gift card number
|
72
|
-
gift_card: Gift
|
80
|
+
gift_card: Gift Cards
|
73
81
|
gift_card_number: Gift Card Number
|
74
82
|
message_to_recipient: Message to Recipient
|
75
83
|
place_order: Click the Place Order button below to complete your order.
|
76
84
|
recipients_email: Recipient's Email
|
85
|
+
remove: remove
|
86
|
+
remove_confirmation: Are you sure you want to remove this gift card?
|
77
87
|
senders_email: Your Name
|
78
|
-
|
88
|
+
tender_required_html: You must submit another payment method for %{amount}.
|
79
89
|
orders:
|
80
90
|
tenders:
|
81
91
|
gift_card:
|
data/config/routes.rb
CHANGED
@@ -10,19 +10,26 @@ Workarea::Storefront::Engine.routes.draw do
|
|
10
10
|
scope '(:locale)', constraints: Workarea::I18n.routes_constraint do
|
11
11
|
get 'gift_cards/balance', to: 'gift_cards#index'
|
12
12
|
get 'gift_cards/lookup', to: 'gift_cards#lookup'
|
13
|
-
|
13
|
+
|
14
|
+
namespace :checkout do
|
15
|
+
patch 'gift_cards', to: 'gift_cards#add'
|
16
|
+
delete 'gift_cards', to: 'gift_cards#remove'
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
17
21
|
if Workarea::Plugin.installed?(:api)
|
18
22
|
Workarea::Api::Admin::Engine.routes.draw do
|
19
|
-
resources :
|
23
|
+
resources :gift_cards do
|
24
|
+
collection { patch 'bulk' }
|
25
|
+
end
|
20
26
|
end
|
21
27
|
|
22
28
|
Workarea::Api::Storefront::Engine.routes.draw do
|
23
29
|
resources :checkouts, only: [] do
|
24
30
|
member do
|
25
31
|
patch 'add_gift_card'
|
32
|
+
delete 'remove_gift_card'
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Workarea
|
2
|
+
module GiftCards
|
3
|
+
class Gateway
|
4
|
+
# Object returns from transaction requests.
|
5
|
+
#
|
6
|
+
# @attr [Boolean] success? whether the transaction was successful or not
|
7
|
+
# @attr [String] message information on the transaction result
|
8
|
+
#
|
9
|
+
class Response < Struct.new(:success?, :message); end
|
10
|
+
|
11
|
+
# Whether or not this gateway uses +Workarea::Payment::GiftCard+
|
12
|
+
# This controls the display of the admin menu, triggering the creation of
|
13
|
+
# cards from orders, and tracking redemptions.
|
14
|
+
#
|
15
|
+
def uses_system_cards?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
# See purchase. This gateway performs a purchase on authorization.
|
20
|
+
#
|
21
|
+
# @param [Integer] amount amount to authorize, in cents
|
22
|
+
# @param [Workarea::Payment::Tender::GiftCard] tender for transaction
|
23
|
+
#
|
24
|
+
# @return [Workarea::GiftCards::Gateway::Response]
|
25
|
+
#
|
26
|
+
def authorize(amount, tender)
|
27
|
+
purchase(amount, tender)
|
28
|
+
end
|
29
|
+
|
30
|
+
# See refund.
|
31
|
+
#
|
32
|
+
# @param [Integer] amount amount to cancel, in cents
|
33
|
+
# @param [Workarea::Payment::Tender::GiftCard] tender for transaction
|
34
|
+
#
|
35
|
+
# @return [Workarea::GiftCards::Gateway::Response]
|
36
|
+
#
|
37
|
+
def cancel(amount, tender)
|
38
|
+
refund(amount, tender)
|
39
|
+
end
|
40
|
+
|
41
|
+
# This gateway does a purchase on authorization so no capture is required.
|
42
|
+
#
|
43
|
+
# @param [Integer] amount amount to capture, in cents
|
44
|
+
# @param [Workarea::Payment::Tender::GiftCard] tender for transaction
|
45
|
+
#
|
46
|
+
# @return [Workarea::GiftCards::Gateway::Response]
|
47
|
+
#
|
48
|
+
def capture(amount, tender)
|
49
|
+
# no op, captures on authorization
|
50
|
+
Response.new(true, I18n.t('workarea.gift_cards.capture'))
|
51
|
+
end
|
52
|
+
|
53
|
+
# Perform a purchase on a +Workarea::Payment::GiftCard+. This will
|
54
|
+
# increment the `used` field, and decrement the `balance` field.
|
55
|
+
#
|
56
|
+
# @param [Integer] amount amount to purchase, in cents
|
57
|
+
# @param [Workarea::Payment::Tender::GiftCard] tender for transaction
|
58
|
+
#
|
59
|
+
# @return [Workarea::GiftCards::Gateway::Response]
|
60
|
+
#
|
61
|
+
def purchase(amount, tender)
|
62
|
+
Payment::GiftCard.purchase(tender.number, amount)
|
63
|
+
|
64
|
+
Response.new(
|
65
|
+
true,
|
66
|
+
I18n.t(
|
67
|
+
'workarea.gift_cards.debit',
|
68
|
+
amount: amount,
|
69
|
+
number: tender.number
|
70
|
+
)
|
71
|
+
)
|
72
|
+
rescue Payment::InsufficientFunds
|
73
|
+
Response.new(false, I18n.t('workarea.gift_cards.insufficient_funds'))
|
74
|
+
end
|
75
|
+
|
76
|
+
# Undo a purchase on a +Workarea::Payment::GiftCard+. This will
|
77
|
+
# increment the `balance` field, and decrement the `used` field.
|
78
|
+
#
|
79
|
+
# @param [Integer] amount amount to refund, in cents
|
80
|
+
# @param [Workarea::Payment::Tender::GiftCard] tender for transaction
|
81
|
+
#
|
82
|
+
# @return [Workarea::GiftCards::Gateway::Response]
|
83
|
+
#
|
84
|
+
def refund(amount, tender)
|
85
|
+
Payment::GiftCard.refund(tender.number, amount)
|
86
|
+
|
87
|
+
Response.new(
|
88
|
+
true,
|
89
|
+
I18n.t(
|
90
|
+
'workarea.gift_cards.credit',
|
91
|
+
amount: amount,
|
92
|
+
number: tender.number
|
93
|
+
)
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Lookup the balance of one or many +Workarea::Payment::GiftCard+ records.
|
98
|
+
# It will always return a single sum. If multiple numbers are provided, it
|
99
|
+
# returns the total of all balances. Invalid numbers return a balance of
|
100
|
+
# zero.
|
101
|
+
#
|
102
|
+
# @param [String] token the gift card number/token
|
103
|
+
#
|
104
|
+
# @return [Money] the balance gift cards matching the numbers provided
|
105
|
+
#
|
106
|
+
def balance(token)
|
107
|
+
Array.wrap(token).sum(0.to_m) { |t| Payment::GiftCard.find_balance(t) }
|
108
|
+
end
|
109
|
+
|
110
|
+
# Lookup a gift card.
|
111
|
+
#
|
112
|
+
# @param [Hash] params
|
113
|
+
# @option params [String] :email address associated to the gift card
|
114
|
+
# @option params [String] :token gift card number/token to lookup
|
115
|
+
#
|
116
|
+
# @return [Workarea::Payment::GiftCard, nil]
|
117
|
+
#
|
118
|
+
def lookup(params)
|
119
|
+
email = params.fetch(:email, nil)
|
120
|
+
token = params.fetch(:token, nil)
|
121
|
+
|
122
|
+
if email.present? && token.present?
|
123
|
+
Workarea::Payment::GiftCard.find_by_token_and_email(token, email)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/workarea/gift_cards.rb
CHANGED
@@ -4,8 +4,17 @@ require 'workarea/admin'
|
|
4
4
|
|
5
5
|
module Workarea
|
6
6
|
module GiftCards
|
7
|
+
def self.gateway
|
8
|
+
Workarea.config.gateways.gift_card.constantize.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.uses_system_cards?
|
12
|
+
Workarea::GiftCards.gateway.respond_to?(:uses_system_cards?) &&
|
13
|
+
Workarea::GiftCards.gateway.uses_system_cards?
|
14
|
+
end
|
7
15
|
end
|
8
16
|
end
|
9
17
|
|
10
18
|
require 'workarea/gift_cards/version'
|
11
19
|
require 'workarea/gift_cards/engine'
|
20
|
+
require 'workarea/gift_cards/gateway'
|