workarea-afterpay 2.0.2

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 (120) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  4. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/.gitignore +22 -0
  7. data/CHANGELOG.md +161 -0
  8. data/CODE_OF_CONDUCT.md +3 -0
  9. data/CONTRIBUTING.md +3 -0
  10. data/Gemfile +17 -0
  11. data/LICENSE +52 -0
  12. data/README.md +131 -0
  13. data/Rakefile +60 -0
  14. data/app/assets/fonts/workarea/storefront/raleway/raleway_800.woff +0 -0
  15. data/app/assets/fonts/workarea/storefront/raleway/raleway_800.woff2 +0 -0
  16. data/app/assets/fonts/workarea/storefront/raleway/raleway_regular.woff +0 -0
  17. data/app/assets/fonts/workarea/storefront/raleway/raleway_regular.woff2 +0 -0
  18. data/app/assets/images/workarea/storefront/afterpay/afterpay_logo.png +0 -0
  19. data/app/assets/images/workarea/storefront/afterpay/aus/dialog_header_image.png +0 -0
  20. data/app/assets/images/workarea/storefront/afterpay/aus/step_1.png +0 -0
  21. data/app/assets/images/workarea/storefront/afterpay/aus/step_2.png +0 -0
  22. data/app/assets/images/workarea/storefront/afterpay/aus/step_3.png +0 -0
  23. data/app/assets/images/workarea/storefront/afterpay/us/complete_checkout.svg +1 -0
  24. data/app/assets/images/workarea/storefront/afterpay/us/four_equal_payments.svg +1 -0
  25. data/app/assets/images/workarea/storefront/afterpay/us/select_installments.svg +1 -0
  26. data/app/assets/javascripts/workarea/storefront/afterpay/config.js.erb +17 -0
  27. data/app/assets/javascripts/workarea/storefront/afterpay/modules/afterpay_redirect.js +30 -0
  28. data/app/assets/stylesheets/workarea/storefront/components/_afterpay_dialog.scss +158 -0
  29. data/app/controllers/workarea/admin/afterpay/configurations_controller.rb +33 -0
  30. data/app/controllers/workarea/storefront/afterpay_controller.rb +124 -0
  31. data/app/controllers/workarea/storefront/afterpay_dialog_controller.rb +7 -0
  32. data/app/controllers/workarea/storefront/checkout/place_order_controller.decorator +11 -0
  33. data/app/helpers/workarea/storefront/afterpay_helper.rb +16 -0
  34. data/app/models/workarea/afterpay/configuration.rb +16 -0
  35. data/app/models/workarea/order.decorator +17 -0
  36. data/app/models/workarea/payment/afterpay_payment_gateway.rb +16 -0
  37. data/app/models/workarea/payment/authorize/afterpay.rb +7 -0
  38. data/app/models/workarea/payment/capture/afterpay.rb +35 -0
  39. data/app/models/workarea/payment/purchase/afterpay.rb +7 -0
  40. data/app/models/workarea/payment/refund/afterpay.rb +52 -0
  41. data/app/models/workarea/payment/tender/afterpay.rb +18 -0
  42. data/app/models/workarea/payment.decorator +42 -0
  43. data/app/services/workarea/afterpay/order_builder.rb +107 -0
  44. data/app/view_models/workarea/admin/afterpay_configuration_view_model.rb +36 -0
  45. data/app/view_models/workarea/storefront/afterpay_configuration.rb +25 -0
  46. data/app/view_models/workarea/storefront/afterpay_view_model.rb +89 -0
  47. data/app/view_models/workarea/storefront/cart_view_model.decorator +12 -0
  48. data/app/view_models/workarea/storefront/checkout/payment_view_model.decorator +32 -0
  49. data/app/view_models/workarea/storefront/product_view_model.decorator +50 -0
  50. data/app/views/workarea/admin/afterpay/configurations/edit.html.haml +59 -0
  51. data/app/views/workarea/admin/orders/tenders/_afterpay.html.haml +2 -0
  52. data/app/views/workarea/admin/shared/_afterpay_configuration_link.html.haml +1 -0
  53. data/app/views/workarea/storefront/afterpay_dialog/show.html.haml +40 -0
  54. data/app/views/workarea/storefront/afterpay_dialog/show_aus.html.haml +40 -0
  55. data/app/views/workarea/storefront/carts/_afterpay.html.haml +9 -0
  56. data/app/views/workarea/storefront/checkouts/_afterpay_payment.html.haml +17 -0
  57. data/app/views/workarea/storefront/order_mailer/tenders/_afterpay.html.haml +4 -0
  58. data/app/views/workarea/storefront/order_mailer/tenders/_afterpay.text.erb +1 -0
  59. data/app/views/workarea/storefront/orders/tenders/_afterpay.html.haml +5 -0
  60. data/app/views/workarea/storefront/products/_afterpay_pricing.html.haml +3 -0
  61. data/app/views/workarea/storefront/style_guides/components/_afterpay_dialog.html.haml +92 -0
  62. data/bin/rails +19 -0
  63. data/bin/test +5 -0
  64. data/config/initializers/appends.rb +34 -0
  65. data/config/initializers/workarea.rb +17 -0
  66. data/config/locales/en.yml +107 -0
  67. data/config/routes.rb +15 -0
  68. data/four_equal_paymnets.svg +1 -0
  69. data/lib/workarea/afterpay/bogus_gateway.rb +211 -0
  70. data/lib/workarea/afterpay/engine.rb +14 -0
  71. data/lib/workarea/afterpay/gateway.rb +121 -0
  72. data/lib/workarea/afterpay/response.rb +17 -0
  73. data/lib/workarea/afterpay/version.rb +5 -0
  74. data/lib/workarea/afterpay.rb +59 -0
  75. data/test/dummy/Rakefile +6 -0
  76. data/test/dummy/bin/bundle +3 -0
  77. data/test/dummy/bin/rails +4 -0
  78. data/test/dummy/bin/rake +4 -0
  79. data/test/dummy/bin/setup +30 -0
  80. data/test/dummy/bin/update +26 -0
  81. data/test/dummy/bin/yarn +11 -0
  82. data/test/dummy/config/application.rb +30 -0
  83. data/test/dummy/config/boot.rb +5 -0
  84. data/test/dummy/config/cable.yml +10 -0
  85. data/test/dummy/config/environment.rb +5 -0
  86. data/test/dummy/config/environments/development.rb +51 -0
  87. data/test/dummy/config/environments/production.rb +88 -0
  88. data/test/dummy/config/environments/test.rb +44 -0
  89. data/test/dummy/config/initializers/application_controller_renderer.rb +8 -0
  90. data/test/dummy/config/initializers/assets.rb +14 -0
  91. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  92. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  93. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  94. data/test/dummy/config/initializers/inflections.rb +16 -0
  95. data/test/dummy/config/initializers/mime_types.rb +4 -0
  96. data/test/dummy/config/initializers/new_framework_defaults.rb +18 -0
  97. data/test/dummy/config/initializers/session_store.rb +3 -0
  98. data/test/dummy/config/initializers/workarea.rb +5 -0
  99. data/test/dummy/config/initializers/wrap_parameters.rb +9 -0
  100. data/test/dummy/config/locales/en.yml +33 -0
  101. data/test/dummy/config/puma.rb +56 -0
  102. data/test/dummy/config/routes.rb +5 -0
  103. data/test/dummy/config/secrets.yml +32 -0
  104. data/test/dummy/config/spring.rb +6 -0
  105. data/test/dummy/config.ru +5 -0
  106. data/test/dummy/db/seeds.rb +2 -0
  107. data/test/dummy/log/.keep +0 -0
  108. data/test/integration/workarea/storefront/afterpay_integration_test.rb +242 -0
  109. data/test/models/workarea/afterpay_order_test.rb +10 -0
  110. data/test/models/workarea/payment/afterpay_payment_integration_test.rb +67 -0
  111. data/test/services/workarea/afterpay/order_builder_test.rb +88 -0
  112. data/test/system/workarea/storefront/afterpay_product_test.rb +51 -0
  113. data/test/system/workarea/storefront/cart_system_test.decorator +83 -0
  114. data/test/system/workarea/storefront/logged_in_checkout_system_test.decorator +10 -0
  115. data/test/teaspoon_env.rb +6 -0
  116. data/test/test_helper.rb +10 -0
  117. data/test/view_models/workarea/storefront/afterpay_view_model_test.rb +100 -0
  118. data/test/view_models/workarea/storefront/product_view_model_afterpay_test.rb +78 -0
  119. data/workarea-afterpay.gemspec +23 -0
  120. metadata +189 -0
@@ -0,0 +1,36 @@
1
+ module Workarea
2
+ module Admin
3
+ class AfterpayConfigurationViewModel < ApplicationViewModel
4
+ include Storefront::AfterpayConfiguration
5
+
6
+ def au_limits
7
+ return unless Workarea::Afterpay.merchant_id(:au).present?
8
+ limits = afterpay_configuration(:au).first
9
+ {
10
+ min: min_price(limits),
11
+ max: max_price(limits)
12
+ }
13
+ end
14
+
15
+ def us_limits
16
+ return unless Workarea::Afterpay.merchant_id(:us).present?
17
+ limits = afterpay_configuration(:us).first
18
+ {
19
+ min: min_price(limits),
20
+ max: max_price(limits)
21
+ }
22
+ end
23
+
24
+ private
25
+
26
+ def min_price(limits)
27
+ return 0.to_m unless limits["minimumAmount"].present?
28
+ limits["minimumAmount"]["amount"].to_m
29
+ end
30
+
31
+ def max_price(limits)
32
+ limits["maximumAmount"]["amount"].to_m
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ module Workarea
2
+ module Storefront
3
+ module AfterpayConfiguration
4
+ class AfterpayConfigurationError < StandardError; end
5
+ # get the configuration for afterpay
6
+ # this will be used to determine elgibility
7
+ # for displaying the afterpay payment option
8
+ def afterpay_configuration(location)
9
+ merchant_id = Workarea::Afterpay.merchant_id(location)
10
+ key = "afterpay_configuration/#{merchant_id}"
11
+ afterpay_configuration = begin
12
+ Rails.cache.fetch(key, expires_in: Workarea.config.cache_expirations.afterpay_configuration) do
13
+ gateway = Workarea::Afterpay.gateway(location)
14
+ response = gateway.get_configuration
15
+ raise AfterpayConfigurationError unless response.success?
16
+ response.body
17
+ end
18
+ end
19
+ rescue
20
+ # avoids caching a failed API response
21
+ nil
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,89 @@
1
+ module Workarea
2
+ module Storefront
3
+ class AfterpayViewModel < ApplicationViewModel
4
+
5
+ # Orders must be between the min and max order total to qualify.
6
+ def order_total_in_range?
7
+ return unless afterpay_configuration.present?
8
+ eligible_options.present?
9
+ end
10
+
11
+ # Show if admin settings are enabled, there are configuration options returned
12
+ # from the API and the currency code is valid.
13
+ def show?
14
+ return unless afterpay_settings.enabled?
15
+ return unless valid_international_order?
16
+ return unless afterpay_configuration.present?
17
+ afterpay_country.present?
18
+ end
19
+
20
+ def show_on_cart?
21
+ show? && afterpay_settings.display_on_cart?
22
+ end
23
+
24
+ def show_on_pdp?
25
+ show? && afterpay_settings.display_on_pdp?
26
+ end
27
+
28
+ # TODO - handle what to display if there are multiple
29
+ # eligible display options. Docs do not seem to
30
+ # indicate there would ever be more than one.
31
+ def display_option
32
+ eligible_options.first
33
+ end
34
+
35
+ def installment_price
36
+ order.order_balance / Workarea.config.afterpay[:installment_count]
37
+ end
38
+
39
+ def min_price
40
+ config = afterpay_configuration.first
41
+ return 0.to_m unless config[:minimumAmount].present?
42
+ config[:minimumAmount][:amount].to_m
43
+ end
44
+
45
+ def max_price
46
+ config = afterpay_configuration.first
47
+ config[:maximumAmount][:amount].to_m
48
+ end
49
+
50
+ def afterpay_country
51
+ Workarea.config.afterpay[:currency_country_map][currency.to_sym]
52
+ end
53
+
54
+ private
55
+ def eligible_options
56
+ ap_options = afterpay_configuration.select do |ap|
57
+ order.order_balance >= min_price && order.order_balance <= max_price
58
+ end
59
+ end
60
+
61
+ def afterpay_configuration
62
+ options[:afterpay_configuration]
63
+ end
64
+
65
+ def order
66
+ @order ||= begin
67
+ o = options[:order]
68
+ Workarea::Storefront::OrderViewModel.new(o)
69
+ end
70
+ end
71
+
72
+ def currency
73
+ order.total_price.currency.iso_code
74
+ end
75
+
76
+ def afterpay_settings
77
+ @afterpay_settings ||= Workarea::Afterpay::Configuration.current
78
+ end
79
+
80
+ # Handles the various International Order plugins Workarea supports
81
+ # This method ensures that the currency the international order is using
82
+ # is supported by afterpay
83
+ def valid_international_order?
84
+ international_currency = order.try(:currency) || currency
85
+ Workarea.config.afterpay[:currency_country_map][international_currency.to_sym].present? && international_currency == currency
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,12 @@
1
+ module Workarea
2
+ decorate Storefront::CartViewModel, with: :afterpay do
3
+ decorated do
4
+ include Storefront::AfterpayConfiguration
5
+ end
6
+
7
+ def afterpay
8
+ @afterpay ||= Storefront::AfterpayViewModel.new(nil, {afterpay_configuration: afterpay_configuration(order.afterpay_location), order: order})
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,32 @@
1
+ module Workarea
2
+ decorate Storefront::Checkout::PaymentViewModel, with: :afterpay do
3
+ decorated do
4
+ include Storefront::AfterpayConfiguration
5
+ delegate :afterpay?, to: :payment
6
+ end
7
+
8
+ def allow_redirect_to_afterpay?
9
+ # only allow a redirect to afterpay if the tender has a token and
10
+ # that token has not been redirected to afterpay already.
11
+ # a token that is ready to capture has come back the afterpay site
12
+ # with a success. This token is now 'hot' and can be captured
13
+ afterpay_token.present? && !payment.afterpay.ready_to_capture?
14
+ end
15
+
16
+ def afterpay_token
17
+ return unless payment.afterpay?
18
+ payment.afterpay.token
19
+ end
20
+
21
+ def using_new_card?
22
+ super && !afterpay?
23
+ end
24
+
25
+ def afterpay
26
+ order = Workarea::Order.find(payment.id)
27
+
28
+ Storefront::AfterpayViewModel.new(order, { afterpay_configuration: afterpay_configuration(order.afterpay_location), order: order })
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,50 @@
1
+ module Workarea
2
+ decorate Storefront::ProductViewModel, with: :afterpay do
3
+ decorated do
4
+ include Storefront::AfterpayConfiguration
5
+ end
6
+
7
+ def show_afterpay?
8
+ return unless pricing.has_prices?
9
+ return unless afterpay_settings.enabled? && afterpay_settings.display_on_pdp?
10
+ return unless afterpay_location_configuration.present?
11
+
12
+ afterpay_location_configuration.any? do |ap|
13
+ pricing.sell_min_price >= min_price && pricing.sell_min_price <= max_price
14
+ end
15
+ end
16
+
17
+ def installment_price
18
+ pricing.sell_min_price / Workarea::Afterpay.config[:installment_count]
19
+ end
20
+
21
+ private
22
+
23
+ def min_price
24
+ config = afterpay_location_configuration.first.with_indifferent_access
25
+ return 0.to_m unless config[:minimumAmount].present?
26
+ config[:minimumAmount][:amount].to_m
27
+ end
28
+
29
+ def max_price
30
+ config = afterpay_location_configuration.first.with_indifferent_access
31
+ config[:maximumAmount][:amount].to_m
32
+ end
33
+
34
+ def afterpay_location
35
+ currency = pricing.sell_min_price.currency.iso_code
36
+ location = Workarea::Afterpay.config[:currency_country_map][currency.to_sym]
37
+ return unless location.present?
38
+
39
+ location.to_sym.downcase
40
+ end
41
+
42
+ def afterpay_location_configuration
43
+ afterpay_configuration(afterpay_location)
44
+ end
45
+
46
+ def afterpay_settings
47
+ @afterpay_settings ||= Workarea::Afterpay::Configuration.current
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,59 @@
1
+ - @page_title = t('workarea.admin.afterpay_configuration.edit.title')
2
+
3
+ .view
4
+ .view__header
5
+ .view__heading
6
+ = link_to "↑ #{t('workarea.admin.search_settings.show.dashboard_link')}", settings_dashboards_path
7
+ %h1= t('workarea.admin.afterpay_configuration.edit.title')
8
+
9
+ .view__container
10
+ = form_tag afterpay_configuration_path, method: :patch, data: { unsaved_changes: '' } do
11
+ .grid
12
+ .grid__cell
13
+ %p= t('workarea.admin.afterpay_configuration.edit.box_help_text')
14
+
15
+ -if @configuration.us_limits.present?
16
+ .grid__cell.grid__cell--33.grid__cell--25-at-medium
17
+ .property
18
+ = label_tag 'uslimits', t('workarea.admin.afterpay_configuration.edit.us_limit'), class: 'property__name'
19
+ = "#{@configuration.us_limits[:min]} - #{@configuration.us_limits[:max]}"
20
+
21
+ -if @configuration.au_limits.present?
22
+ .grid__cell.grid__cell--33.grid__cell--25-at-medium
23
+ .property
24
+ = label_tag 'uslimits', t('workarea.admin.afterpay_configuration.edit.au_limit'), class: 'property__name'
25
+ = "#{@configuration.au_limits[:min]} - #{@configuration.au_limits[:max]}"
26
+
27
+ .grid__cell
28
+
29
+ .property
30
+ %span.property__name
31
+ = t('workarea.admin.afterpay_configuration.edit.enabled')
32
+ = link_to '#enabled', data: { tooltip: '' } do
33
+ = inline_svg('workarea/admin/icons/help.svg', class: 'svg-icon svg-icon--small svg-icon--blue', title: t('workarea.admin.afterpay_configuration.edit.enabled'))
34
+ #enabled.tooltip-content
35
+ %p= t('workarea.admin.afterpay_configuration.edit.help.enabled')
36
+
37
+ = toggle_button_for 'enabled', @configuration.enabled?
38
+
39
+ %span.property__name
40
+ = t('workarea.admin.afterpay_configuration.edit.show_on_pdp')
41
+ = link_to '#show-on-pdp', data: { tooltip: '' } do
42
+ = inline_svg('workarea/admin/icons/help.svg', class: 'svg-icon svg-icon--small svg-icon--blue', title: t('workarea.admin.afterpay_configuration.edit.show_on_pdp'))
43
+ #show-on-pdp.tooltip-content
44
+ %p= t('workarea.admin.afterpay_configuration.edit.help.show_on_pdp')
45
+
46
+ = toggle_button_for 'display_on_pdp', @configuration.display_on_pdp?
47
+
48
+ %span.property__name
49
+ = t('workarea.admin.afterpay_configuration.edit.show_on_cart')
50
+ = link_to '#show-on-cart', data: { tooltip: '' } do
51
+ = inline_svg('workarea/admin/icons/help.svg', class: 'svg-icon svg-icon--small svg-icon--blue', title: t('workarea.admin.afterpay_configuration.edit.show_on_cart'))
52
+ #show-on-cart.tooltip-content
53
+ %p= t('workarea.admin.afterpay_configuration.edit.help.show_on_cart')
54
+
55
+ = toggle_button_for 'display_on_cart', @configuration.display_on_cart?
56
+
57
+ .workflow-bar
58
+ .grid.grid--auto.grid--right.grid--middle
59
+ .grid__cell= button_tag t('workarea.admin.afterpay_configuration.edit.button'), value: 'save_settings', class: 'workflow-bar__button workflow-bar__button--update'
@@ -0,0 +1,2 @@
1
+ %li= t('workarea.afterpay.tender_description', installment_price: number_to_currency(tender.installment_price), installment_count: Workarea.config.afterpay[:installment_count])
2
+
@@ -0,0 +1 @@
1
+ %li{ class: "primary-nav__item" }= link_to t('workarea.admin.shared.primary_nav.afterpay_configuration_title'), edit_afterpay_configuration_path, class: navigation_link_classes(edit_afterpay_configuration_path)
@@ -0,0 +1,40 @@
1
+ .afterpay-dialog
2
+ .afterpay-dialog__header
3
+ .grid
4
+ .grid__cell
5
+ %p= t('workarea.afterpay.dialog.us.installments_by')
6
+ = image_tag('workarea/storefront/afterpay/afterpay_logo.png', alt: 'Afterpay Logo', class: "afterpay-dialog__logo")
7
+ %h2.afterpay-dialog__heading
8
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.us.shop_now')
9
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.us.enjoy_now')
10
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.us.pay_later')
11
+ .afterpay-dialog__description= t('workarea.afterpay.dialog.us.description')
12
+
13
+ .afterpay-dialog__steps
14
+ .grid
15
+ .grid__cell.grid__cell--33-at-medium
16
+ .afterpay-dialog__step
17
+ = inline_svg 'workarea/storefront/afterpay/us/select_installments.svg', class: 'afterpay-dialog__step-icon'
18
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.steps.first.heading')
19
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.us.steps.first.body')
20
+ .grid__cell.grid__cell--33-at-medium
21
+ .afterpay-dialog__step
22
+ = inline_svg 'workarea/storefront/afterpay/us/complete_checkout.svg', class: 'afterpay-dialog__step-icon'
23
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.steps.second.heading')
24
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.us.steps.second.body')
25
+ .grid__cell.grid__cell--33-at-medium
26
+ .afterpay-dialog__step
27
+ = inline_svg 'workarea/storefront/afterpay/us/four_equal_payments.svg', class: 'afterpay-dialog__step-icon'
28
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.steps.third.heading')
29
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.us.steps.third.body')
30
+ .afterpay-dialog__footer
31
+ %h5.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.footer_heading')
32
+ %ol.afterpay-dialog__requirements
33
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.first')
34
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.second')
35
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.third')
36
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.fourth')
37
+ %p.afterpay-dialog__terms
38
+ = t('workarea.afterpay.dialog.us.terms.')
39
+ = link_to 'https://www.afterpay.com/purchase-payment-agreement','https://www.afterpay.com/purchase-payment-agreement', target: '_blank', rel: 'noopener'
40
+ %p.afterpay-dialog__copyright= t('workarea.afterpay.dialog.us.copyright')
@@ -0,0 +1,40 @@
1
+ .afterpay-dialog.afterpay-dialog--aus
2
+ .afterpay-dialog__header
3
+ .grid
4
+ .grid__cell.grid__cell--66-at-medium
5
+ = image_tag('workarea/storefront/afterpay/afterpay_logo.png', alt: 'Afterpay Logo', class: "afterpay-dialog__logo")
6
+ %h2.afterpay-dialog__heading
7
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.aus.shop_now')
8
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.aus.enjoy_now')
9
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.aus.pay_later')
10
+ .afterpay-dialog__description= t('workarea.afterpay.dialog.aus.description')
11
+ .grid__cell.grid__cell--33-at-medium
12
+ = image_tag('workarea/storefront/afterpay/aus/dialog_header_image.png', alt: 'Afterpay background', class: "afterpay-dialog__header-image")
13
+
14
+ .afterpay-dialog__steps
15
+ .grid
16
+ .grid__cell.grid__cell--33-at-medium
17
+ .afterpay-dialog__step
18
+ = image_tag('workarea/storefront/afterpay/aus/step_1.png', alt: 'Select Afterpay', class: "afterpay-dialog__step-icon")
19
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.steps.first.heading')
20
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.aus.steps.first.body')
21
+ .grid__cell.grid__cell--33-at-medium
22
+ .afterpay-dialog__step
23
+ = image_tag('workarea/storefront/afterpay/aus/step_2.png', alt: 'Complete Checkout', class: "afterpay-dialog__step-icon")
24
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.steps.second.heading')
25
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.aus.steps.second.body')
26
+ .grid__cell.grid__cell--33-at-medium
27
+ .afterpay-dialog__step
28
+ = image_tag('workarea/storefront/afterpay/aus/step_3.png', alt: 'Pay over 4 equal payments', class: "afterpay-dialog__step-icon")
29
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.steps.third.heading')
30
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.aus.steps.third.body')
31
+ .afterpay-dialog__footer
32
+ %h5.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.footer_heading')
33
+ %ol.afterpay-dialog__requirements
34
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.aus.requirements.first')
35
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.aus.requirements.second')
36
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.aus.requirements.third')
37
+ %p.afterpay-dialog__terms
38
+ = t('workarea.afterpay.dialog.aus.terms')
39
+ = link_to 'https://www.afterpay.com/terms', 'https://www.afterpay.com/terms', target: '_blank', rel: 'noopener'
40
+ %p.afterpay-dialog__copyright= t('workarea.afterpay.dialog.aus.copyright')
@@ -0,0 +1,9 @@
1
+ -if @cart.afterpay.show_on_cart?
2
+ -if @cart.afterpay.order_total_in_range?
3
+ %p.cart__checkout-action.cart__checkout-action--afterpay
4
+ #{t('workarea.storefront.carts.afterpay', installment_price: number_to_currency(@cart.afterpay.installment_price), installment_count: Workarea.config.afterpay[:installment_count])} #{image_tag('https://static.afterpay.com/integration/product-page/logo-afterpay-colour.png')}
5
+ %span= link_to 'More Info', learn_more_link(@cart.total_price), data: { dialog_button: '' }
6
+ - else
7
+ %p
8
+ #{image_tag('https://static.afterpay.com/integration/product-page/logo-afterpay-colour.png')}
9
+ #{t('workarea.storefront.afterpay.ineligible_order_total', min: number_to_currency(@cart.afterpay.min_price), max: number_to_currency(@cart.afterpay.max_price))}
@@ -0,0 +1,17 @@
1
+ -if @step.afterpay.show?
2
+ -if @step.afterpay.order_total_in_range?
3
+ .checkout-payment__primary-method{ class: ('checkout-payment__primary-method--selected' if @step.afterpay?) }
4
+ .button-property
5
+ = hidden_field_tag 'from_checkout', 'from_checkout', id: nil
6
+ .value= radio_button_tag 'payment', 'afterpay', step.afterpay?, data: { afterpay_token: (@step.afterpay_token if @step.allow_redirect_to_afterpay?), afterpay_country: @step.afterpay.afterpay_country }
7
+ = label_tag 'payment[afterpay]', nil, class: 'button-property__name' do
8
+ %span.button-property__text= image_tag('https://static.afterpay.com/integration/product-page/logo-afterpay-colour.png')
9
+ %p.checkout-payment__primary-method-description
10
+ %span #{t('workarea.storefront.checkouts.afterpay', installment_price: number_to_currency(@step.afterpay.installment_price), installment_count: Workarea.config.afterpay[:installment_count])}
11
+ %span= link_to(t('workarea.storefront.afterpay.learn_more'), learn_more_link(@cart.total_price), data: { popup_button: { width: 600, height: 800 }})
12
+ %p
13
+ %span= t('workarea.storefront.afterpay.on_continue')
14
+ - else
15
+ %p
16
+ #{image_tag('https://static.afterpay.com/integration/product-page/logo-afterpay-colour.png')}
17
+ #{t('workarea.storefront.afterpay.ineligible_order_total', min: number_to_currency(@cart.afterpay.min_price), max: number_to_currency(@cart.afterpay.max_price))}
@@ -0,0 +1,4 @@
1
+ %p{ style: "margin: 0 0 6px; font: 13px/1.5 arial; color: #{@config.text_color};" }
2
+ = t('workarea.afterpay.tender_description', installment_price: number_to_currency(tender.installment_price), installment_count: Workarea.config.afterpay[:installment_count])
3
+
4
+
@@ -0,0 +1 @@
1
+ <%= t('workarea.afterpay.tender_description', installment_price: number_to_currency(tender.installment_price), installment_count: Workarea.config.afterpay[:installment_count]) %>
@@ -0,0 +1,5 @@
1
+ .data-card
2
+ .data-card__cell
3
+ %p.data-card__line
4
+ = t('workarea.afterpay.tender_description', installment_price: number_to_currency(tender.installment_price), installment_count: Workarea.config.afterpay[:installment_count])
5
+
@@ -0,0 +1,3 @@
1
+ -if @product.show_afterpay?
2
+ %p.cart__checkout-action.cart__checkout-action--afterpay.cart__ #{t('workarea.storefront.products.afterpay', installment_price: number_to_currency(@product.installment_price), installment_count: Workarea.config.afterpay[:installment_count])} #{image_tag('https://static.afterpay.com/integration/product-page/logo-afterpay-colour.png')}
3
+ %span= link_to t('workarea.storefront.afterpay.learn_more'), learn_more_link(@product.sell_min_price), data: { popup_button: { width: 600, height: 800 }}
@@ -0,0 +1,92 @@
1
+ #afterpay-dialog.style-guide__subsection
2
+
3
+ %h3= link_to_style_guide('components', 'afterpay_dialog')
4
+
5
+ %p Displays the US Afterpay dialog according to designs provided
6
+
7
+ .style-guide__example-block
8
+ .afterpay-dialog
9
+ .afterpay-dialog__header
10
+ .grid
11
+ .grid__cell
12
+ %p= t('workarea.afterpay.dialog.us.installments_by')
13
+ = image_tag('workarea/storefront/afterpay/afterpay_logo.png', alt: 'Afterpay Logo', class: "afterpay-dialog__logo")
14
+ %h2.afterpay-dialog__heading
15
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.us.shop_now')
16
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.us.enjoy_now')
17
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.us.pay_later')
18
+ .afterpay-dialog__description= t('workarea.afterpay.dialog.us.description')
19
+
20
+ .afterpay-dialog__steps
21
+ .grid
22
+ .grid__cell.grid__cell--33-at-medium
23
+ .afterpay-dialog__step
24
+ = inline_svg 'workarea/storefront/afterpay/us/select_installments.svg', class: 'afterpay-dialog__step-icon'
25
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.steps.first.heading')
26
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.us.steps.first.body')
27
+ .grid__cell.grid__cell--33-at-medium
28
+ .afterpay-dialog__step
29
+ = inline_svg 'workarea/storefront/afterpay/us/complete_checkout.svg', class: 'afterpay-dialog__step-icon'
30
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.steps.second.heading')
31
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.us.steps.second.body')
32
+ .grid__cell.grid__cell--33-at-medium
33
+ .afterpay-dialog__step
34
+ = inline_svg 'workarea/storefront/afterpay/us/four_equal_payments.svg', class: 'afterpay-dialog__step-icon'
35
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.steps.third.heading')
36
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.us.steps.third.body')
37
+ .afterpay-dialog__footer
38
+ %h5.afterpay-dialog__heading= t('workarea.afterpay.dialog.us.footer_heading')
39
+ %ol.afterpay-dialog__requirements
40
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.first')
41
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.second')
42
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.third')
43
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.us.requirements.fourth')
44
+ %p.afterpay-dialog__terms
45
+ = t('workarea.afterpay.dialog.us.terms.')
46
+ = link_to 'https://www.afterpay.com/purchase-payment-agreement','https://www.afterpay.com/purchase-payment-agreement', target: '_blank', rel: 'noopener'
47
+ %p.afterpay-dialog__copyright= t('workarea.afterpay.dialog.us.copyright')
48
+
49
+
50
+ %p Displays a different Afterpay dialog for AUS
51
+
52
+ .style-guide__example-block
53
+ .afterpay-dialog.afterpay-dialog--aus
54
+ .afterpay-dialog__header
55
+ .grid
56
+ .grid__cell.grid__cell--66-at-medium
57
+ = image_tag('workarea/storefront/afterpay/afterpay_logo.png', alt: 'Afterpay Logo', class: "afterpay-dialog__logo")
58
+ %h2.afterpay-dialog__heading
59
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.aus.shop_now')
60
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.aus.enjoy_now')
61
+ %span.afterpay-dialog__subheading-part= t('workarea.afterpay.dialog.aus.pay_later')
62
+ .afterpay-dialog__description= t('workarea.afterpay.dialog.aus.description')
63
+ .grid__cell.grid__cell--33-at-medium
64
+ = image_tag('workarea/storefront/afterpay/aus/dialog_header_image.png', alt: 'Afterpay background', class: "afterpay-dialog__header-image")
65
+
66
+ .afterpay-dialog__steps
67
+ .grid
68
+ .grid__cell.grid__cell--33-at-medium
69
+ .afterpay-dialog__step
70
+ = image_tag('workarea/storefront/afterpay/aus/step_1.png', alt: 'Select Afterpay', class: "afterpay-dialog__step-icon")
71
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.steps.first.heading')
72
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.aus.steps.first.body')
73
+ .grid__cell.grid__cell--33-at-medium
74
+ .afterpay-dialog__step
75
+ = image_tag('workarea/storefront/afterpay/aus/step_2.png', alt: 'Complete Checkout', class: "afterpay-dialog__step-icon")
76
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.steps.second.heading')
77
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.aus.steps.second.body')
78
+ .grid__cell.grid__cell--33-at-medium
79
+ .afterpay-dialog__step
80
+ = image_tag('workarea/storefront/afterpay/aus/step_3.png', alt: 'Pay over 4 equal payments', class: "afterpay-dialog__step-icon")
81
+ %h3.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.steps.third.heading')
82
+ .afterpay-dialog__step-body= t('workarea.afterpay.dialog.aus.steps.third.body')
83
+ .afterpay-dialog__footer
84
+ %h5.afterpay-dialog__heading= t('workarea.afterpay.dialog.aus.footer_heading')
85
+ %ol.afterpay-dialog__requirements
86
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.aus.requirements.first')
87
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.aus.requirements.second')
88
+ %li.afterpay-dialog__requirement= t('workarea.afterpay.dialog.aus.requirements.third')
89
+ %p.afterpay-dialog__terms
90
+ = t('workarea.afterpay.dialog.aus.terms')
91
+ = link_to 'https://www.afterpay.com/terms', 'https://www.afterpay.com/terms', target: '_blank', rel: 'noopener'
92
+ %p.afterpay-dialog__copyright= t('workarea.afterpay.dialog.aus.copyright')
data/bin/rails ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
6
+ ENGINE_PATH = File.expand_path('../../lib/workarea/afterpay/engine', __FILE__)
7
+
8
+ # Set up gems listed in the Gemfile.
9
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
10
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
11
+
12
+ require "action_controller/railtie"
13
+ require "action_view/railtie"
14
+ require "action_mailer/railtie"
15
+ require "rails/test_unit/railtie"
16
+ require "sprockets/railtie"
17
+ require 'teaspoon-mocha'
18
+
19
+ require 'rails/engine/commands'
data/bin/test ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $: << File.expand_path(File.expand_path("../../test", __FILE__))
3
+
4
+ require "bundler/setup"
5
+ require "rails/plugin/test"
@@ -0,0 +1,34 @@
1
+ Workarea::Plugin.append_partials(
2
+ 'storefront.product_pricing_details',
3
+ 'workarea/storefront/products/afterpay_pricing'
4
+ )
5
+
6
+ Workarea::Plugin.append_partials(
7
+ 'storefront.payment_method',
8
+ 'workarea/storefront/checkouts/afterpay_payment'
9
+ )
10
+
11
+ Workarea::Plugin.append_partials(
12
+ 'storefront.cart_checkout_actions',
13
+ 'workarea/storefront/carts/afterpay'
14
+ )
15
+
16
+ Workarea::Plugin.append_javascripts(
17
+ 'storefront.config',
18
+ 'workarea/storefront/afterpay/config'
19
+ )
20
+
21
+ Workarea::Plugin.append_javascripts(
22
+ 'storefront.modules',
23
+ 'workarea/storefront/afterpay/modules/afterpay_redirect'
24
+ )
25
+
26
+ Workarea::Plugin.append_stylesheets(
27
+ 'storefront.components',
28
+ 'workarea/storefront/components/afterpay_dialog'
29
+ )
30
+
31
+ Workarea.append_partials(
32
+ "admin.settings_menu",
33
+ "workarea/admin/shared/afterpay_configuration_link"
34
+ )
@@ -0,0 +1,17 @@
1
+ Workarea.configure do |config|
2
+ config.cache_expirations.afterpay_configuration = 1.hour
3
+
4
+ config.tender_types.append(:afterpay)
5
+
6
+ config.afterpay = ActiveSupport::Configurable::Configuration.new
7
+ config.afterpay.api_timeout = 5
8
+ config.afterpay.open_timeout = 2
9
+ config.afterpay.installment_count = 4
10
+
11
+ config.afterpay.test = !Rails.env.production?
12
+
13
+ config.afterpay.currency_country_map = {
14
+ "USD": "US",
15
+ "AUD": "AU"
16
+ }
17
+ end