solidus_virtual_gift_card 1.0.0

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE +26 -0
  6. data/README.md +52 -0
  7. data/Rakefile +21 -0
  8. data/app/assets/javascripts/spree/backend/solidus_virtual_gift_card.coffee +9 -0
  9. data/app/assets/stylesheets/spree/backend/solidus_virtual_gift_card.css +7 -0
  10. data/app/controllers/spree/admin/gift_cards_controller.rb +54 -0
  11. data/app/controllers/spree/api/gift_cards_controller.rb +23 -0
  12. data/app/mailers/spree/gift_card_mailer.rb +8 -0
  13. data/app/models/concerns/spree/gift_cards/line_item_concerns.rb +17 -0
  14. data/app/models/concerns/spree/gift_cards/order_concerns.rb +34 -0
  15. data/app/models/concerns/spree/redemption_code_generator.rb +10 -0
  16. data/app/models/spree/line_item_decorator.rb +1 -0
  17. data/app/models/spree/order_decorator.rb +1 -0
  18. data/app/models/spree/permission_sets/virtual_gift_card_display.rb +9 -0
  19. data/app/models/spree/permission_sets/virtual_gift_card_management.rb +9 -0
  20. data/app/models/spree/store_credit_category_decorator.rb +2 -0
  21. data/app/models/spree/virtual_gift_card.rb +75 -0
  22. data/app/overrides/admin_item_view_gift_card_codes.rb +13 -0
  23. data/app/overrides/admin_user_sidebar_store_credits.rb +6 -0
  24. data/app/overrides/admin_user_sub_menu.rb +6 -0
  25. data/app/views/spree/admin/gift_cards/_lookup_form.html.erb +8 -0
  26. data/app/views/spree/admin/gift_cards/_redemption_form.html.erb +8 -0
  27. data/app/views/spree/admin/gift_cards/index.html.erb +1 -0
  28. data/app/views/spree/admin/gift_cards/lookup.html.erb +16 -0
  29. data/app/views/spree/admin/gift_cards/show.html.erb +32 -0
  30. data/app/views/spree/admin/orders/_gift_card_redemption_codes.html.erb +3 -0
  31. data/app/views/spree/admin/users/_gift_card_sidebar.html.erb +3 -0
  32. data/app/views/spree/admin/users/_sub_menu.html.erb +10 -0
  33. data/app/views/spree/gift_card_mailer/gift_card_email.text.erb +7 -0
  34. data/bin/rails +7 -0
  35. data/circle.yml +6 -0
  36. data/config/initializers/gift_card_store_credit_event_originator.rb +7 -0
  37. data/config/locales/en.yml +21 -0
  38. data/config/routes.rb +23 -0
  39. data/db/migrate/20140623152903_create_virtual_gift_card.rb +16 -0
  40. data/db/migrate/20140624175113_seed_gift_card_category.rb +5 -0
  41. data/db/migrate/20140627185148_add_timestamps_to_gift_cards.rb +6 -0
  42. data/db/migrate/20140702153907_add_gift_card_flag_to_products.rb +5 -0
  43. data/db/migrate/20140707200431_add_line_item_to_gift_card.rb +7 -0
  44. data/db/seeds.rb +1 -0
  45. data/lib/generators/solidus_virtual_gift_card/install/install_generator.rb +36 -0
  46. data/lib/solidus_virtual_gift_card.rb +2 -0
  47. data/lib/spree_virtual_gift_card/engine.rb +20 -0
  48. data/lib/spree_virtual_gift_card/factories.rb +13 -0
  49. data/solidus_virtual_gift_card.gemspec +31 -0
  50. data/spec/controllers/spree/admin/gift_cards_controller_spec.rb +111 -0
  51. data/spec/controllers/spree/api/gift_cards_controller_spec.rb +88 -0
  52. data/spec/models/concerns/spree/redemption_code_generator_spec.rb +42 -0
  53. data/spec/models/spree/line_item_spec.rb +30 -0
  54. data/spec/models/spree/order_spec.rb +90 -0
  55. data/spec/models/spree/permission_sets/virtual_gift_card_display_spec.rb +22 -0
  56. data/spec/models/spree/permission_sets/virtual_gift_card_management_spec.rb +21 -0
  57. data/spec/models/spree/store_credit_category_spec.rb +23 -0
  58. data/spec/models/spree/virtual_gift_card_spec.rb +179 -0
  59. data/spec/spec_helper.rb +74 -0
  60. metadata +258 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ead961e2e91055078cda6622eff9bcb37135679c
4
+ data.tar.gz: fc2ae98ff7e39233c92aa1ef57e5b88647baec14
5
+ SHA512:
6
+ metadata.gz: 70cff66f119830a384728feb0b4a127f4fd86aa59189662d7c93c913e7e3422d9e72a054a89c7b555dbac3d569b49bdbe75d9a38ca30ffeacc82d36653b36ef7
7
+ data.tar.gz: 95b4b982fdba785b3d6a08a87a1ea8c9a366f2d1fb688dcea8b2f0bd30b9f98334a04e511d556340f625ba91b211dd2497fe3439b905db9dfc79fffb8ecc611a
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ .sass-cache
8
+ coverage
9
+ Gemfile.lock
10
+ tmp
11
+ nbproject
12
+ pkg
13
+ *.swp
14
+ spec/dummy
15
+ spec/examples.txt
16
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "solidus", github: "solidusio/solidus", branch: "master"
4
+ gem "solidus_auth_devise", "~> 1.0"
5
+
6
+ group :test, :development do
7
+ gem "pry-byebug"
8
+ end
9
+
10
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2014 [Bonobos]
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ Solidus - Virtual Gift Card
2
+ ===========================
3
+ A virtual gift card implementation for Solidus.
4
+
5
+ * Allows setup of virtual gift card products that get unique codes upon
6
+ purchase.
7
+ * The virtual gift card codes can be used to add store credit to a user's
8
+ account.
9
+
10
+ [![Circle CI](https://circleci.com/gh/solidusio/solidus_virtual_gift_card/tree/master.svg?style=shield)](https://circleci.com/gh/solidusio/solidus_virtual_gift_card/tree/master)
11
+
12
+ Installation
13
+ ------------
14
+
15
+ In your Gemfile:
16
+
17
+ ```ruby
18
+ gem "solidus_virtual_gift_card"
19
+ ```
20
+
21
+ Bundle your dependencies and run the installation generator:
22
+
23
+ ```shell
24
+ bundle install
25
+ bundle exec rails g solidus_virtual_gift_card:install
26
+ ```
27
+
28
+ Authorization
29
+ -------------
30
+
31
+ For discrete authorization, two permission sets have been added to allow for granular display in the admin.
32
+
33
+ `Spree::PermissionSets::VirtualGiftCardDisplay` and `Spree::PermissionSets::VirtualGiftCardManagement` have been added and can be registered via [RoleConfiguration](http://docs.solidus.io/Spree/RoleConfiguration.html)
34
+
35
+ Testing
36
+ -------
37
+
38
+ First bundle your dependencies, then run `rake`. `rake` will default to
39
+ building the dummy app if it does not exist, then it will run specs. The dummy
40
+ app can be regenerated by using `rake test_app`.
41
+
42
+ ```shell
43
+ bundle
44
+ bundle exec rake
45
+ ```
46
+
47
+ When testing your applications integration with this extension you may use it's
48
+ factories. Simply add this require statement to your spec_helper:
49
+
50
+ ```ruby
51
+ require "spree_virtual_gift_card/factories"
52
+ ```
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir["spec/dummy"].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir("../../")
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'solidus_virtual_gift_card'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1,9 @@
1
+ window.GiftCards =
2
+ _bindLookupGiftCard: ->
3
+ $(document).on('submit', '#lookup-redemption-code', (event) ->
4
+ event.preventDefault()
5
+ window.location.href = $(this).attr('action') + '/' + $(this).find('#gift_card_redemption_code').val()
6
+ )
7
+
8
+ init: ->
9
+ @_bindLookupGiftCard()
@@ -0,0 +1,7 @@
1
+ .gift-card-code-lookup {
2
+ margin-bottom: 30px;
3
+ }
4
+
5
+ .lookup-gift-card-button {
6
+ margin-top: 15px;
7
+ }
@@ -0,0 +1,54 @@
1
+ class Spree::Admin::GiftCardsController < Spree::Admin::BaseController
2
+ before_filter :load_gift_card_history, only: [:show]
3
+ before_filter :load_user, only: [:lookup, :redeem]
4
+ before_filter :load_gift_card_for_redemption, only: [:redeem]
5
+
6
+ def index
7
+ end
8
+
9
+ def show
10
+ end
11
+
12
+ def lookup
13
+ end
14
+
15
+ def redeem
16
+ if @gift_card.redeem(@user)
17
+ flash[:success] = Spree.t("admin.gift_cards.redeemed_gift_card")
18
+ redirect_to admin_user_store_credits_path(@user)
19
+ else
20
+ flash[:error] = Spree.t("admin.gift_cards.errors.unable_to_redeem_gift_card")
21
+ render :lookup
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def load_gift_card_history
28
+ redemption_code = Spree::RedemptionCodeGenerator.format_redemption_code_for_lookup(params[:id])
29
+ @gift_cards = Spree::VirtualGiftCard.where(redemption_code: redemption_code)
30
+
31
+ if @gift_cards.empty?
32
+ flash[:error] = Spree.t('admin.gift_cards.errors.not_found')
33
+ redirect_to(admin_gift_cards_path)
34
+ end
35
+ end
36
+
37
+ def load_gift_card_for_redemption
38
+ redemption_code = Spree::RedemptionCodeGenerator.format_redemption_code_for_lookup(params[:gift_card][:redemption_code])
39
+ @gift_card = Spree::VirtualGiftCard.active_by_redemption_code(redemption_code)
40
+
41
+ if @gift_card.blank?
42
+ flash[:error] = Spree.t("admin.gift_cards.errors.not_found")
43
+ render :lookup
44
+ end
45
+ end
46
+
47
+ def load_user
48
+ @user = Spree::User.find(params[:user_id])
49
+ end
50
+
51
+ def model_class
52
+ Spree::VirtualGiftCard
53
+ end
54
+ end
@@ -0,0 +1,23 @@
1
+ class Spree::Api::GiftCardsController < Spree::Api::BaseController
2
+
3
+ def redeem
4
+ redemption_code = Spree::RedemptionCodeGenerator.format_redemption_code_for_lookup(params[:redemption_code] || "")
5
+ @gift_card = Spree::VirtualGiftCard.active_by_redemption_code(redemption_code)
6
+
7
+ if !@gift_card
8
+ render status: :not_found, json: redeem_fail_response
9
+ elsif @gift_card.redeem(@current_api_user)
10
+ render status: :created, json: {}
11
+ else
12
+ render status: 422, json: redeem_fail_response
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def redeem_fail_response
19
+ {
20
+ error_message: "#{Spree.t('admin.gift_cards.errors.not_found')}. #{Spree.t('admin.gift_cards.errors.please_try_again')}"
21
+ }
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ class Spree::GiftCardMailer < Spree::BaseMailer
2
+ def gift_card_email(gift_card)
3
+ @gift_card = gift_card.respond_to?(:id) ? gift_card : Spree::VirtualGiftCard.find(gift_card)
4
+ @order = @gift_card.line_item.order
5
+ subject = "#{Spree::Store.current.name} #{Spree.t('gift_card_mailer.gift_card_email.subject')}"
6
+ mail(to: @order.email, from: from_address, subject: subject)
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ module GiftCards::LineItemConcerns
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :gift_cards, class_name: Spree::VirtualGiftCard
7
+ delegate :gift_card?, :gift_card, to: :product
8
+ prepend(InstanceMethods)
9
+ end
10
+
11
+ module InstanceMethods
12
+ def redemption_codes
13
+ gift_cards.map {|gc| {amount: gc.formatted_amount, redemption_code: gc.formatted_redemption_code}}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ module Spree
2
+ module GiftCards::OrderConcerns
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ Spree::Order.state_machine.after_transition to: :complete, do: :send_gift_card_emails
7
+
8
+ has_many :gift_cards, through: :line_items
9
+
10
+ prepend(InstanceMethods)
11
+ end
12
+
13
+ module InstanceMethods
14
+ def finalize!
15
+ create_gift_cards
16
+ super
17
+ end
18
+
19
+ def create_gift_cards
20
+ line_items.each do |item|
21
+ item.quantity.times do
22
+ Spree::VirtualGiftCard.create!(amount: item.price, currency: item.currency, purchaser: user, line_item: item) if item.gift_card?
23
+ end
24
+ end
25
+ end
26
+
27
+ def send_gift_card_emails
28
+ gift_cards.each do |gift_card|
29
+ Spree::GiftCardMailer.gift_card_email(gift_card).deliver
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,10 @@
1
+ module Spree::RedemptionCodeGenerator
2
+ def self.generate_redemption_code
3
+ chars = [('A'..'Z'), ('0'..'9')].map(&:to_a).flatten
4
+ 16.times.map { chars[rand(chars.count)] }.join
5
+ end
6
+
7
+ def self.format_redemption_code_for_lookup(redemption_code)
8
+ redemption_code.delete('-').upcase
9
+ end
10
+ end
@@ -0,0 +1 @@
1
+ Spree::LineItem.include Spree::GiftCards::LineItemConcerns
@@ -0,0 +1 @@
1
+ Spree::Order.include Spree::GiftCards::OrderConcerns
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module PermissionSets
3
+ class VirtualGiftCardDisplay < PermissionSets::Base
4
+ def activate!
5
+ can [:display, :admin], Spree::VirtualGiftCard
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module PermissionSets
3
+ class VirtualGiftCardManagement < PermissionSets::Base
4
+ def activate!
5
+ can :manage, Spree::VirtualGiftCard
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ Spree::StoreCreditCategory::GIFT_CARD_CATEGORY_NAME = "Gift Card".freeze
2
+ Spree::StoreCreditCategory.non_expiring_credit_types |= [Spree::StoreCreditCategory::GIFT_CARD_CATEGORY_NAME]
@@ -0,0 +1,75 @@
1
+ class Spree::VirtualGiftCard < ActiveRecord::Base
2
+ include ActionView::Helpers::NumberHelper
3
+
4
+ belongs_to :store_credit, class_name: 'Spree::StoreCredit'
5
+ belongs_to :purchaser, class_name: 'Spree::User'
6
+ belongs_to :redeemer, class_name: 'Spree::User'
7
+ belongs_to :line_item, class_name: 'Spree::LineItem'
8
+ before_create :set_redemption_code, unless: -> { redemption_code }
9
+
10
+
11
+ validates :amount, numericality: { greater_than: 0 }
12
+ validates_uniqueness_of :redemption_code, conditions: -> { where(redeemed_at: nil) }
13
+ validates_presence_of :purchaser_id
14
+
15
+ scope :unredeemed, -> { where(redeemed_at: nil) }
16
+ scope :by_redemption_code, -> (redemption_code) { where(redemption_code: redemption_code) }
17
+
18
+ def redeemed?
19
+ redeemed_at.present?
20
+ end
21
+
22
+ def redeem(redeemer)
23
+ return false if redeemed?
24
+ create_store_credit!({
25
+ amount: amount,
26
+ currency: currency,
27
+ memo: memo,
28
+ user: redeemer,
29
+ created_by: redeemer,
30
+ action_originator: self,
31
+ category: store_credit_category,
32
+ })
33
+ self.update_attributes( redeemed_at: Time.now, redeemer: redeemer )
34
+ end
35
+
36
+ def memo
37
+ "Gift Card ##{self.redemption_code}"
38
+ end
39
+
40
+ def formatted_redemption_code
41
+ redemption_code.scan(/.{4}/).join('-')
42
+ end
43
+
44
+ def formatted_amount
45
+ number_to_currency(amount, precision: 0)
46
+ end
47
+
48
+ def store_credit_category
49
+ Spree::StoreCreditCategory.where(name: Spree::StoreCreditCategory::GIFT_CARD_CATEGORY_NAME).first
50
+ end
51
+
52
+ def self.active_by_redemption_code(redemption_code)
53
+ Spree::VirtualGiftCard.unredeemed.by_redemption_code(redemption_code).first
54
+ end
55
+
56
+ private
57
+
58
+ def set_redemption_code
59
+ self.redemption_code = generate_unique_redemption_code
60
+ end
61
+
62
+ def generate_unique_redemption_code
63
+ redemption_code = Spree::RedemptionCodeGenerator.generate_redemption_code
64
+
65
+ if duplicate_redemption_code?(redemption_code)
66
+ generate_unique_redemption_code
67
+ else
68
+ redemption_code
69
+ end
70
+ end
71
+
72
+ def duplicate_redemption_code?(redemption_code)
73
+ Spree::VirtualGiftCard.active_by_redemption_code(redemption_code)
74
+ end
75
+ end
@@ -0,0 +1,13 @@
1
+ Deface::Override.new(
2
+ virtual_path: "spree/admin/orders/_shipment_manifest",
3
+ name: "admin_item_view_gift_card_codes",
4
+ insert_bottom: ".item-name",
5
+ partial: "spree/admin/orders/gift_card_redemption_codes",
6
+ )
7
+
8
+ Deface::Override.new(
9
+ virtual_path: "spree/admin/orders/_carton_manifest",
10
+ name: "admin_item_view_gift_card_codes",
11
+ insert_bottom: ".item-name",
12
+ partial: "spree/admin/orders/gift_card_redemption_codes",
13
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: "spree/admin/users/_sidebar",
3
+ name: "admin_user_sidebar_store_credits",
4
+ insert_bottom: "[data-hook='admin_user_tab_options']",
5
+ partial: "spree/admin/users/gift_card_sidebar",
6
+ )
@@ -0,0 +1,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: "spree/admin/shared/_menu",
3
+ name: "admin_user_sub_menu_index",
4
+ insert_after: "#admin-menu",
5
+ partial: "spree/admin/users/sub_menu",
6
+ )
@@ -0,0 +1,8 @@
1
+ <script async='true'>GiftCards.init()</script>
2
+
3
+ <div class='gift-card-code-lookup'>
4
+ <%= form_for :gift_card, url: admin_gift_cards_path, html: {id: 'lookup-redemption-code'} do |f| %>
5
+ Redemption code: <%= f.text_field :redemption_code %><br />
6
+ <%= f.submit 'Lookup Gift Card', class: 'lookup-gift-card-button' %>
7
+ <% end %>
8
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="row">
2
+ <div class="alpha twelve columns">
3
+ <%= f.field_container :redemption_code do %>
4
+ <%= f.label :redemption_code, Spree.t('admin.gift_cards.redemption_code') %> <span class="required">*</span><br />
5
+ <%= f.text_field :redemption_code %>
6
+ <% end %>
7
+ </div>
8
+ </div>
@@ -0,0 +1 @@
1
+ <%= render partial: 'lookup_form' %>
@@ -0,0 +1,16 @@
1
+ <% content_for :page_title do %>
2
+ <%= link_to "#{Spree.t(:editing_user)} #{@user.email}", edit_admin_user_url(@user) %>
3
+ <% end %>
4
+
5
+ <%= render :partial => 'spree/admin/users/sidebar', :locals => { :current => :gift_cards } %>
6
+ <% content_for :page_actions do %>
7
+ <li><%= link_to_with_icon 'arrow-left', Spree.t("admin.store_credits.back_to_user_list"), admin_users_path, class: 'button' %></li>
8
+ <% end %>
9
+
10
+ <%= form_for :gift_card, url: redeem_admin_user_gift_cards_path do |f| %>
11
+ <fieldset>
12
+ <legend align="center"><%= Spree.t("admin.gift_cards.redeem_gift_card") %></legend>
13
+ <%= render :partial => 'redemption_form', :locals => { :f => f } %>
14
+ <%= render :partial => 'spree/admin/shared/new_resource_links', :locals => { :collection_url => edit_admin_user_url(@user) } %>
15
+ </fieldset>
16
+ <% end %>
@@ -0,0 +1,32 @@
1
+ <%= render partial: 'spree/admin/shared/sub_menu' %>
2
+ <%= render partial: 'lookup_form' %>
3
+
4
+ <table class="index">
5
+ <thead>
6
+ <tr>
7
+ <th class="align-center">Redemption Code</th>
8
+ <th class="align-center">Amount</th>
9
+ <th class="align-center">Purchased by</th>
10
+ <th class="align-center">Purchased at</th>
11
+ <th class="align-center">Redeemed by</th>
12
+ <th class="align-center">Redeemed at</th>
13
+ </tr>
14
+ </thead>
15
+ <tbody>
16
+ <% @gift_cards.each do |gift_card| %>
17
+ <tr>
18
+ <td class="align-center"><%= gift_card.formatted_redemption_code %></td>
19
+ <td class="align-center"><%= number_to_currency(gift_card.amount) %></td>
20
+ <td class="align-center"><%= link_to "#{gift_card.purchaser.email}", edit_admin_user_path(gift_card.purchaser) %></td>
21
+ <td class="align-center"><%= gift_card.created_at.localtime.strftime("%F %I:%M%p") %></td>
22
+ <% if gift_card.redeemed? %>
23
+ <td class="align-center"><%= link_to "#{gift_card.redeemer.email}", edit_admin_user_path(gift_card.redeemer) %></td>
24
+ <td class="align-center"><%= gift_card.redeemed_at.localtime.strftime("%F %I:%M%p") %></td>
25
+ <% else %>
26
+ <td class="align-center"></td>
27
+ <td class="align-center"></td>
28
+ <% end %>
29
+ </tr>
30
+ <% end %>
31
+ </tbody>
32
+ </table>
@@ -0,0 +1,3 @@
1
+ <% item.line_item.gift_cards.each do |gift_card| %>
2
+ <br><strong><%= Spree.t('admin.gift_cards.redemption_code') %>:</strong> <%= gift_card.redemption_code %>
3
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <li<%== ' class="active"' if current == :gift_cards %>>
2
+ <%= link_to_with_icon 'gift', Spree.t(:"admin.gift_cards.redeem_gift_card"), lookup_admin_user_gift_cards_path(@user) %>
3
+ </li>
@@ -0,0 +1,10 @@
1
+ <% if request.fullpath.match(/^\/admin\/users/) %>
2
+ <% content_for :sub_menu do %>
3
+ <ul id="sub_nav" class="inline-menu">
4
+ <%= tab :users %>
5
+ <% if can?(:display, Spree::VirtualGiftCard) %>
6
+ <%= tab :gift_cards, :match_path => '/users/gift_cards' %>
7
+ <% end %>
8
+ </ul>
9
+ <% end %>
10
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%= Spree.t('gift_card_mailer.gift_card_email.dear_customer') %>
2
+
3
+ <%= Spree.t('gift_card_mailer.gift_card_email.your_gift_card_code') %>
4
+
5
+ ============================================================
6
+ <%= Spree.t('gift_card_mailer.gift_card_email.gift_card_code', code: @gift_card.redemption_code) %>
7
+ ============================================================
data/bin/rails ADDED
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_store_credits/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
data/circle.yml ADDED
@@ -0,0 +1,6 @@
1
+ machine:
2
+ ruby:
3
+ version: 2.1.5
4
+ test:
5
+ pre:
6
+ - bundle exec rake test_app
@@ -0,0 +1,7 @@
1
+ Rails.application.config.to_prepare do
2
+ Spree::Admin::StoreCreditEventsHelper.originator_links[Spree::VirtualGiftCard.to_s] = {
3
+ new_tab: true,
4
+ href_type: :line_item,
5
+ translation_key: 'admin.gift_cards.gift_card_originator'
6
+ }
7
+ end
@@ -0,0 +1,21 @@
1
+ ---
2
+ en:
3
+ spree:
4
+ admin:
5
+ gift_cards:
6
+ gift_card: "Gift Card"
7
+ gift_card_originator: "Gift Card - Order #%{order_number}"
8
+ redeem: "Redeem"
9
+ redeem_gift_card: "Redeem Gift Card"
10
+ redeemed_gift_card: "Redeemed Gift Card"
11
+ redemption_code: "Redemption Code"
12
+ errors:
13
+ not_found: "Gift card was not found"
14
+ please_try_again: "Please try again"
15
+ unable_to_redeem_gift_card: "Unable to redeem gift card"
16
+ gift_card_mailer:
17
+ gift_card_email:
18
+ dear_customer: "Dear customer"
19
+ your_gift_card_code: "Here is your gift card code"
20
+ gift_card_code: "Gift card code: %{code}"
21
+ subject: "Your gift card code"
data/config/routes.rb ADDED
@@ -0,0 +1,23 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ namespace :admin do
3
+ resources :users, only: [] do
4
+ resources :gift_cards, only: [] do
5
+ collection do
6
+ get :lookup
7
+ post :redeem
8
+ end
9
+ end
10
+ collection do
11
+ resources :gift_cards, only: [:index, :show]
12
+ end
13
+ end
14
+ end
15
+
16
+ namespace :api, defaults: { format: 'json' } do
17
+ resources :gift_cards, only: [] do
18
+ collection do
19
+ post :redeem
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ class CreateVirtualGiftCard < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_virtual_gift_cards do |t|
4
+ t.integer :purchaser_id
5
+ t.integer :redeemer_id
6
+ t.integer :store_credit_id
7
+ t.integer :amount
8
+ t.string :currency
9
+ t.string :redemption_code
10
+ t.datetime :redeemed_at
11
+ end
12
+
13
+ add_index :spree_virtual_gift_cards, :redemption_code
14
+ add_index :spree_virtual_gift_cards, :redeemed_at
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ class SeedGiftCardCategory < ActiveRecord::Migration
2
+ def change
3
+ Spree::StoreCreditCategory.find_or_create_by(name: 'Gift Card')
4
+ end
5
+ end