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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/{.eslintrc → .eslintrc.json} +12 -1
  3. data/.github/workflows/ci.yml +10 -8
  4. data/.rubocop.yml +2 -197
  5. data/.stylelintrc.json +8 -0
  6. data/CHANGELOG.md +0 -71
  7. data/Gemfile +3 -5
  8. data/Rakefile +5 -4
  9. data/app/controllers/workarea/api/admin/gift_cards_controller.rb +309 -0
  10. data/app/controllers/workarea/api/storefront/checkouts_controller.decorator +6 -0
  11. data/app/controllers/workarea/api/storefront/gift_cards_controller.rb +2 -8
  12. data/app/controllers/workarea/storefront/checkout/gift_cards_controller.rb +32 -0
  13. data/app/controllers/workarea/storefront/gift_cards_controller.rb +15 -16
  14. data/app/models/workarea/checkout/steps/gift_card.rb +71 -0
  15. data/app/models/workarea/fulfillment/policies/create_gift_card.rb +30 -0
  16. data/app/models/workarea/payment/authorize/gift_card.rb +7 -20
  17. data/app/models/workarea/payment/capture/gift_card.rb +5 -7
  18. data/app/models/workarea/payment/gift_card.rb +1 -1
  19. data/app/models/workarea/payment/gift_card_operation.rb +9 -0
  20. data/app/models/workarea/payment/purchase/gift_card.rb +24 -1
  21. data/app/models/workarea/payment/refund/gift_card.rb +9 -14
  22. data/app/models/workarea/payment/tender/gift_card.rb +3 -10
  23. data/app/models/workarea/payment.decorator +25 -7
  24. data/app/models/workarea/search/admin/order.decorator +2 -4
  25. data/app/seeds/workarea/gift_card_seeds.rb +7 -7
  26. data/app/view_models/workarea/storefront/gift_card_order_pricing.rb +19 -20
  27. data/app/view_models/workarea/storefront/order_view_model.decorator +2 -22
  28. data/app/views/workarea/admin/payment_gift_cards/_menu.html.haml +2 -1
  29. data/app/views/workarea/storefront/checkouts/_gift_card_error.html.haml +8 -6
  30. data/app/views/workarea/storefront/checkouts/_gift_card_payment.html.haml +20 -12
  31. data/app/views/workarea/storefront/gift_card_mailer/created.html.haml +1 -1
  32. data/app/views/workarea/storefront/order_mailer/_gift_card_summary.html.haml +6 -5
  33. data/app/views/workarea/storefront/orders/_gift_card_summary.html.haml +2 -2
  34. data/app/views/workarea/storefront/products/templates/_gift_card.html.haml +5 -5
  35. data/app/workers/workarea/log_gift_card_redemption.rb +16 -9
  36. data/config/initializers/configuration.rb +7 -4
  37. data/config/initializers/fields.rb +14 -0
  38. data/config/locales/en.yml +14 -4
  39. data/config/routes.rb +9 -2
  40. data/lib/workarea/gift_cards/gateway.rb +128 -0
  41. data/lib/workarea/gift_cards/version.rb +1 -1
  42. data/lib/workarea/gift_cards.rb +9 -0
  43. data/test/documentation/workarea/api/admin/gift_cards_documentation_test.rb +24 -10
  44. data/test/documentation/workarea/api/storefront/gift_cards_documentation_test.rb +57 -50
  45. data/test/dummy/config/initializers/session_store.rb +1 -1
  46. data/test/integration/workarea/api/admin/gift_card_integration_test.rb +13 -5
  47. data/test/integration/workarea/api/storefront/checkout_gift_cards_integration_test.rb +120 -0
  48. data/test/integration/workarea/api/storefront/{balance_integration_test.rb → gift_cards_integration_test.rb} +1 -1
  49. data/test/integration/workarea/storefront/checkout_gift_cards_integration_test.rb +116 -0
  50. data/test/integration/workarea/storefront/gift_cards_integration_test.rb +48 -0
  51. data/test/integration/workarea/storefront/purchase_gift_cards_integration_test.rb +55 -0
  52. data/test/lib/workarea/gift_cards/gateway_test.rb +97 -0
  53. data/test/models/workarea/checkout/steps/gift_card_test.rb +104 -0
  54. data/test/models/workarea/fulfillment/policies/create_gift_card_test.rb +47 -0
  55. data/test/models/workarea/gift_card_payment_test.rb +15 -3
  56. data/test/models/workarea/payment/purchase/gift_card_test.rb +11 -8
  57. data/test/queries/workarea/admin_redemptions_export_test.rb +31 -35
  58. data/test/system/workarea/storefront/gift_cards_system_test.rb +8 -2
  59. data/test/view_models/workarea/storefront/gift_card_order_pricing_test.rb +113 -0
  60. data/test/workers/workarea/log_gift_card_redemption_test.rb +1 -1
  61. data/workarea-gift_cards.gemspec +4 -4
  62. metadata +26 -30
  63. data/.eslintignore +0 -2
  64. data/.scss-lint.yml +0 -188
  65. data/app/controllers/workarea/api/admin/payment_gift_cards_controller.rb +0 -49
  66. data/app/controllers/workarea/storefront/checkouts_controller.decorator +0 -24
  67. data/app/services/workarea/checkout/steps/gift_card.rb +0 -49
  68. data/app/view_models/workarea/storefront/checkout/payment_view_model.decorator +0 -32
  69. data/app/view_models/workarea/storefront/checkout/summary_view_model.decorator +0 -11
  70. data/app/workers/workarea/create_ordered_gift_cards.rb +0 -47
  71. data/config/initializers/jump_to_navigation.rb +0 -3
  72. data/test/integration/workarea/api/storefront/checkout_integration_test.rb +0 -161
  73. data/test/integration/workarea/storefront/gift_card_integration_test.rb +0 -226
  74. data/test/services/workarea/checkout/steps/gift_card_test.rb +0 -87
  75. data/test/view_models/workarea/storefront/checkout/gift_card_payment_view_model_test.rb +0 -65
  76. 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
- super(amount)
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 ||= Payment::GiftCard.find_balance(number)
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
- embeds_one :gift_card, class_name: 'Workarea::Payment::Tender::GiftCard'
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 set_gift_card(attrs)
9
- build_gift_card unless gift_card
10
- gift_card.number = attrs[:number]
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
- def reset!
15
- self.gift_card = nil
16
- super
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 search_text
4
- result = super
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
- Workarea::Pricing::Sku.find_or_create_by(
27
+
28
+ Workarea::Fulfillment::Sku.find_or_create_by(
29
29
  id: 'GIFT_CARD_10',
30
- prices: [{ regular: 10 }]
30
+ policy: :create_gift_card
31
31
  )
32
32
 
33
- Workarea::Pricing::Sku.find_or_create_by(
33
+ Workarea::Fulfillment::Sku.find_or_create_by(
34
34
  id: 'GIFT_CARD_25',
35
- prices: [{ regular: 25 }]
35
+ policy: :create_gift_card
36
36
  )
37
37
 
38
- Workarea::Pricing::Sku.find_or_create_by(
38
+ Workarea::Fulfillment::Sku.find_or_create_by(
39
39
  id: 'GIFT_CARD_50',
40
- prices: [{ regular: 50 }]
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
- def gift_card
5
- return unless payment.gift_card.present?
6
- @gift_card ||= Workarea::Payment::GiftCard.find_by_token(
7
- payment.gift_card.number
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 gift_card_balance
12
- if gift_card.present?
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
- if gift_card_balance > total_after_store_credit
21
- total_after_store_credit
22
- else
23
- gift_card_balance
24
- end
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 total_after_store_credit
28
- order.total_price - store_credit_amount
26
+ def advance_payment_amount
27
+ super + gift_card_amount
29
28
  end
30
29
 
31
- def order_balance
32
- super - gift_card_amount
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: 'gift_card_display' do
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 - gift_card_tender_amount
4
+ super - gift_card_amount
25
5
  end
26
6
  end
27
7
  end
@@ -1 +1,2 @@
1
- %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
+ - 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.payment.gift_card && step.payment.gift_card.errors.any?
2
- - step.payment.gift_card.errors.full_messages.each do |message|
3
- .message.message--error
4
- %p.message__type
5
- %span.message__icon= t('workarea.storefront.messages.error')
6
- %p.message__text= message
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.show_gift_card? ? 'checkout-payment__secondary-method--visible' : nil }
1
+ .checkout-payment__secondary-method{ class: step.gift_card? ? 'checkout-payment__secondary-method--visible' : nil }
2
2
 
3
- - if step.show_gift_card?
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.balance', amount: number_to_currency(step.gift_card_balance))}
9
- #{t('workarea.storefront.gift_cards.applied_to_order', amount: number_to_currency(step.gift_card_amount))}
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.tender_required', amount: number_to_currency(step.order_balance))}
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.gift_card.try(:number)) do
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 checkout_add_gift_card_path, method: 'patch', id: 'gift_card_form', class: 'inline-form' do
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.gift_card.try(: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.gift_card && step.gift_card.errors[:number].present?
26
- %span.value__error= step.gift_card.errors[:number].first
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, style: "color: #{@config.link_color}"), amount: number_to_currency(@card.amount))
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.gift_card_tender_amount > 0
2
- %tr
3
- %th= t('workarea.storefront.gift_cards.gift_card')
4
- %td
5
- - #{number_to_currency order.gift_card_tender_amount}
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.gift_card_tender_amount > 0
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.gift_card_tender_amount)}
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{ itemprop: 'name' }= product.name
5
+ %h1.product-details__heading= product.name
6
6
 
7
7
  %p.product-details__id
8
- %span{ itemprop: 'productID' }= product.id
8
+ %span= product.id
9
9
 
10
- .product-prices.product-prices--details{ itemprop: 'offers', itemscope: true, itemtype: 'http://schema.org/Offer' }
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', itemprop: 'url'
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', itemprop: 'image', class: 'product-details__primary-image-link-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 enqueue_on: { Order => :place }
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
- gift_card = Payment::GiftCard.find_by_token(payment.gift_card.number)
15
- return if redemption_already_exists?(gift_card, order.id)
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
- gift_card.redemptions.create!(
18
- redeemed_at: order.placed_at,
19
- amount: payment.gift_card.amount,
20
- order_id: order.id
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
- gift_card.touch
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.tender_types.prepend(:gift_card)
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.gift_card_token_length = 8
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
@@ -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
- applied_to_order: "%{amount} will be applied to your order."
73
+ applied_to_order_html: "%{amount} will be applied to your order."
67
74
  apply_gift_card: Apply
68
- balance: Your gift card balance is %{amount}.
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 Card
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
- tender_required: You must submit another payment method for %{amount}.
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
- patch 'checkout/add_gift_card', to: 'checkouts#add_gift_card'
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 :payment_gift_cards
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
@@ -1,5 +1,5 @@
1
1
  module Workarea
2
2
  module GiftCards
3
- VERSION = '3.4.11'.freeze
3
+ VERSION = '4.0.0.beta.1'.freeze
4
4
  end
5
5
  end
@@ -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'