solidus_virtual_gift_card 1.0.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -0
  3. data/Gemfile +7 -4
  4. data/README.md +1 -1
  5. data/app/assets/javascripts/spree/frontend/solidus_virtual_gift_card.js +0 -0
  6. data/app/assets/stylesheets/spree/backend/solidus_virtual_gift_card.css +0 -11
  7. data/app/assets/stylesheets/spree/frontend/solidus_virtual_gift_card.css +0 -0
  8. data/app/controllers/spree/admin/gift_cards_controller.rb +15 -2
  9. data/app/mailers/spree/gift_card_mailer.rb +2 -2
  10. data/app/models/concerns/spree/gift_cards/inventory_unit_concerns.rb +10 -0
  11. data/app/models/concerns/spree/gift_cards/order_concerns.rb +3 -2
  12. data/app/models/spree/inventory_unit_decorator.rb +1 -0
  13. data/app/models/spree/virtual_gift_card.rb +27 -2
  14. data/app/overrides/admin_user_sub_menu.rb +7 -4
  15. data/app/overrides/spree/admin/products/_form/add_gift_card.html.erb.deface +8 -0
  16. data/app/views/spree/admin/gift_cards/_lookup_form.html.erb +35 -27
  17. data/app/views/spree/admin/gift_cards/edit.html.erb +12 -4
  18. data/app/views/spree/admin/gift_cards/index.html.erb +7 -1
  19. data/app/views/spree/admin/orders/_gift_card_details.html.erb +6 -1
  20. data/app/views/spree/admin/users/_sub_menu.html.erb +5 -9
  21. data/config/locales/en.yml +11 -0
  22. data/config/locales/it.yml +27 -0
  23. data/config/routes.rb +2 -1
  24. data/db/migrate/20151109202300_add_deactivated_at_to_gift_card.rb +5 -0
  25. data/db/migrate/20151110202752_add_inventory_unit_to_gift_card.rb +5 -0
  26. data/db/migrate/20151111211220_backfill_inventory_units_on_gift_card.rb +27 -0
  27. data/lib/generators/solidus_virtual_gift_card/install/install_generator.rb +0 -4
  28. data/lib/spree_virtual_gift_card/factories.rb +5 -0
  29. data/solidus_virtual_gift_card.gemspec +8 -6
  30. data/spec/controllers/spree/admin/gift_cards_controller_spec.rb +56 -0
  31. data/spec/features/admin/products_card_spec.rb +26 -0
  32. data/spec/mailers/spree/gift_card_mailer_spec.rb +20 -0
  33. data/spec/models/spree/line_item_spec.rb +1 -1
  34. data/spec/models/spree/virtual_gift_card_spec.rb +121 -1
  35. data/spec/spec_helper.rb +20 -6
  36. metadata +50 -14
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d68ab9a6fbe5f3e13073ab38d343df394def740a
4
- data.tar.gz: 1ef7434bca9095d79f2889e46232725d85d6aab5
3
+ metadata.gz: ea5a0d37ac45be094a61721f9f91b948a4713063
4
+ data.tar.gz: 31f391fb4340bbded183df0bd9fdd5e828c12de5
5
5
  SHA512:
6
- metadata.gz: 7d2212e47e0a8463e009165fa50c4eaa27ec63f4b131c874919c3b479f18454d0012199a6d4034e78c5d161426eade5176d0c41c27a99cd584d72618a81fb371
7
- data.tar.gz: 9636919f4bfbb68ff3b34509b952971d113147e47a61de9490a73b1c3c47d326a0e2dce7a60bf26bbc34bb52ed719c1f9b41a50162287a142775b04118235fb1
6
+ metadata.gz: 652d0b4ace4f835d099d5f518bdca86fb708a809198fa08a7cfad4f0c8011f472c8f8a89e9dc0572e8b76f10e36818aae20b875f2ea210440d73e8d839aeef53
7
+ data.tar.gz: 78cd94b6aa0d3e4b89b937ffdbabc83af98940ef1b42edff365ff30600c9787e29c5ac9715d3141d65d6c43e22ca65bcedb262af5150c753ae224f2cae4e8873
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ sudo: false
2
+ language: ruby
3
+ env:
4
+ matrix:
5
+ - SOLIDUS_BRANCH=v1.2 DB=mysql
6
+ - SOLIDUS_BRANCH=v1.2 DB=postgres
7
+ rvm:
8
+ - 2.1.8
data/Gemfile CHANGED
@@ -1,11 +1,14 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "solidus", github: "solidusio/solidus", branch: "master"
4
- gem "solidus_auth_devise", "~> 1.0"
3
+ branch = ENV.fetch('SOLIDUS_BRANCH', 'master')
4
+ gem "solidus", github: "solidusio/solidus", branch: branch
5
+ gem "solidus_auth_devise"
6
+
7
+ gem 'pg'
8
+ gem 'mysql2'
5
9
 
6
10
  group :test, :development do
7
- gem "pry-byebug"
8
- gem 'selenium-webdriver'
11
+ gem 'pry-rails'
9
12
  end
10
13
 
11
14
  gemspec
data/README.md CHANGED
@@ -7,7 +7,7 @@ A virtual gift card implementation for Solidus.
7
7
  * The virtual gift card codes can be used to add store credit to a user's
8
8
  account.
9
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)
10
+ [![Build Status](https://travis-ci.org/solidusio/solidus_virtual_gift_card.svg?branch=master)](https://travis-ci.org/solidusio/solidus_virtual_gift_card)
11
11
 
12
12
  Installation
13
13
  ------------
@@ -1,11 +0,0 @@
1
- .gift-card-code-lookup {
2
- margin-bottom: 30px;
3
- }
4
-
5
- .lookup-gift-card-button {
6
- margin-top: 15px;
7
- }
8
-
9
- .last-email-sent {
10
- margin-bottom: 10px;
11
- }
@@ -1,8 +1,8 @@
1
1
  class Spree::Admin::GiftCardsController < Spree::Admin::BaseController
2
2
  before_filter :load_user, only: [:lookup, :redeem]
3
3
  before_filter :load_gift_card_for_redemption, only: [:redeem]
4
- before_filter :load_gift_card_by_id, only: [:edit, :update, :send_email]
5
- before_filter :load_order, only: [:edit, :update]
4
+ before_filter :load_gift_card_by_id, only: [:edit, :update, :send_email, :deactivate]
5
+ before_filter :load_order, only: [:edit, :update, :deactivate]
6
6
 
7
7
  def index
8
8
  @search = Spree::VirtualGiftCard.purchased.search(params[:q])
@@ -35,6 +35,19 @@ class Spree::Admin::GiftCardsController < Spree::Admin::BaseController
35
35
  end
36
36
  end
37
37
 
38
+ def deactivate
39
+ if @gift_card.deactivate
40
+ flash[:success] = Spree.t("admin.gift_cards.deactivated_gift_card")
41
+ redirect_to edit_admin_order_path(@order)
42
+ else
43
+ flash[:error] = @gift_card.errors.full_messages.join(", ").presence || Spree.t("admin.gift_cards.errors.unable_to_reimburse_gift_card")
44
+ redirect_to edit_admin_order_gift_card_path(@order, @gift_card)
45
+ end
46
+ rescue Spree::Reimbursement::IncompleteReimbursementError
47
+ flash[:error] = Spree.t("admin.gift_cards.errors.unable_to_reimburse_gift_card")
48
+ redirect_to edit_admin_order_gift_card_path(@order, @gift_card)
49
+ end
50
+
38
51
  def send_email
39
52
  @gift_card.send_email
40
53
  redirect_to :back
@@ -2,8 +2,8 @@ class Spree::GiftCardMailer < Spree::BaseMailer
2
2
  def gift_card_email(gift_card)
3
3
  @gift_card = gift_card.respond_to?(:id) ? gift_card : Spree::VirtualGiftCard.find(gift_card)
4
4
  @order = @gift_card.line_item.order
5
- send_to_address = @gift_card.recipient_email || @order.email
5
+ send_to_address = @gift_card.recipient_email.presence || @order.email
6
6
  subject = "#{Spree::Store.current.name} #{Spree.t('gift_card_mailer.gift_card_email.subject')}"
7
- mail(to: send_to_address, from: from_address, subject: subject)
7
+ mail(to: send_to_address, from: from_address(Spree::Store.current), subject: subject)
8
8
  end
9
9
  end
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module GiftCards::InventoryUnitConcerns
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_one :gift_card, class_name: 'Spree::VirtualGiftCard'
7
+ end
8
+ end
9
+ end
10
+
@@ -23,8 +23,9 @@ module Spree
23
23
 
24
24
  def finalize!
25
25
  super
26
- gift_cards.each do |gift_card|
27
- gift_card.make_redeemable!(purchaser: user)
26
+ inventory_units = self.inventory_units
27
+ gift_cards.each_with_index do |gift_card, index|
28
+ gift_card.make_redeemable!(purchaser: user, inventory_unit: inventory_units[index])
28
29
  end
29
30
  end
30
31
 
@@ -0,0 +1 @@
1
+ Spree::InventoryUnit.include Spree::GiftCards::InventoryUnitConcerns
@@ -5,6 +5,8 @@ class Spree::VirtualGiftCard < ActiveRecord::Base
5
5
  belongs_to :purchaser, class_name: 'Spree::User'
6
6
  belongs_to :redeemer, class_name: 'Spree::User'
7
7
  belongs_to :line_item, class_name: 'Spree::LineItem'
8
+ belongs_to :inventory_unit, class_name: 'Spree::InventoryUnit'
9
+ has_one :order, through: :line_item
8
10
 
9
11
  validates :amount, numericality: { greater_than: 0 }
10
12
  validates_uniqueness_of :redemption_code, conditions: -> { where(redeemed_at: nil, redeemable: true) }
@@ -22,6 +24,10 @@ class Spree::VirtualGiftCard < ActiveRecord::Base
22
24
  redeemed_at.present?
23
25
  end
24
26
 
27
+ def deactivated?
28
+ deactivated_at.present?
29
+ end
30
+
25
31
  def redeem(redeemer)
26
32
  return false if redeemed? || !redeemable?
27
33
  create_store_credit!({
@@ -36,8 +42,17 @@ class Spree::VirtualGiftCard < ActiveRecord::Base
36
42
  self.update_attributes( redeemed_at: Time.now, redeemer: redeemer )
37
43
  end
38
44
 
39
- def make_redeemable!(purchaser:)
40
- update_attributes!(redeemable: true, purchaser: purchaser, redemption_code: (self.redemption_code || generate_unique_redemption_code))
45
+ def make_redeemable!(purchaser:, inventory_unit:)
46
+ update_attributes!(redeemable: true, purchaser: purchaser, inventory_unit: inventory_unit, redemption_code: (self.redemption_code || generate_unique_redemption_code))
47
+ end
48
+
49
+ def deactivate
50
+ update_attributes(redeemable: false, deactivated_at: Time.now) &&
51
+ cancel_and_reimburse_inventory_unit
52
+ end
53
+
54
+ def can_deactivate?
55
+ order.completed? && order.paid? && !deactivated?
41
56
  end
42
57
 
43
58
  def memo
@@ -81,6 +96,10 @@ class Spree::VirtualGiftCard < ActiveRecord::Base
81
96
  redeemed_at.localtime.strftime("%F %I:%M%p") if redeemed_at
82
97
  end
83
98
 
99
+ def formatted_deactivated_at
100
+ deactivated_at.localtime.strftime("%F %I:%M%p") if deactivated_at
101
+ end
102
+
84
103
  def store_credit_category
85
104
  Spree::StoreCreditCategory.where(name: Spree::StoreCreditCategory::GIFT_CARD_CATEGORY_NAME).first
86
105
  end
@@ -96,6 +115,12 @@ class Spree::VirtualGiftCard < ActiveRecord::Base
96
115
 
97
116
  private
98
117
 
118
+ def cancel_and_reimburse_inventory_unit
119
+ cancellation = Spree::OrderCancellations.new(line_item.order)
120
+ cancellation.cancel_unit(inventory_unit)
121
+ !!cancellation.reimburse_units([inventory_unit])
122
+ end
123
+
99
124
  def generate_unique_redemption_code
100
125
  redemption_code = Spree::RedemptionCodeGenerator.generate_redemption_code
101
126
 
@@ -1,6 +1,9 @@
1
1
  Deface::Override.new(
2
- virtual_path: "spree/admin/shared/_menu",
2
+ virtual_path: "spree/admin/shared/_tabs",
3
3
  name: "admin_user_sub_menu_index",
4
- insert_after: "#admin-menu",
5
- partial: "spree/admin/users/sub_menu",
6
- )
4
+ replace: "erb[loud]:contains('BackendConfiguration::USER_TABS')",
5
+ text: <<-ERB)
6
+ <%= tab *Spree::BackendConfiguration::USER_TABS, url: spree.admin_users_path, icon: 'user' do %>
7
+ <%- render "spree/admin/users/sub_menu" %>
8
+ <%- end %>
9
+ ERB
@@ -0,0 +1,8 @@
1
+ <!-- insert_bottom '[data-hook="admin_product_form_right"]' -->
2
+ <div class="field">
3
+ <%= f.check_box(:gift_card) %>
4
+ <%= f.label :gift_card, Spree.t("admin.gift_cards.gift_card") %>
5
+ <span class="info">
6
+ <%= Spree.t("admin.gift_cards.convert_product_label") %>
7
+ </span>
8
+ </div>
@@ -1,33 +1,41 @@
1
- <div class='gift-card-code-lookup'>
2
- <%= search_form_for @search, url: admin_gift_cards_path(@search) do |f| %>
3
- <div class="four columns">
4
- <div class="field">
5
- <%= label_tag nil, "Redemption Code" %>
6
- <%= f.text_field :redemption_code_cont, :size => 27 %>
1
+ <% content_for :table_filter_title do %>
2
+ <%= Spree.t(:search) %>
3
+ <% end %>
4
+
5
+ <% content_for :table_filter do %>
6
+ <div class='gift-card-code-lookup'>
7
+ <%= search_form_for @search, url: admin_gift_cards_path(@search) do |f| %>
8
+ <div class="alpha four columns">
9
+ <div class="field">
10
+ <%= label_tag nil, "Redemption Code" %>
11
+ <%= f.text_field :redemption_code_cont, size: 27 %>
12
+ </div>
13
+ </div>
14
+ <div class="four columns">
15
+ <div class="field">
16
+ <%= label_tag nil, "Recipient Email" %>
17
+ <%= f.text_field :recipient_email_cont, size: 25 %>
18
+ </div>
7
19
  </div>
8
- </div>
9
- <div class="four columns">
10
- <div class="field">
11
- <%= label_tag nil, "Recipient Email" %>
12
- <%= f.text_field :recipient_email_cont, :size => 25 %>
20
+ <div class="four columns">
21
+ <div class="field">
22
+ <%= label_tag nil, "Order Number" %>
23
+ <%= f.text_field :line_item_order_number_cont, size: 25 %>
24
+ </div>
13
25
  </div>
14
- </div>
15
- <div class="four columns">
16
- <div class="field">
17
- <%= label_tag nil, "Order Number" %>
18
- <%= f.text_field :line_item_order_number_cont, :size => 25 %>
26
+ <div class="omega four columns">
27
+ <div class="field">
28
+ <%= label_tag nil, "Send Date" %>
29
+ <%= f.text_field :sent_at_or_send_email_at_is, class: 'datepicker', size: 25 %>
30
+ </div>
19
31
  </div>
20
- </div>
21
- <div class="three columns">
22
- <div class="field">
23
- <%= label_tag nil, "Send Date" %>
24
- <%= f.text_field :sent_at_or_send_email_at_is, :class => 'datepicker', :size => 25 %>
32
+
33
+ <div class="clearfix"></div>
34
+
35
+ <div class="actions filter-actions">
36
+ <%= button 'Lookup Gift Card', 'search' %>
25
37
  </div>
26
- </div>
27
- <div class="clearfix"></div>
28
- <div class="actions filter-actions">
29
- <%= button 'Lookup Gift Card', 'search', class: 'lookup-gift-card-button' %>
30
- </div>
31
- <% end %>
38
+ <% end %>
32
39
  </div>
40
+ <% end %>
33
41
 
@@ -67,15 +67,23 @@
67
67
  <%= f.text_field :send_email_at, :class => 'datepicker datepicker-from giftcard-datepicker' %>
68
68
  <% end %>
69
69
  <% end %>
70
+
71
+ <% if @gift_card.deactivated_at %>
72
+ <div class="deactivated-at">
73
+ Deactivated at: <%= @gift_card.formatted_deactivated_at %>
74
+ </div>
75
+ <% end %>
70
76
  </div>
71
77
  </div>
72
78
 
73
79
  <%= render :partial => 'spree/admin/shared/edit_resource_links', locals: { collection_url: edit_admin_order_path(@order) } %>
74
80
  </fieldset>
81
+ <% end %>
82
+
75
83
 
76
- <div class="form-buttons filter-actions actions" data-hook="buttons">
77
- <% if @order.completed? %>
78
- <%= button_link_to "Send email now", send_email_admin_order_gift_card_path(@order, @gift_card), :icon => 'email', :data => { :confirm => "Any changes that have not been updated will not send" } %>
79
- <% end %>
84
+ <% if @gift_card.can_deactivate? && can?(:deactivate, @gift_card) %>
85
+ <div class="form-buttons filter-actions actions gift-card-actions" data-hook="buttons">
86
+ <%= button_link_to "Send email now", send_email_admin_order_gift_card_path(@order, @gift_card), :icon => 'email', :method => 'put', :data => { :confirm => "Any changes that have not been updated will not send" } %>
87
+ <%= button_link_to "Deactivate", deactivate_admin_order_gift_card_path(@order, @gift_card), :icon => 'ban', :method => 'put', :data => { :confirm => "Are you sure you want to deactivate the gift card?" } %>
80
88
  </div>
81
89
  <% end %>
@@ -1,5 +1,11 @@
1
+ <% content_for :page_title do %>
2
+ <%= Spree.t(:listing_gift_cards) %>
3
+ <% end %>
4
+
1
5
  <%= render partial: 'lookup_form' %>
2
- <%= paginate @gift_cards %>
6
+
7
+ <%= paginate @gift_cards %>
8
+
3
9
  <% if @gift_cards.any? %>
4
10
  <table class="index">
5
11
  <thead>
@@ -1,2 +1,7 @@
1
1
  <br><strong><%= Spree.t('admin.gift_cards.redemption_code') %>:</strong> <%= gift_card.redemption_code %>
2
- <br><%= link_to '(Edit Details)', edit_admin_order_gift_card_path(@order, gift_card), class: 'edit-gift-card-details' %>
2
+ <br>
3
+ <% if gift_card.deactivated? %>
4
+ <b>DEACTIVATED</b>
5
+ <% end %>
6
+ <% edit_text = gift_card.deactivated? ? "(Details)" : "(Edit Details)" %>
7
+ <%= link_to edit_text, edit_admin_order_gift_card_path(@order, gift_card), class: 'edit-gift-card-details' %>
@@ -1,10 +1,6 @@
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>
1
+ <ul class="admin-subnav">
2
+ <%= tab :users, match_path: /\/users$/ %>
3
+ <% if can?(:display, Spree::VirtualGiftCard) %>
4
+ <%= tab :gift_cards, match_path: "/users/gift_cards" %>
9
5
  <% end %>
10
- <% end %>
6
+ </ul>
@@ -3,11 +3,17 @@ en:
3
3
  spree:
4
4
  admin:
5
5
  gift_cards:
6
+ convert_product_label: "Turn this product into a gift card?"
7
+ deactivated_gift_card: "Gift card deactivated"
6
8
  editing_gift_card: "Editing Gift Card"
7
9
  gift_card: "Gift Card"
8
10
  gift_card_details: "Gift Card Details"
9
11
  gift_card_originator: "Gift Card - Order #%{order_number}"
10
12
  gift_card_updated: "Gift card updated!"
13
+ gift_message: "Gift Message"
14
+ purchaser_name: "Purchaser Name"
15
+ recipient_email: "Recipient Email"
16
+ recipient_name: "Recipient Name"
11
17
  redeem: "Redeem"
12
18
  redeem_gift_card: "Redeem Gift Card"
13
19
  redeemed_gift_card: "Redeemed Gift Card"
@@ -15,10 +21,15 @@ en:
15
21
  errors:
16
22
  not_found: "Gift card was not found"
17
23
  please_try_again: "Please try again"
24
+ unable_to_deactivate_gift_card: "Unable to deactivate gift card"
18
25
  unable_to_redeem_gift_card: "Unable to redeem gift card"
26
+ unable_to_reimburse_gift_card: "Unable to reimburse gift card"
27
+ tab:
28
+ gift_cards: "Gift Cards"
19
29
  gift_card_mailer:
20
30
  gift_card_email:
21
31
  dear_customer: "Dear customer"
22
32
  your_gift_card_code: "Here is your gift card code"
23
33
  gift_card_code: "Gift card code: %{code}"
24
34
  subject: "Your gift card code"
35
+ listing_gift_cards: "Listing Gift Cards"
@@ -0,0 +1,27 @@
1
+ ---
2
+ it:
3
+ spree:
4
+ admin:
5
+ gift_cards:
6
+ editing_gift_card: "Modifica Gift Card"
7
+ deactivated_gift_card: "Gift Card disattivata"
8
+ gift_card: "Gift Card"
9
+ gift_card_details: "Dettagli Gift Card"
10
+ gift_card_originator: "Gift Card - Ordine #%{order_number}"
11
+ gift_card_updated: "Gift Card aggiornata!"
12
+ redeem: "Riscuoti"
13
+ redeem_gift_card: "Utilizza Gift Card"
14
+ redeemed_gift_card: "Utilizza la tua Gift Card"
15
+ redemption_code: "Codice Gift Card"
16
+ errors:
17
+ not_found: "La Gift Card non è stata trovata"
18
+ please_try_again: "Si prega di riprovare"
19
+ unable_to_deactivate_gift_card: "Impossibile disattivate la Gift Card"
20
+ unable_to_redeem_gift_card: "Impossibile utilizzare la Gift Card"
21
+ unable_to_reimburse_gift_card: "Impossibile rimborsare la Gift Card"
22
+ gift_card_mailer:
23
+ gift_card_email:
24
+ dear_customer: "Gentile CLiente"
25
+ your_gift_card_code: "ecco il codice della tua Gift Card"
26
+ gift_card_code: "Codice Gift Card: %{code}"
27
+ subject: "Il codice della tua Gift Card"
data/config/routes.rb CHANGED
@@ -15,7 +15,8 @@ Spree::Core::Engine.routes.draw do
15
15
  resources :orders, only: [] do
16
16
  resources :gift_cards, only: [:edit, :update] do
17
17
  member do
18
- get :send_email
18
+ put :send_email
19
+ put :deactivate
19
20
  end
20
21
  end
21
22
  end
@@ -0,0 +1,5 @@
1
+ class AddDeactivatedAtToGiftCard < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_virtual_gift_cards, :deactivated_at, :datetime
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddInventoryUnitToGiftCard < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_virtual_gift_cards, :inventory_unit_id, :integer
4
+ end
5
+ end
@@ -0,0 +1,27 @@
1
+ class BackfillInventoryUnitsOnGiftCard < ActiveRecord::Migration
2
+ def up
3
+ gift_card_products = Spree::Product.where(gift_card: true)
4
+
5
+ gift_card_products.find_each do |product|
6
+ line_items = product.line_items
7
+
8
+ line_items.find_each do |line_item|
9
+ if line_item.order.completed? && !line_item.gift_cards.all? {|gc| gc.inventory_unit.present? }
10
+ inventory_units = line_item.inventory_units
11
+
12
+ line_item.gift_cards.each_with_index do |gift_card, i|
13
+ inventory_unit = inventory_units[i]
14
+ gift_card.update_attributes!(inventory_unit: inventory_unit)
15
+ say "Updating gift card #{gift_card.id} to have inventory unit #{inventory_unit.id}"
16
+ end
17
+ else
18
+ say "Skipping line_item #{line_item.id}. Order incomplete or gift cards associated to inventory units"
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def down
25
+ Spree::VirtualGiftCard.update_all(inventory_unit_id: nil)
26
+ end
27
+ end
@@ -8,10 +8,6 @@ module SolidusVirtualGiftCard
8
8
  append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/solidus_virtual_gift_card\n"
9
9
  end
10
10
 
11
- def add_stylesheets
12
- inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/solidus_virtual_gift_card\n", before: /\*\//, verbose: true
13
- end
14
-
15
11
  def include_seed_data
16
12
  append_file "db/seeds.rb", <<-SEEDS
17
13
  \n
@@ -12,6 +12,11 @@ FactoryGirl.define do
12
12
 
13
13
  factory :redeemable_virtual_gift_card do
14
14
  association :purchaser, factory: :user
15
+ inventory_unit do |gift_card|
16
+ gift_card.line_item.inventory_units.select{|iu| iu.gift_card.nil? }.first ||
17
+ create(:inventory_unit, line_item: gift_card.line_item)
18
+ end
19
+
15
20
  redeemable true
16
21
 
17
22
  before(:create) do |gift_card, evaluator|
@@ -3,21 +3,22 @@
3
3
  Gem::Specification.new do |s|
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.name = "solidus_virtual_gift_card"
6
- s.version = "1.0.1"
6
+ s.version = "1.2.0"
7
7
  s.summary = "Virtual gift card for purchase, drops into the user's account as store credit"
8
8
  s.required_ruby_version = ">= 2.1"
9
9
 
10
- s.author = "Bonobos"
11
- s.email = "engineering@bonobos.com"
12
- s.homepage = "http://www.bonobos.com"
13
- s.license = %q{BSD-3}
10
+ s.author = "Solidus Team"
11
+ s.email = "contact@solidus.io"
12
+ s.homepage = "https://solidus.io"
13
+ s.license = "BSD-3-Clause"
14
14
 
15
15
  s.files = `git ls-files`.split("\n")
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
17
  s.require_path = "lib"
18
18
  s.requirements << "none"
19
19
 
20
- s.add_dependency "solidus", [">= 1.0.0", "< 1.2.0"]
20
+ s.add_dependency "solidus", "~> 1.2.0"
21
+ s.add_dependency "deface"
21
22
 
22
23
  s.add_development_dependency "rspec-rails", "~> 3.2"
23
24
  s.add_development_dependency "simplecov"
@@ -26,6 +27,7 @@ Gem::Specification.new do |s|
26
27
  s.add_development_dependency "coffee-rails"
27
28
  s.add_development_dependency "factory_girl"
28
29
  s.add_development_dependency "capybara"
30
+ s.add_development_dependency "poltergeist"
29
31
  s.add_development_dependency "database_cleaner"
30
32
  s.add_development_dependency "ffaker"
31
33
  end
@@ -24,6 +24,62 @@ describe Spree::Admin::GiftCardsController do
24
24
  end
25
25
  end
26
26
 
27
+ describe 'PUT deactivate' do
28
+ let(:user) { create :user }
29
+ let!(:gift_card) { create(:redeemable_virtual_gift_card, line_item: order.line_items.first) }
30
+ let(:order) { create(:shipped_order, line_items_count: 1) }
31
+ let!(:default_refund_reason) { Spree::RefundReason.find_or_create_by!(name: Spree::RefundReason::RETURN_PROCESSING_REASON, mutable: false) }
32
+
33
+ subject { spree_put :deactivate, id: gift_card.id, order_id: order.number }
34
+
35
+ context "when successful" do
36
+ it "redirects to the admin order edit page" do
37
+ expect(subject).to redirect_to spree.edit_admin_order_path(order)
38
+ end
39
+
40
+ it "deactivates the gift card" do
41
+ subject
42
+ expect(gift_card.reload.deactivated_at).to be_present
43
+ end
44
+ end
45
+
46
+ context "when deactivating fails without raising an exception" do
47
+ before { expect_any_instance_of(Spree::VirtualGiftCard).to receive(:deactivate).and_return(false) }
48
+
49
+ it "does not deactivate the gift card" do
50
+ subject
51
+ expect(gift_card.reload.deactivated_at).to be_nil
52
+ end
53
+
54
+ it "redirects to gift card edit page" do
55
+ expect(subject).to redirect_to spree.edit_admin_order_gift_card_path(order, gift_card)
56
+ end
57
+
58
+ it "sets the flash message" do
59
+ subject
60
+ expect(flash[:error]).to eq Spree.t('admin.gift_cards.errors.unable_to_reimburse_gift_card')
61
+ end
62
+ end
63
+
64
+ context "when deactivating fails from reimbursement" do
65
+ before { expect_any_instance_of(Spree::VirtualGiftCard).to receive(:deactivate).and_raise(Spree::Reimbursement::IncompleteReimbursementError) }
66
+
67
+ it "does not deactivate the gift card" do
68
+ subject
69
+ expect(gift_card.reload.deactivated_at).to be_nil
70
+ end
71
+
72
+ it "redirects to gift card edit page" do
73
+ expect(subject).to redirect_to spree.edit_admin_order_gift_card_path(order, gift_card)
74
+ end
75
+
76
+ it "sets the flash message" do
77
+ subject
78
+ expect(flash[:error]).to eq Spree.t('admin.gift_cards.errors.unable_to_reimburse_gift_card')
79
+ end
80
+ end
81
+ end
82
+
27
83
  describe 'POST redeem' do
28
84
  let(:user) { create :user }
29
85
  let(:gift_card) { create(:redeemable_virtual_gift_card) }
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Gift Cards', type: :feature, js: true do
4
+ stub_authorization!
5
+
6
+ let(:admin_user) { create(:admin_user) }
7
+
8
+ before do
9
+ allow_any_instance_of(Spree::Admin::BaseController).to receive(:spree_current_user).and_return(admin_user)
10
+ end
11
+
12
+ describe "edit product" do
13
+ let(:product) { create(:product, available_on: 1.year.from_now) }
14
+
15
+ it "can mark a product as a gift card" do
16
+ visit spree.admin_product_path(product)
17
+
18
+ find('#product_gift_card').click
19
+
20
+ click_on 'Update'
21
+
22
+ expect(page).to have_content("successfully updated!")
23
+ expect(page).to have_field('product_gift_card', checked: true)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::GiftCardMailer, type: :mailer do
4
+ context '#gift_card_email' do
5
+ let(:gift_card) { create(:redeemable_virtual_gift_card) }
6
+
7
+ subject { Spree::GiftCardMailer.gift_card_email(gift_card) }
8
+
9
+ context "the recipient email is blank" do
10
+ before do
11
+ gift_card.update_attributes!(recipient_email: "")
12
+ gift_card.line_item.order.update_attributes!(email: "gift_card_tester@example.com")
13
+ end
14
+
15
+ it "uses the email associated with the order" do
16
+ expect(subject.to).to contain_exactly('gift_card_tester@example.com')
17
+ end
18
+ end
19
+ end
20
+ end
@@ -39,7 +39,7 @@ describe Spree::LineItem do
39
39
  end
40
40
 
41
41
  it 'contains the correct keys and values' do
42
- gift_card_details = subject.first
42
+ gift_card_details = subject.detect{|x| x[:redemption_code] == gift_card.formatted_redemption_code }
43
43
  expect(gift_card_details[:amount]).to eq gift_card.formatted_amount
44
44
  expect(gift_card_details[:redemption_code]).to eq gift_card.formatted_redemption_code
45
45
  expect(gift_card_details[:recipient_email]).to eq gift_card.recipient_email
@@ -19,10 +19,97 @@ describe Spree::VirtualGiftCard do
19
19
  end
20
20
  end
21
21
 
22
+ describe "#can_deactivate?" do
23
+ subject { gift_card.can_deactivate? }
24
+
25
+ let!(:default_refund_reason) { Spree::RefundReason.find_or_create_by!(name: Spree::RefundReason::RETURN_PROCESSING_REASON, mutable: false) }
26
+ let(:gift_card) { create(:redeemable_virtual_gift_card, line_item: order.line_items.first) }
27
+
28
+ context "the order is not complete" do
29
+ let(:order) { create(:order_with_line_items, line_items_count: 1) }
30
+
31
+ it "can't deactivate" do
32
+ expect(subject).to be_falsey
33
+ end
34
+ end
35
+
36
+ context "gift card is already deactivated" do
37
+ before { gift_card.deactivate }
38
+ let(:order) { create(:shipped_order, line_items_count: 1) }
39
+
40
+ it "can't deactivate" do
41
+ expect(subject).to be_falsey
42
+ end
43
+ end
44
+
45
+ context "order is not paid" do
46
+ let(:order) { create(:order_with_line_items, line_items_count: 1) }
47
+
48
+ it "can't deactivate" do
49
+ expect(subject).to be_falsey
50
+ end
51
+ end
52
+
53
+ context "order is paid and complete and gift card is active" do
54
+ let(:order) { create(:shipped_order, line_items_count: 1) }
55
+
56
+ it "can deactivate" do
57
+ expect(subject).to be_truthy
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "#deactivate" do
63
+ let!(:gift_card) { create(:redeemable_virtual_gift_card, line_item: order.line_items.first) }
64
+ let(:order) { create(:shipped_order, line_items_count: 1) }
65
+ let!(:default_refund_reason) { Spree::RefundReason.find_or_create_by!(name: Spree::RefundReason::RETURN_PROCESSING_REASON, mutable: false) }
66
+ subject { gift_card.deactivate }
67
+
68
+ it "makes it not redeemable" do
69
+ subject
70
+ expect(gift_card.reload.redeemable?).to be_falsey
71
+ end
72
+
73
+ it "sets the deactivated_at" do
74
+ subject
75
+ expect(gift_card.reload.deactivated_at).to be_present
76
+ end
77
+
78
+ it "#deactivated? returns true" do
79
+ subject
80
+ expect(gift_card.reload.deactivated?).to be_truthy
81
+ end
82
+
83
+ it "cancels the inventory unit" do
84
+ subject
85
+ expect(gift_card.inventory_unit.unit_cancel).to be_present
86
+ end
87
+
88
+ it "creates a reimbursement" do
89
+ expect { subject }.to change { Spree::Reimbursement.count }.by(1)
90
+ end
91
+
92
+ it "returns true" do
93
+ expect(subject).to be_truthy
94
+ end
95
+ end
96
+
22
97
  describe '#make_redeemable!' do
23
98
  let(:user) { create(:user) }
24
99
  let(:gift_card) { create(:virtual_gift_card) }
25
- subject { gift_card.make_redeemable!(purchaser: user) }
100
+ let(:order) { create(:shipped_order, line_items_count: 1) }
101
+ let(:inventory_unit) { order.inventory_units.first }
102
+ subject { gift_card.make_redeemable!(purchaser: user, inventory_unit: inventory_unit) }
103
+
104
+ it "sets the purchaser" do
105
+ subject
106
+ expect(gift_card.purchaser).to be user
107
+ end
108
+
109
+ it "sets the inventory unit" do
110
+ subject
111
+ expect(gift_card.inventory_unit).to be inventory_unit
112
+ end
26
113
 
27
114
  context 'no collision on redemption code' do
28
115
  it 'sets a redemption code' do
@@ -85,6 +172,19 @@ describe Spree::VirtualGiftCard do
85
172
  end
86
173
  end
87
174
 
175
+ describe '#deactivated?' do
176
+ let(:gift_card) { build(:virtual_gift_card) }
177
+
178
+ it 'is deactivated if there is a deactivated_at set' do
179
+ gift_card.deactivated_at = Time.now
180
+ expect(gift_card.deactivated?).to be true
181
+ end
182
+
183
+ it 'is not deactivated if there is no timestamp for deactivated_at' do
184
+ expect(gift_card.deactivated?).to be false
185
+ end
186
+ end
187
+
88
188
  describe '#redeem' do
89
189
  let(:gift_card) { create(:redeemable_virtual_gift_card) }
90
190
  let(:redeemer) { create(:user) }
@@ -108,6 +208,26 @@ describe Spree::VirtualGiftCard do
108
208
  end
109
209
  end
110
210
 
211
+ context 'it has been deactivated' do
212
+ before do
213
+ expect(gift_card).to receive(:cancel_and_reimburse_inventory_unit).and_return(true)
214
+ gift_card.deactivate
215
+ end
216
+
217
+ it 'should return false' do
218
+ expect(subject).to be false
219
+ end
220
+
221
+ context 'does nothing to the gift card' do
222
+ it 'should not create a store credit' do
223
+ expect(gift_card.store_credit).not_to be_present
224
+ end
225
+
226
+ it 'should not update the gift card' do
227
+ expect { subject }.to_not change{ gift_card }
228
+ end
229
+ end
230
+ end
111
231
 
112
232
  context 'it has already been redeemed' do
113
233
  before { gift_card.redeemed_at = Date.yesterday }
data/spec/spec_helper.rb CHANGED
@@ -30,6 +30,12 @@ require 'cancan/matchers'
30
30
 
31
31
  require "spree_virtual_gift_card/factories"
32
32
 
33
+ require "capybara/poltergeist"
34
+ Capybara.register_driver :poltergeist do |app|
35
+ Capybara::Poltergeist::Driver.new(app, timeout: 120)
36
+ end
37
+ Capybara.javascript_driver = :poltergeist
38
+
33
39
  Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
34
40
 
35
41
  RSpec.configure do |config|
@@ -52,16 +58,17 @@ RSpec.configure do |config|
52
58
  config.include Spree::TestingSupport::ControllerRequests, type: :controller
53
59
  config.include Spree::TestingSupport::UrlHelpers, type: :controller
54
60
 
55
- # Ensure Suite is set to use transactions for speed.
56
61
  config.before :suite do
57
- DatabaseCleaner.strategy = :transaction
58
62
  DatabaseCleaner.clean_with :truncation
59
63
  end
60
64
 
61
- # Before each spec check if it is a Javascript test and switch between using
62
- # database transactions or not where necessary.
63
65
  config.before :each do |example|
64
- DatabaseCleaner.strategy = :truncation
66
+ if RSpec.current_example.metadata[:js]
67
+ page.driver.browser.url_blacklist = ['http://fonts.googleapis.com']
68
+ DatabaseCleaner.strategy = :truncation
69
+ else
70
+ DatabaseCleaner.strategy = :transaction
71
+ end
65
72
  DatabaseCleaner.start
66
73
 
67
74
  Spree::Api::Config[:requires_authentication] = true
@@ -69,7 +76,14 @@ RSpec.configure do |config|
69
76
  end
70
77
 
71
78
  # After each spec clean the database.
72
- config.after :each do
79
+ config.append_after :each do
73
80
  DatabaseCleaner.clean
74
81
  end
82
+
83
+ if defined?(VersionCake::TestHelpers)
84
+ config.include VersionCake::TestHelpers, type: :controller
85
+ config.before(:each, type: :controller) do
86
+ set_request_version('', 1)
87
+ end
88
+ end
75
89
  end
metadata CHANGED
@@ -1,35 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_virtual_gift_card
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Bonobos
7
+ - Solidus Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-09 00:00:00.000000000 Z
11
+ date: 2016-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: solidus
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 1.0.0
20
- - - "<"
17
+ - - "~>"
21
18
  - !ruby/object:Gem::Version
22
19
  version: 1.2.0
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: deface
29
+ requirement: !ruby/object:Gem::Requirement
26
30
  requirements:
27
31
  - - ">="
28
32
  - !ruby/object:Gem::Version
29
- version: 1.0.0
30
- - - "<"
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
31
39
  - !ruby/object:Gem::Version
32
- version: 1.2.0
40
+ version: '0'
33
41
  - !ruby/object:Gem::Dependency
34
42
  name: rspec-rails
35
43
  requirement: !ruby/object:Gem::Requirement
@@ -128,6 +136,20 @@ dependencies:
128
136
  - - ">="
129
137
  - !ruby/object:Gem::Version
130
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: poltergeist
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
131
153
  - !ruby/object:Gem::Dependency
132
154
  name: database_cleaner
133
155
  requirement: !ruby/object:Gem::Requirement
@@ -157,26 +179,31 @@ dependencies:
157
179
  - !ruby/object:Gem::Version
158
180
  version: '0'
159
181
  description:
160
- email: engineering@bonobos.com
182
+ email: contact@solidus.io
161
183
  executables: []
162
184
  extensions: []
163
185
  extra_rdoc_files: []
164
186
  files:
165
187
  - ".gitignore"
166
188
  - ".rspec"
189
+ - ".travis.yml"
167
190
  - Gemfile
168
191
  - LICENSE
169
192
  - README.md
170
193
  - Rakefile
171
194
  - app/assets/javascripts/spree/backend/solidus_virtual_gift_card.coffee
195
+ - app/assets/javascripts/spree/frontend/solidus_virtual_gift_card.js
172
196
  - app/assets/stylesheets/spree/backend/solidus_virtual_gift_card.css
197
+ - app/assets/stylesheets/spree/frontend/solidus_virtual_gift_card.css
173
198
  - app/controllers/spree/admin/gift_cards_controller.rb
174
199
  - app/controllers/spree/api/gift_cards_controller.rb
175
200
  - app/mailers/spree/gift_card_mailer.rb
201
+ - app/models/concerns/spree/gift_cards/inventory_unit_concerns.rb
176
202
  - app/models/concerns/spree/gift_cards/line_item_concerns.rb
177
203
  - app/models/concerns/spree/gift_cards/order_concerns.rb
178
204
  - app/models/concerns/spree/gift_cards/order_contents_concerns.rb
179
205
  - app/models/concerns/spree/redemption_code_generator.rb
206
+ - app/models/spree/inventory_unit_decorator.rb
180
207
  - app/models/spree/line_item_decorator.rb
181
208
  - app/models/spree/order_contents_decorator.rb
182
209
  - app/models/spree/order_decorator.rb
@@ -188,6 +215,7 @@ files:
188
215
  - app/overrides/admin_item_view_gift_card_codes.rb
189
216
  - app/overrides/admin_user_sidebar_store_credits.rb
190
217
  - app/overrides/admin_user_sub_menu.rb
218
+ - app/overrides/spree/admin/products/_form/add_gift_card.html.erb.deface
191
219
  - app/views/spree/admin/gift_cards/_lookup_form.html.erb
192
220
  - app/views/spree/admin/gift_cards/_redemption_form.html.erb
193
221
  - app/views/spree/admin/gift_cards/edit.html.erb
@@ -207,6 +235,7 @@ files:
207
235
  - config/initializers/line_item_controller_gift_card_details.rb
208
236
  - config/initializers/ransack.rb
209
237
  - config/locales/en.yml
238
+ - config/locales/it.yml
210
239
  - config/routes.rb
211
240
  - db/migrate/20140623152903_create_virtual_gift_card.rb
212
241
  - db/migrate/20140624175113_seed_gift_card_category.rb
@@ -217,6 +246,9 @@ files:
217
246
  - db/migrate/20151013210615_add_active_flag_to_virtual_gift_card.rb
218
247
  - db/migrate/20151013214647_set_redeemable_true_on_virtual_gift_cards.rb
219
248
  - db/migrate/20151019190731_add_email_send_time_to_virtual_gift_card.rb
249
+ - db/migrate/20151109202300_add_deactivated_at_to_gift_card.rb
250
+ - db/migrate/20151110202752_add_inventory_unit_to_gift_card.rb
251
+ - db/migrate/20151111211220_backfill_inventory_units_on_gift_card.rb
220
252
  - db/seeds.rb
221
253
  - lib/generators/solidus_virtual_gift_card/install/install_generator.rb
222
254
  - lib/solidus_virtual_gift_card.rb
@@ -227,7 +259,9 @@ files:
227
259
  - spec/controllers/spree/admin/gift_cards_controller_spec.rb
228
260
  - spec/controllers/spree/api/gift_cards_controller_spec.rb
229
261
  - spec/features/admin/gift_cards_spec.rb
262
+ - spec/features/admin/products_card_spec.rb
230
263
  - spec/lib/tasks/send_gift_card_emails_spec.rb
264
+ - spec/mailers/spree/gift_card_mailer_spec.rb
231
265
  - spec/models/concerns/spree/redemption_code_generator_spec.rb
232
266
  - spec/models/spree/line_item_spec.rb
233
267
  - spec/models/spree/order_contents_spec.rb
@@ -237,9 +271,9 @@ files:
237
271
  - spec/models/spree/store_credit_category_spec.rb
238
272
  - spec/models/spree/virtual_gift_card_spec.rb
239
273
  - spec/spec_helper.rb
240
- homepage: http://www.bonobos.com
274
+ homepage: https://solidus.io
241
275
  licenses:
242
- - BSD-3
276
+ - BSD-3-Clause
243
277
  metadata: {}
244
278
  post_install_message:
245
279
  rdoc_options: []
@@ -258,7 +292,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
258
292
  requirements:
259
293
  - none
260
294
  rubyforge_project:
261
- rubygems_version: 2.2.5
295
+ rubygems_version: 2.4.5.1
262
296
  signing_key:
263
297
  specification_version: 4
264
298
  summary: Virtual gift card for purchase, drops into the user's account as store credit
@@ -266,7 +300,9 @@ test_files:
266
300
  - spec/controllers/spree/admin/gift_cards_controller_spec.rb
267
301
  - spec/controllers/spree/api/gift_cards_controller_spec.rb
268
302
  - spec/features/admin/gift_cards_spec.rb
303
+ - spec/features/admin/products_card_spec.rb
269
304
  - spec/lib/tasks/send_gift_card_emails_spec.rb
305
+ - spec/mailers/spree/gift_card_mailer_spec.rb
270
306
  - spec/models/concerns/spree/redemption_code_generator_spec.rb
271
307
  - spec/models/spree/line_item_spec.rb
272
308
  - spec/models/spree/order_contents_spec.rb