workarea-gift_cards 3.4.10 → 4.0.3

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.
Files changed (76) hide show
  1. checksums.yaml +5 -5
  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 +40 -20
  7. data/Gemfile +3 -5
  8. data/README.md +25 -1
  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 +72 -0
  15. data/app/models/workarea/fulfillment/policies/create_gift_card.rb +30 -0
  16. data/app/models/workarea/payment.decorator +25 -7
  17. data/app/models/workarea/payment/authorize/gift_card.rb +7 -20
  18. data/app/models/workarea/payment/capture/gift_card.rb +5 -7
  19. data/app/models/workarea/payment/gift_card.rb +1 -1
  20. data/app/models/workarea/payment/gift_card_operation.rb +9 -0
  21. data/app/models/workarea/payment/purchase/gift_card.rb +24 -1
  22. data/app/models/workarea/payment/refund/gift_card.rb +9 -14
  23. data/app/models/workarea/payment/tender/gift_card.rb +3 -10
  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.rb +9 -0
  41. data/lib/workarea/gift_cards/gateway.rb +128 -0
  42. data/lib/workarea/gift_cards/version.rb +1 -1
  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 +131 -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 +32 -25
  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
@@ -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:
@@ -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
 
@@ -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'
@@ -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