workarea-gift_cards 3.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +20 -0
  3. data/.eslintignore +2 -0
  4. data/.eslintrc +24 -0
  5. data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  6. data/.github/ISSUE_TEMPLATE/documentation-request.md +17 -0
  7. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  8. data/.gitignore +15 -0
  9. data/.scss-lint.yml +188 -0
  10. data/.yardopts +1 -0
  11. data/CHANGELOG.md +485 -0
  12. data/CODE_OF_CONDUCT.md +3 -0
  13. data/CONTRIBUTING.md +3 -0
  14. data/Gemfile +7 -0
  15. data/LICENSE +52 -0
  16. data/README.md +119 -0
  17. data/Rakefile +53 -0
  18. data/app/assets/images/workarea/admin/payment_icons/gift_card.svg +1 -0
  19. data/app/assets/images/workarea/storefront/payment_icons/gift_card.svg +1 -0
  20. data/app/controllers/workarea/admin/data_file_exports_controller.decorator +28 -0
  21. data/app/controllers/workarea/admin/payment_gift_cards_controller.rb +78 -0
  22. data/app/controllers/workarea/api/admin/payment_gift_cards_controller.rb +49 -0
  23. data/app/controllers/workarea/api/storefront/checkouts_controller.decorator +10 -0
  24. data/app/controllers/workarea/api/storefront/gift_cards_controller.rb +26 -0
  25. data/app/controllers/workarea/storefront/checkouts_controller.decorator +24 -0
  26. data/app/controllers/workarea/storefront/gift_cards_controller.rb +24 -0
  27. data/app/mailers/workarea/storefront/gift_card_mailer.rb +28 -0
  28. data/app/models/workarea/catalog/customizations/gift_card.rb +9 -0
  29. data/app/models/workarea/catalog/product.decorator +11 -0
  30. data/app/models/workarea/order/item.decorator +7 -0
  31. data/app/models/workarea/payment/authorize/gift_card.rb +43 -0
  32. data/app/models/workarea/payment/capture/gift_card.rb +25 -0
  33. data/app/models/workarea/payment/gift_card/redemption.rb +23 -0
  34. data/app/models/workarea/payment/gift_card.rb +186 -0
  35. data/app/models/workarea/payment/purchase/gift_card.rb +7 -0
  36. data/app/models/workarea/payment/refund/gift_card.rb +35 -0
  37. data/app/models/workarea/payment/tender/gift_card.rb +30 -0
  38. data/app/models/workarea/payment.decorator +19 -0
  39. data/app/models/workarea/search/admin/order.decorator +9 -0
  40. data/app/models/workarea/search/admin/payment_gift_card.rb +46 -0
  41. data/app/queries/workarea/admin_redemptions_export.rb +84 -0
  42. data/app/queries/workarea/order_item_details.decorator +11 -0
  43. data/app/queries/workarea/search/admin_gift_cards.rb +20 -0
  44. data/app/seeds/workarea/gift_card_seeds.rb +44 -0
  45. data/app/services/workarea/checkout/steps/gift_card.rb +49 -0
  46. data/app/view_models/workarea/admin/payment_gift_card_view_model.rb +11 -0
  47. data/app/view_models/workarea/storefront/checkout/payment_view_model.decorator +32 -0
  48. data/app/view_models/workarea/storefront/checkout/summary_view_model.decorator +11 -0
  49. data/app/view_models/workarea/storefront/gift_card_order_pricing.rb +36 -0
  50. data/app/view_models/workarea/storefront/order_view_model.decorator +27 -0
  51. data/app/view_models/workarea/storefront/product_templates/gift_card_view_model.rb +4 -0
  52. data/app/views/workarea/admin/activities/_payment_gift_card_create.html.haml +12 -0
  53. data/app/views/workarea/admin/activities/_payment_gift_card_destroy.html.haml +10 -0
  54. data/app/views/workarea/admin/activities/_payment_gift_card_update.html.haml +14 -0
  55. data/app/views/workarea/admin/orders/tenders/_gift_card.html.haml +5 -0
  56. data/app/views/workarea/admin/payment_gift_cards/_aux_navigation.html.haml +4 -0
  57. data/app/views/workarea/admin/payment_gift_cards/_cards.html.haml +74 -0
  58. data/app/views/workarea/admin/payment_gift_cards/_menu.html.haml +1 -0
  59. data/app/views/workarea/admin/payment_gift_cards/_summary.html.haml +11 -0
  60. data/app/views/workarea/admin/payment_gift_cards/edit.html.haml +37 -0
  61. data/app/views/workarea/admin/payment_gift_cards/index.html.haml +95 -0
  62. data/app/views/workarea/admin/payment_gift_cards/new.html.haml +43 -0
  63. data/app/views/workarea/admin/payment_gift_cards/redemptions.html.haml +29 -0
  64. data/app/views/workarea/admin/payment_gift_cards/show.html.haml +19 -0
  65. data/app/views/workarea/api/storefront/checkouts/steps/_gift_card.json.jbuilder +6 -0
  66. data/app/views/workarea/api/storefront/gift_cards/balance.json.jbuilder +3 -0
  67. data/app/views/workarea/api/storefront/orders/tenders/_gift_card.json.jbuilder +3 -0
  68. data/app/views/workarea/storefront/checkouts/_gift_card_error.html.haml +6 -0
  69. data/app/views/workarea/storefront/checkouts/_gift_card_payment.html.haml +28 -0
  70. data/app/views/workarea/storefront/checkouts/_gift_card_summary.html.haml +6 -0
  71. data/app/views/workarea/storefront/gift_card_mailer/created.html.haml +15 -0
  72. data/app/views/workarea/storefront/gift_cards/index.html.haml +17 -0
  73. data/app/views/workarea/storefront/order_mailer/_gift_card_summary.html.haml +5 -0
  74. data/app/views/workarea/storefront/order_mailer/tenders/_gift_card.html.haml +5 -0
  75. data/app/views/workarea/storefront/orders/_gift_card_summary.html.haml +6 -0
  76. data/app/views/workarea/storefront/orders/tenders/_gift_card.html.haml +9 -0
  77. data/app/views/workarea/storefront/products/templates/_gift_card.html.haml +77 -0
  78. data/app/workers/workarea/create_ordered_gift_cards.rb +47 -0
  79. data/app/workers/workarea/log_gift_card_redemption.rb +32 -0
  80. data/app/workers/workarea/send_gift_card_notifications.rb +20 -0
  81. data/bin/rails +18 -0
  82. data/config/initializers/append_points.rb +37 -0
  83. data/config/initializers/configuration.rb +8 -0
  84. data/config/initializers/jump_to_navigation.rb +3 -0
  85. data/config/locales/en.yml +82 -0
  86. data/config/routes.rb +31 -0
  87. data/lib/workarea/gift_cards/engine.rb +19 -0
  88. data/lib/workarea/gift_cards/version.rb +5 -0
  89. data/lib/workarea/gift_cards.rb +11 -0
  90. data/lib/workarea/mailer_previews/storefront/gift_card_mailer_preview.rb +18 -0
  91. data/test/documentation/workarea/api/admin/gift_cards_documentation_test.rb +82 -0
  92. data/test/documentation/workarea/api/storefront/gift_cards_documentation_test.rb +107 -0
  93. data/test/dummy/Rakefile +6 -0
  94. data/test/dummy/app/assets/config/manifest.js +4 -0
  95. data/test/dummy/app/assets/images/.keep +0 -0
  96. data/test/dummy/app/assets/javascripts/application.js +13 -0
  97. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  98. data/test/dummy/app/controllers/application_controller.rb +3 -0
  99. data/test/dummy/app/controllers/concerns/.keep +0 -0
  100. data/test/dummy/app/helpers/application_helper.rb +2 -0
  101. data/test/dummy/app/jobs/application_job.rb +2 -0
  102. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  103. data/test/dummy/app/models/concerns/.keep +0 -0
  104. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  105. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  106. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  107. data/test/dummy/bin/bundle +3 -0
  108. data/test/dummy/bin/rails +4 -0
  109. data/test/dummy/bin/rake +4 -0
  110. data/test/dummy/bin/setup +34 -0
  111. data/test/dummy/bin/update +29 -0
  112. data/test/dummy/config/application.rb +24 -0
  113. data/test/dummy/config/boot.rb +5 -0
  114. data/test/dummy/config/cable.yml +9 -0
  115. data/test/dummy/config/environment.rb +5 -0
  116. data/test/dummy/config/environments/development.rb +54 -0
  117. data/test/dummy/config/environments/production.rb +86 -0
  118. data/test/dummy/config/environments/test.rb +43 -0
  119. data/test/dummy/config/initializers/application_controller_renderer.rb +6 -0
  120. data/test/dummy/config/initializers/assets.rb +11 -0
  121. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  122. data/test/dummy/config/initializers/cookies_serializer.rb +5 -0
  123. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  124. data/test/dummy/config/initializers/inflections.rb +16 -0
  125. data/test/dummy/config/initializers/mime_types.rb +4 -0
  126. data/test/dummy/config/initializers/new_framework_defaults.rb +21 -0
  127. data/test/dummy/config/initializers/session_store.rb +3 -0
  128. data/test/dummy/config/initializers/workarea.rb +5 -0
  129. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  130. data/test/dummy/config/locales/en.yml +23 -0
  131. data/test/dummy/config/puma.rb +47 -0
  132. data/test/dummy/config/routes.rb +6 -0
  133. data/test/dummy/config/secrets.yml +22 -0
  134. data/test/dummy/config/spring.rb +6 -0
  135. data/test/dummy/config.ru +5 -0
  136. data/test/dummy/lib/assets/.keep +0 -0
  137. data/test/dummy/log/.keep +0 -0
  138. data/test/dummy/public/404.html +67 -0
  139. data/test/dummy/public/422.html +67 -0
  140. data/test/dummy/public/500.html +66 -0
  141. data/test/dummy/public/apple-touch-icon-precomposed.png +0 -0
  142. data/test/dummy/public/apple-touch-icon.png +0 -0
  143. data/test/dummy/public/favicon.ico +0 -0
  144. data/test/factories/gift_cards.rb +27 -0
  145. data/test/integration/workarea/admin/gift_card_integration_test.rb +53 -0
  146. data/test/integration/workarea/admin/gift_card_redemptions_export_integration_test.rb +104 -0
  147. data/test/integration/workarea/api/admin/gift_card_integration_test.rb +57 -0
  148. data/test/integration/workarea/api/storefront/balance_integration_test.rb +40 -0
  149. data/test/integration/workarea/api/storefront/checkout_integration_test.rb +161 -0
  150. data/test/integration/workarea/storefront/gift_card_integration_test.rb +222 -0
  151. data/test/models/workarea/catalog/gift_card_product_test.rb +15 -0
  152. data/test/models/workarea/gift_card_payment_test.rb +12 -0
  153. data/test/models/workarea/payment/gift_card_test.rb +127 -0
  154. data/test/models/workarea/payment/purchase/gift_card_test.rb +52 -0
  155. data/test/models/workarea/payment/refund/gift_card_test.rb +19 -0
  156. data/test/queries/workarea/admin_redemptions_export_test.rb +52 -0
  157. data/test/queries/workarea/gift_card_order_item_details_test.rb +11 -0
  158. data/test/services/workarea/checkout/steps/gift_card_test.rb +87 -0
  159. data/test/system/workarea/admin/gift_cards_system_test.rb +89 -0
  160. data/test/system/workarea/storefront/gift_cards_system_test.rb +400 -0
  161. data/test/test_helper.rb +10 -0
  162. data/test/view_models/workarea/storefront/checkout/gift_card_payment_view_model_test.rb +65 -0
  163. data/test/workers/workarea/create_ordered_gift_cards_test.rb +39 -0
  164. data/test/workers/workarea/log_gift_card_redemption_test.rb +19 -0
  165. data/workarea-gift_cards.gemspec +21 -0
  166. metadata +227 -0
@@ -0,0 +1,95 @@
1
+ - @page_title = t('workarea.admin.payment_gift_cards.index.title')
2
+
3
+ .view
4
+ .view__header
5
+ .grid.grid--middle.grid--center
6
+ .grid__cell.grid__cell--50
7
+ .view__heading
8
+ = link_to "↑ #{t('workarea.admin.orders.index.dashboard_link')}", orders_dashboards_path, class: 'view__dashboard-button'
9
+ %h1= t('workarea.admin.payment_gift_cards.index.title')
10
+
11
+ .view__container
12
+ .browsing-controls.browsing-controls--with-divider.browsing-controls--center{ class: ('browsing-controls--filters-displayed' unless @search.toggle_facets?) }
13
+ = form_tag payment_gift_cards_path, method: 'get', id: 'gift_cards_form' do
14
+ = facet_hidden_inputs(@search.facets)
15
+ .browsing-controls__sort
16
+ .property.property--inline
17
+ = label_tag 'sort', t('workarea.admin.search.sort_by'), class: 'property__name'
18
+ = select_tag :sort, options_for_select(@search.sorts, selected: @search.sort), data: { form_submitting_control: '' }
19
+
20
+ .browsing-controls__search
21
+ .search-form
22
+ = text_field_tag :q, params[:q], class: 'search-form__input', id: 'search_products', title: t('workarea.admin.search.keywords'), placeholder: t('workarea.admin.search.keywords')
23
+ = submit_tag 'search_gift_cards', class: 'search-form__button'
24
+
25
+ = render 'workarea/admin/shared/creation_date', search: @search, form_path: payment_gift_cards_path
26
+
27
+ - if @search.facets.present?
28
+ - @search.facets.each do |facet|
29
+ = render "workarea/admin/facets/#{facet.type}", facet: facet
30
+
31
+ - if @search.toggle_facets?
32
+ .browsing-controls__toggle-filters
33
+ %button.text-button{ type: 'button', data: { toggle_filters: '' } }= t('workarea.admin.search.show_filters')
34
+
35
+ = render 'workarea/admin/facets/applied', search: @search, reset_path: payment_gift_cards_path
36
+
37
+ %p.browsing-controls__count{ data: { browsing_controls_count: @search.total } }
38
+ = pluralize(@search.total, t('workarea.admin.payment_gift_cards.gift_card'))
39
+
40
+ - if @search.results.any?
41
+ %table.index-table
42
+ %thead
43
+ %tr
44
+ %th.index-table__control-cell
45
+ .checkbox
46
+ = check_box_tag 'select_all', nil, false, id: 'select_all', class: 'checkbox__input', data: { bulk_action_select_all: '' }
47
+ = label_tag 'select_all', t('workarea.admin.bulk_actions.select_all'), class: 'checkbox__label'
48
+ %th= t('workarea.admin.fields.token')
49
+ %th= t('workarea.admin.fields.from')
50
+ %th= t('workarea.admin.fields.recipient')
51
+ %th.align-right= t('workarea.admin.fields.amount')
52
+ %th.align-right= t('workarea.admin.fields.balance')
53
+ %th.align-center= t('workarea.admin.fields.order_id')
54
+ %th.align-right= t('workarea.admin.fields.expires_on')
55
+ %th= t('workarea.admin.fields.created_at')
56
+
57
+ %tbody
58
+ - @search.results.each do |result|
59
+ %tr.index-table__row
60
+ %td.index-table__control-cell
61
+ .checkbox
62
+ = check_box_tag 'global_id', result.to_global_id.to_param, false, class: 'checkbox__input', id: dom_id(result), data: { bulk_action_item: '' }
63
+ = label_tag dom_id(result), '', class: 'checkbox__label', title: t('workarea.admin.bulk_actions.add_summary_button')
64
+ %td
65
+ = link_to result.token, payment_gift_card_path(result)
66
+ = upcoming_changesets_icon_for(result)
67
+ = comments_icon_for(result)
68
+ %td= result.from.presence || t('workarea.admin.cards.attributes.no_value')
69
+ %td= result.to
70
+ %td.align-right= number_to_currency result.amount
71
+ %td.align-right= number_to_currency result.balance
72
+ %td.align-center= result.order_id.presence || t('workarea.admin.cards.attributes.no_value')
73
+ %td.align-right
74
+ - if result.expires_at.present?
75
+ = local_time_ago(result.expires_at)
76
+ - else
77
+ = t('workarea.admin.cards.attributes.no_value')
78
+ %td= local_time_ago(result.created_at)
79
+
80
+ - if @search.results.total_pages > 1
81
+ = render 'workarea/admin/shared/pagination', collection: @search.results
82
+
83
+ .workflow-bar
84
+ .grid
85
+ .grid__cell.grid__cell--50
86
+ = render 'workarea/admin/shared/bulk_actions', klass: Workarea::Payment::GiftCard, search: @search do
87
+ .grid__cell
88
+ = form_tag new_data_file_export_path, method: 'get', data: { bulk_action_form: '' } do
89
+ = hidden_field_tag 'model_type', 'Workarea::Payment::GiftCard::Redemption', id: nil
90
+ = hidden_field_tag 'query_id', @search.to_gid_param, id: nil
91
+ = hidden_field_tag 'return_to', request.path, id: nil
92
+ %button.workflow-bar__button{ type: :submit }= t('workarea.admin.payment_gift_cards.index.export_redemptions')
93
+
94
+ .grid__cell.grid__cell--50.align-right
95
+ = link_to t('workarea.admin.payment_gift_cards.index.button'), new_payment_gift_card_path, id: 'add_payment_gift_card', class: 'workflow-bar__button workflow-bar__button--create'
@@ -0,0 +1,43 @@
1
+ - @page_title = t('workarea.admin.payment_gift_cards.new.title')
2
+
3
+ .view
4
+ .view__header
5
+ .grid.grid--middle.grid--center
6
+ .grid__cell.grid__cell--50
7
+ .view__heading
8
+ = link_to_index_for(@gift_card)
9
+ %h1= t('workarea.admin.payment_gift_cards.new.title')
10
+
11
+ .view__container
12
+ - if @gift_card.errors.present?
13
+ - @gift_card.errors.full_messages.each do |message|
14
+ = render_message 'error', message
15
+
16
+ = form_tag payment_gift_cards_path, method: 'post', id: 'payment_gift_card_form' do
17
+ = hidden_field_tag 'return_to', request.referrer
18
+
19
+ .section
20
+ .property
21
+ = label_tag 'gift_card[token]', t('workarea.admin.fields.token'), class: 'property__name'
22
+ = text_field_tag 'gift_card[token]', @gift_card.token, class: 'text-box'
23
+
24
+ .property
25
+ = label_tag 'gift_card[to]', t('workarea.admin.fields.recipient'), class: 'property__name'
26
+ = email_field_tag 'gift_card[to]', @gift_card.to, class: 'text-box'
27
+
28
+ .property
29
+ = label_tag 'gift_card[notify]', t('workarea.admin.fields.notify'), class: 'property__name'
30
+ = check_box_tag 'gift_card[notify]', 1, false
31
+
32
+ .property
33
+ = label_tag 'gift_card[amount]', t('workarea.admin.fields.amount'), class: 'property__name'
34
+ %span $
35
+ = text_field_tag 'gift_card[amount]', @gift_card.amount, class: 'text-box text-box--small'
36
+
37
+ .property
38
+ = label_tag 'gift_card[expires_at]', t('workarea.admin.fields.expires_on'), class: 'property__name'
39
+ = datetime_picker_tag 'gift_card[expires_at]', @gift_card.expires_at, class: 'text-box', data: { datepicker_field: { inline: false } }
40
+
41
+ .workflow-bar
42
+ .grid.grid--auto.grid--right.grid--middle
43
+ .grid__cell= button_tag t('workarea.admin.payment_gift_cards.new.button'), value: 'create_gift_card', class: 'workflow-bar__button workflow-bar__button--create'
@@ -0,0 +1,29 @@
1
+ - @page_title = t('workarea.admin.payment_gift_cards.redemptions.title', name: @gift_card.name)
2
+
3
+ .view
4
+ .view__header
5
+ .grid.grid--middle.grid--center
6
+ .grid__cell.grid__cell--50
7
+ .view__heading
8
+ = link_to_index_for(@gift_card)
9
+ %h1= link_to @gift_card.name, url_for(@gift_card)
10
+
11
+ .view__container
12
+ = render_cards_for(@gift_card, :redemptions)
13
+
14
+ .view__container
15
+ %p.align-center= pluralize(@gift_card.redemptions.count, t('workarea.admin.payment_gift_cards.redemptions.redemption'))
16
+
17
+ - if @gift_card.redemptions.any?
18
+ %table
19
+ %thead
20
+ %tr
21
+ %th= t('workarea.admin.fields.order_id')
22
+ %th= t('workarea.admin.fields.amount')
23
+ %th= t('workarea.admin.fields.redeemed_at')
24
+ %tbody
25
+ - @gift_card.redemptions.each do |redemption|
26
+ %tr
27
+ %td= link_to redemption.order_id, order_path(redemption.order_id)
28
+ %td= number_to_currency redemption.amount
29
+ %td= local_time(redemption.redeemed_at, :long)
@@ -0,0 +1,19 @@
1
+ - @page_title = @gift_card.name
2
+
3
+ .view
4
+ .view__header
5
+ .grid.grid--middle
6
+ .grid__cell.grid__cell--25
7
+ = render 'workarea/admin/releases/select'
8
+ .grid__cell.grid__cell--50
9
+ .view__heading
10
+ = link_to_index_for(@gift_card)
11
+ %h1= @gift_card.name
12
+ .grid__cell.grid__cell--25
13
+ = render_aux_navigation_for(@gift_card)
14
+
15
+ .view__container
16
+ = render_cards_for(@gift_card)
17
+
18
+ .workflow-bar
19
+ = link_to t('workarea.admin.actions.delete'), payment_gift_card_path(@gift_card), class: 'workflow-bar__button workflow-bar__button--delete', data: { method: 'delete', confirm: t('workarea.admin.actions.delete_confirmation') }
@@ -0,0 +1,6 @@
1
+ json.gift_card do
2
+ json.complete step.complete?
3
+ json.gift_card_balance summary.gift_card_balance
4
+ json.gift_card_amount summary.gift_card_amount
5
+ json.order_balance summary.order_balance
6
+ end
@@ -0,0 +1,3 @@
1
+ json.to @gift_card.to
2
+ json.token @gift_card.token
3
+ json.balance @gift_card.balance
@@ -0,0 +1,3 @@
1
+ json.type 'gift_card'
2
+ json.display_number tender.display_number
3
+ json.amount tender.amount
@@ -0,0 +1,6 @@
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
@@ -0,0 +1,28 @@
1
+ .checkout-payment__secondary-method{ class: step.show_gift_card? ? 'checkout-payment__secondary-method--visible' : nil }
2
+
3
+ - if step.show_gift_card?
4
+ .message.message--info
5
+ %p.message__type
6
+ %span.message__icon= t('workarea.storefront.messages.info')
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))}
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
+ - if step.tender_required?
14
+ #{t('workarea.storefront.gift_cards.tender_required', amount: number_to_currency(step.order_balance))}
15
+
16
+ = optional_field(t('workarea.storefront.gift_cards.enter_gift_card_prompt'), step.gift_card.try(:number)) do
17
+
18
+ %h2= t('workarea.storefront.gift_cards.gift_card')
19
+
20
+ = form_tag checkout_add_gift_card_path, method: 'patch', id: 'gift_card_form', class: 'inline-form' do
21
+
22
+ .inline-form__cell
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
27
+ .inline-form__cell
28
+ %p= button_tag t('workarea.storefront.gift_cards.apply_gift_card'), value: 'apply_gift_card', class: 'button'
@@ -0,0 +1,6 @@
1
+ - if summary.gift_card?
2
+ %tr
3
+ %th
4
+ %span= t('workarea.storefront.gift_cards.gift_card')
5
+ %td
6
+ %strong.table__price-discount −#{number_to_currency(summary.gift_card_amount)}
@@ -0,0 +1,15 @@
1
+ %tr
2
+ %td
3
+ %h1= t('workarea.storefront.email.gift_card_created.heading')
4
+ %p
5
+ %strong= @from
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))
8
+
9
+ - if @card.message.present?
10
+ %p
11
+ %strong= @from
12
+ %br
13
+ = @card.message
14
+
15
+ %p= t('workarea.storefront.email.gift_card_created.how_to_redeem', token: @card.token)
@@ -0,0 +1,17 @@
1
+ .view
2
+
3
+ %h1= t('workarea.storefront.gift_cards.check_balance')
4
+
5
+ = form_tag gift_cards_lookup_path, method: 'get' do
6
+
7
+ .property.property--responsive
8
+ = label_tag 'gift_card_email', class: 'property__name' do
9
+ %span.property__text= t('workarea.storefront.users.email')
10
+ .value= email_field_tag :email, nil, id: 'gift_card_email', class: 'text-box', required: true
11
+
12
+ .property.property--responsive
13
+ = label_tag 'gift_card_number', class: 'property__name' do
14
+ %span.property__text= t('workarea.storefront.gift_cards.gift_card_number')
15
+ .value= text_field_tag :token, nil, id: 'gift_card_number', class: 'text-box', required: true
16
+
17
+ %p= button_tag t('workarea.storefront.forms.go'), value: 'submit', class: 'button'
@@ -0,0 +1,5 @@
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}
@@ -0,0 +1,5 @@
1
+ %p
2
+ = t('workarea.storefront.gift_cards.gift_card')
3
+ %br
4
+ #{tender.display_number}:
5
+ = number_to_currency(tender.amount)
@@ -0,0 +1,6 @@
1
+ - if order.gift_card_tender_amount > 0
2
+ %tr
3
+ %th
4
+ %span= t('workarea.storefront.gift_cards.gift_card')
5
+ %td
6
+ %strong.table__price-discount −#{number_to_currency(order.gift_card_tender_amount)}
@@ -0,0 +1,9 @@
1
+ .data-card
2
+ .data-card__cell
3
+ %p.data-card__line.data-card__credit-card
4
+ = inline_svg('workarea/storefront/payment_icons/gift_card.svg', title: t('workarea.storefront.orders.tenders.gift_card.title'), class: 'payment-icon')
5
+ %span.data-card__credit-card-number
6
+ = t('workarea.storefront.credit_cards.summary', issuer: t('workarea.storefront.orders.tenders.gift_card.title'), number: tender.display_number)
7
+ %p.data-card__line
8
+ %strong
9
+ #{t('workarea.storefront.orders.amount')}: #{number_to_currency tender.amount}
@@ -0,0 +1,77 @@
1
+ .grid.grid--rev
2
+ .grid__cell.grid__cell--60-at-medium
3
+
4
+ .product-details__name
5
+ %h1.product-details__heading{ itemprop: 'name' }= product.name
6
+
7
+ %p.product-details__id
8
+ %span{ itemprop: 'productID' }= product.id
9
+
10
+ .product-prices.product-prices--details{ itemprop: 'offers', itemscope: true, itemtype: 'http://schema.org/Offer' }
11
+ = render 'workarea/storefront/products/pricing', product: product
12
+
13
+ - if product.description.present?
14
+ .product-details__description
15
+ %p= truncated_product_description(product, t('workarea.storefront.products.read_more'))
16
+
17
+ = form_tag cart_items_path, method: 'post', class: 'product-details__add-to-cart-form', data: { dialog_form: { dialogOptions: { closeAll: true, initModules: true } }, analytics: add_to_cart_analytics_data(product).to_json } do
18
+ = hidden_field_tag :product_id, product.id, id: dom_id(product, 'product_id')
19
+
20
+ - if product.sku_options.one?
21
+ = hidden_field_tag :sku, product.sku_options.first.second
22
+
23
+ - else
24
+ .property
25
+ = label_tag :sku, nil, class: 'property__name', for: "sku_#{dom_id(product)}" do
26
+ %span.property__text= t('workarea.storefront.products.select_options')
27
+ .value
28
+ = select_tag :sku, options_for_select(product.sku_options, params[:sku]), required: true, id: "sku_#{dom_id(product)}", data: { product_details_sku_select: product.slug }
29
+ - if params[:sku].present?
30
+ .value__note= product.inventory_status
31
+
32
+ = hidden_field_tag :quantity, 1, id: "quantity#{dom_id(product)}"
33
+
34
+ .message.message--info
35
+ %p.message__type
36
+ %span.message__icon= t('workarea.storefront.messages.info')
37
+ %p.message__text= t('workarea.storefront.gift_cards.email_to_recipient')
38
+
39
+ .property
40
+ = label_tag :email, nil, class: "property__name", for: "email_#{dom_id(product)}" do
41
+ %span.property__text= t('workarea.storefront.gift_cards.recipients_email')
42
+ .value= email_field_tag :email, params[:email], class: 'text-box', required: true, id: "email_#{dom_id(product)}"
43
+ .property
44
+ = label_tag :from, nil, class: "property__name", for: "from_#{dom_id(product)}" do
45
+ %span.property__text= t('workarea.storefront.gift_cards.senders_email')
46
+ %span.property__requirement.property__requirement--optional= t('workarea.storefront.forms.optional')
47
+ .value= text_field_tag :from, params[:from], class: 'text-box', id: "from_#{dom_id(product)}", maxlength: 100
48
+ .property
49
+ = label_tag :message, nil, class: "property__name", for: "message_#{dom_id(product)}" do
50
+ %span.property__text= t('workarea.storefront.gift_cards.message_to_recipient')
51
+ %span.property__requirement.property__requirement--optional= t('workarea.storefront.forms.optional')
52
+ .value= text_area_tag :message, params[:message], class: 'text-box text-box--multi-line', id: "message_#{dom_id(product)}", maxlength: 500
53
+
54
+ - if product.purchasable?
55
+ %p.product-details__add-to-cart-action= button_tag t('workarea.storefront.products.add_to_cart'), value: 'add_to_cart', class: 'button button--large'
56
+
57
+ - else
58
+ %p.product-details__unavailable= t('workarea.storefront.products.unavailable')
59
+
60
+ = append_partials('storefront.product_details', product: product)
61
+
62
+ %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
+
64
+ .grid__cell.grid__cell--40-at-medium
65
+
66
+ .product-details__primary-image
67
+ = link_to(product_image_url(product.primary_image, :zoom), target: '_blank', class: 'product-details__primary-image-link', data: { dialog_button: '' }) do
68
+ = image_tag product_image_url(product.primary_image, :detail), alt: 'View Larger Image', itemprop: 'image', class: 'product-details__primary-image-link-image'
69
+
70
+ - if product.images.length > 1
71
+ .product-details__alt-images
72
+ .grid.grid--auto
73
+ - product.images.each_with_index do |image, index|
74
+ .grid__cell
75
+ .product-details__alt-image
76
+ - button_class = index == 0 ? 'product-details__alt-image-link product-details__alt-image-link--selected' : 'product-details__alt-image-link'
77
+ = link_to(image_tag(product_image_url(image, :small_thumb), alt: t('workarea.storefront.products.zoom')), product_image_url(image, :zoom), class: button_class, target: '_blank', data: { alternate_image_button: { src: product_image_url(image, :detail) }.to_json })
@@ -0,0 +1,47 @@
1
+ module Workarea
2
+ class CreateOrderedGiftCards
3
+ include Sidekiq::Worker
4
+ include Sidekiq::CallbacksWorker
5
+
6
+ sidekiq_options enqueue_on: { Fulfillment => :create }
7
+
8
+ def perform(order_id)
9
+ order = Order.find(order_id)
10
+ fulfillment = Fulfillment.find(order.id)
11
+
12
+ gift_cards = order.items.select do |item|
13
+ item.digital? && item.gift_card?
14
+ end
15
+
16
+ gift_cards.each do |item|
17
+ unit_adjustment = item.price_adjustments.first
18
+ unit_amount = unit_adjustment.amount / item.quantity
19
+
20
+ item.quantity.times do
21
+ Payment::GiftCard.create!(
22
+ amount: unit_amount,
23
+ order_id: order.id,
24
+ to: item.customizations['email'],
25
+ from: item.customizations['from'],
26
+ message: item.customizations['message'],
27
+ notify: true,
28
+ purchased: true
29
+ )
30
+ end
31
+
32
+ update_fulfillment(fulfillment, item)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def update_fulfillment(fulfillment, item)
39
+ # Ensure item is there to ship
40
+ fulfillment.items.detect { |i| i.order_item_id == item.id.to_s } ||
41
+ fulfillment.items.build(order_item_id: item.id, quantity: item.quantity)
42
+
43
+ fulfillment.mark_item_shipped(id: item.id.to_s, quantity: item.quantity)
44
+ fulfillment.save!
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ module Workarea
2
+ class LogGiftCardRedemption
3
+ include Sidekiq::Worker
4
+ include Sidekiq::CallbacksWorker
5
+
6
+ sidekiq_options enqueue_on: { Order => :place }
7
+
8
+ def perform(order_id)
9
+ order = Order.find(order_id)
10
+
11
+ payment = Payment.find_or_initialize_by(id: order.id)
12
+ return unless payment.gift_card?
13
+
14
+ gift_card = Payment::GiftCard.find_by_token(payment.gift_card.number)
15
+ return if redemption_already_exists?(gift_card, order.id)
16
+
17
+ gift_card.redemptions.create!(
18
+ redeemed_at: order.placed_at,
19
+ amount: payment.gift_card.amount,
20
+ order_id: order.id
21
+ )
22
+
23
+ gift_card.touch
24
+ end
25
+
26
+ private
27
+
28
+ def redemption_already_exists?(card, order_id)
29
+ card.redemptions.pluck(:order_id).include?(order_id)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ module Workarea
2
+ class SendGiftCardNotifications
3
+ include Sidekiq::Worker
4
+ include Sidekiq::CallbacksWorker
5
+
6
+ sidekiq_options enqueue_on: { Payment::GiftCard => :create }, queue: 'low'
7
+
8
+ def perform(gift_card_id)
9
+ card = Payment::GiftCard.find(gift_card_id)
10
+ return unless send_notification?(card)
11
+ Storefront::GiftCardMailer.created(card.id.to_s).deliver_now
12
+ end
13
+
14
+ private
15
+
16
+ def send_notification?(card)
17
+ card.order_id.present? || (card.to.present? && card.notify?)
18
+ end
19
+ end
20
+ end
data/bin/rails ADDED
@@ -0,0 +1,18 @@
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/gift_cards/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
+
18
+ require 'rails/engine/commands'
@@ -0,0 +1,37 @@
1
+ #
2
+ # Store Front
3
+ #
4
+ #
5
+ Workarea.append_partials(
6
+ 'storefront.checkout_summary_payment',
7
+ 'workarea/storefront/checkouts/gift_card_summary'
8
+ )
9
+
10
+ Workarea.append_partials(
11
+ 'storefront.payment_error',
12
+ 'workarea/storefront/checkouts/gift_card_error'
13
+ )
14
+
15
+ Workarea.append_partials(
16
+ 'storefront.secondary_payment',
17
+ 'workarea/storefront/checkouts/gift_card_payment'
18
+ )
19
+
20
+ Workarea.append_partials(
21
+ 'storefront.order_summary_payment',
22
+ 'workarea/storefront/orders/gift_card_summary'
23
+ )
24
+
25
+ Workarea.append_partials(
26
+ 'storefront.order_mailer_summary_payment',
27
+ 'workarea/storefront/order_mailer/gift_card_summary'
28
+ )
29
+
30
+ #
31
+ # Admin
32
+ #
33
+ #
34
+ Workarea.append_partials(
35
+ 'admin.orders_menu',
36
+ 'workarea/admin/payment_gift_cards/menu'
37
+ )
@@ -0,0 +1,8 @@
1
+ Workarea.configure do |config|
2
+ config.checkout_steps << 'Workarea::Checkout::Steps::GiftCard'
3
+ config.customization_types << Workarea::Catalog::Customizations::GiftCard
4
+ config.product_templates << :gift_card
5
+ config.tender_types.prepend(:gift_card)
6
+ config.seeds << 'Workarea::GiftCardSeeds'
7
+ config.gift_card_token_length = 8
8
+ end
@@ -0,0 +1,3 @@
1
+ Workarea.configure do |config|
2
+ config.jump_to_navigation.merge!('Gift Cards' => :payment_gift_cards_path)
3
+ end
@@ -0,0 +1,82 @@
1
+ en:
2
+ workarea:
3
+ admin:
4
+ activities:
5
+ payment_gift_card_create_html: created %{name}
6
+ payment_gift_card_destroy_html: deleted a payment gift card
7
+ payment_gift_card_update_html: updated %{name}
8
+ fields:
9
+ amount: Amount
10
+ balance: Balance
11
+ expires_on: Expires on
12
+ from: From
13
+ message: Message
14
+ notify: Notify Recipient
15
+ number: Number
16
+ order_id: Order ID
17
+ redeemed_at: Redeemed At
18
+ recipient: Recipient
19
+ token: Token
20
+ used: Used
21
+ orders:
22
+ tenders:
23
+ gift_card:
24
+ title: Gift Card
25
+ payment_gift_cards:
26
+ cards:
27
+ redemptions:
28
+ button: View All Redemptions
29
+ empty: There are no redemptions for this gift card yet.
30
+ title: Redemptions
31
+ edit:
32
+ button: Save Gift Card
33
+ title: Editing %{name}
34
+ gift_card: Gift Card
35
+ index:
36
+ button: Add Gift Card
37
+ title: Gift Cards
38
+ export_redemptions: Export Redemptions
39
+ new:
40
+ button: Create Gift Card
41
+ title: New Gift Card
42
+ redemptions:
43
+ export_button: Create Export
44
+ redemption: Redemption
45
+ title: Gift Card Redemptions
46
+ view_order: View Order
47
+ shared:
48
+ primary_nav:
49
+ gift_cards: Gift Cards
50
+ gift_cards:
51
+ capture: Gift cards are captured on authorization.
52
+ credit: "%{amount} added to gift card %{number}"
53
+ debit: "%{amount} deducted from gift card %{number}"
54
+ insufficient_funds: This gift card doesn't not enough balance.
55
+ payment_gift_card:
56
+ name: Gift Card %{token}
57
+ storefront:
58
+ email:
59
+ gift_card_created:
60
+ heading: You've Got a Gift Certificate!
61
+ how_to_redeem: To redeem your gift certificate, enter code %{token} at checkout. Enjoy!
62
+ message_html: has purchased a gift certificate for you to use at %{link} in the amount of %{amount}.
63
+ says: 'says:'
64
+ subject: You've Got a Gift Certificate!
65
+ gift_cards:
66
+ applied_to_order: "%{amount} will be applied to your order."
67
+ apply_gift_card: Apply
68
+ balance: Your gift card balance is %{amount}.
69
+ check_balance: Check Your Gift Card Balance
70
+ email_to_recipient: We will email the digital gift card to the recipient.
71
+ enter_gift_card_prompt: Enter a gift card number
72
+ gift_card: Gift Card
73
+ gift_card_number: Gift Card Number
74
+ message_to_recipient: Message to Recipient
75
+ place_order: Click the Place Order button below to complete your order.
76
+ recipients_email: Recipient's Email
77
+ senders_email: Your Name
78
+ tender_required: You must submit another payment method for %{amount}.
79
+ orders:
80
+ tenders:
81
+ gift_card:
82
+ title: Gift Card