solidus_virtual_gift_card 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/app/assets/javascripts/spree/backend/solidus_virtual_gift_card.coffee +6 -6
- data/app/assets/stylesheets/spree/backend/solidus_virtual_gift_card.css +4 -0
- data/app/controllers/spree/admin/gift_cards_controller.rb +32 -12
- data/app/mailers/spree/gift_card_mailer.rb +2 -1
- data/app/models/concerns/spree/gift_cards/line_item_concerns.rb +6 -1
- data/app/models/concerns/spree/gift_cards/order_concerns.rb +15 -9
- data/app/models/concerns/spree/gift_cards/order_contents_concerns.rb +84 -0
- data/app/models/spree/order_contents_decorator.rb +1 -0
- data/app/models/spree/virtual_gift_card.rb +47 -10
- data/app/overrides/admin_gift_card_order_confirmation.rb +6 -0
- data/app/overrides/admin_item_view_gift_card_codes.rb +9 -2
- data/app/views/spree/admin/gift_cards/_lookup_form.html.erb +31 -6
- data/app/views/spree/admin/gift_cards/edit.html.erb +81 -0
- data/app/views/spree/admin/gift_cards/index.html.erb +39 -0
- data/app/views/spree/admin/gift_cards/show.html.erb +0 -32
- data/app/views/spree/admin/orders/_cart_gift_card_details.html.erb +3 -0
- data/app/views/spree/admin/orders/_confirmation_gift_card_details.html.erb +50 -0
- data/app/views/spree/admin/orders/_gift_card_details.html.erb +2 -0
- data/app/views/spree/admin/orders/_shipments_gift_card_details.html.erb +3 -0
- data/bin/rails +1 -1
- data/config/initializers/line_item_controller_gift_card_details.rb +4 -0
- data/config/initializers/ransack.rb +7 -0
- data/config/locales/en.yml +3 -0
- data/config/routes.rb +9 -1
- data/db/migrate/20151013172931_add_recipient_fields_to_virtual_gift_card.rb +8 -0
- data/db/migrate/20151013210615_add_active_flag_to_virtual_gift_card.rb +5 -0
- data/db/migrate/20151013214647_set_redeemable_true_on_virtual_gift_cards.rb +11 -0
- data/db/migrate/20151019190731_add_email_send_time_to_virtual_gift_card.rb +7 -0
- data/lib/spree_virtual_gift_card/factories.rb +11 -2
- data/lib/tasks/send_gift_card_emails.rake +8 -0
- data/solidus_virtual_gift_card.gemspec +1 -1
- data/spec/controllers/spree/admin/gift_cards_controller_spec.rb +1 -33
- data/spec/controllers/spree/api/gift_cards_controller_spec.rb +1 -1
- data/spec/features/admin/gift_cards_spec.rb +74 -0
- data/spec/lib/tasks/send_gift_card_emails_spec.rb +60 -0
- data/spec/models/spree/line_item_spec.rb +21 -0
- data/spec/models/spree/order_contents_spec.rb +270 -0
- data/spec/models/spree/order_spec.rb +34 -57
- data/spec/models/spree/virtual_gift_card_spec.rb +54 -23
- data/spec/spec_helper.rb +1 -0
- metadata +23 -3
- data/app/views/spree/admin/orders/_gift_card_redemption_codes.html.erb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d68ab9a6fbe5f3e13073ab38d343df394def740a
|
4
|
+
data.tar.gz: 1ef7434bca9095d79f2889e46232725d85d6aab5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d2212e47e0a8463e009165fa50c4eaa27ec63f4b131c874919c3b479f18454d0012199a6d4034e78c5d161426eade5176d0c41c27a99cd584d72618a81fb371
|
7
|
+
data.tar.gz: 9636919f4bfbb68ff3b34509b952971d113147e47a61de9490a73b1c3c47d326a0e2dce7a60bf26bbc34bb52ed719c1f9b41a50162287a142775b04118235fb1
|
data/Gemfile
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
window.GiftCards =
|
2
|
-
|
3
|
-
$(document).
|
4
|
-
|
5
|
-
|
2
|
+
setAdminDatepicker: () ->
|
3
|
+
$(document).ready(() ->
|
4
|
+
if $(".giftcard-datepicker").val()
|
5
|
+
$(".giftcard-datepicker").datepicker("setDate", new Date($(".giftcard-datepicker").val().split("-")))
|
6
|
+
$(".giftcard-datepicker").datepicker("option", "minDate", new Date())
|
6
7
|
)
|
7
8
|
|
8
|
-
|
9
|
-
@_bindLookupGiftCard()
|
9
|
+
|
@@ -1,17 +1,30 @@
|
|
1
1
|
class Spree::Admin::GiftCardsController < Spree::Admin::BaseController
|
2
|
-
before_filter :load_gift_card_history, only: [:show]
|
3
2
|
before_filter :load_user, only: [:lookup, :redeem]
|
4
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]
|
5
6
|
|
6
7
|
def index
|
8
|
+
@search = Spree::VirtualGiftCard.purchased.search(params[:q])
|
9
|
+
@gift_cards = @search.result.page(params[:page]).per(params[:per_page])
|
7
10
|
end
|
8
11
|
|
9
|
-
def
|
12
|
+
def edit
|
10
13
|
end
|
11
14
|
|
12
15
|
def lookup
|
13
16
|
end
|
14
17
|
|
18
|
+
def update
|
19
|
+
if @gift_card.update_attributes(gift_card_params)
|
20
|
+
flash[:success] = Spree.t("admin.gift_cards.gift_card_updated")
|
21
|
+
redirect_to edit_admin_order_path(@order)
|
22
|
+
else
|
23
|
+
flash[:error] = @gift_card.errors.full_messages.join(", ")
|
24
|
+
redirect_to :back
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
15
28
|
def redeem
|
16
29
|
if @gift_card.redeem(@user)
|
17
30
|
flash[:success] = Spree.t("admin.gift_cards.redeemed_gift_card")
|
@@ -22,18 +35,13 @@ class Spree::Admin::GiftCardsController < Spree::Admin::BaseController
|
|
22
35
|
end
|
23
36
|
end
|
24
37
|
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
38
|
+
def send_email
|
39
|
+
@gift_card.send_email
|
40
|
+
redirect_to :back
|
35
41
|
end
|
36
42
|
|
43
|
+
private
|
44
|
+
|
37
45
|
def load_gift_card_for_redemption
|
38
46
|
redemption_code = Spree::RedemptionCodeGenerator.format_redemption_code_for_lookup(params[:gift_card][:redemption_code])
|
39
47
|
@gift_card = Spree::VirtualGiftCard.active_by_redemption_code(redemption_code)
|
@@ -44,10 +52,22 @@ class Spree::Admin::GiftCardsController < Spree::Admin::BaseController
|
|
44
52
|
end
|
45
53
|
end
|
46
54
|
|
55
|
+
def load_gift_card_by_id
|
56
|
+
@gift_card = Spree::VirtualGiftCard.find_by(id: params[:id])
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_order
|
60
|
+
@order = Spree::Order.find_by(number: params[:order_id])
|
61
|
+
end
|
62
|
+
|
47
63
|
def load_user
|
48
64
|
@user = Spree::User.find(params[:user_id])
|
49
65
|
end
|
50
66
|
|
67
|
+
def gift_card_params
|
68
|
+
params.require(:virtual_gift_card).permit(:recipient_name, :recipient_email, :purchaser_name, :gift_message, :send_email_at)
|
69
|
+
end
|
70
|
+
|
51
71
|
def model_class
|
52
72
|
Spree::VirtualGiftCard
|
53
73
|
end
|
@@ -2,7 +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
6
|
subject = "#{Spree::Store.current.name} #{Spree.t('gift_card_mailer.gift_card_email.subject')}"
|
6
|
-
mail(to:
|
7
|
+
mail(to: send_to_address, from: from_address, subject: subject)
|
7
8
|
end
|
8
9
|
end
|
@@ -3,8 +3,9 @@ module Spree
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
has_many :gift_cards, class_name: Spree::VirtualGiftCard
|
6
|
+
has_many :gift_cards, class_name: Spree::VirtualGiftCard, dependent: :destroy
|
7
7
|
delegate :gift_card?, :gift_card, to: :product
|
8
|
+
self.whitelisted_ransackable_associations += %w[order]
|
8
9
|
prepend(InstanceMethods)
|
9
10
|
end
|
10
11
|
|
@@ -12,6 +13,10 @@ module Spree
|
|
12
13
|
def redemption_codes
|
13
14
|
gift_cards.map {|gc| {amount: gc.formatted_amount, redemption_code: gc.formatted_redemption_code}}
|
14
15
|
end
|
16
|
+
|
17
|
+
def gift_card_details
|
18
|
+
gift_cards.map(&:details)
|
19
|
+
end
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
@@ -11,22 +11,28 @@ module Spree
|
|
11
11
|
end
|
12
12
|
|
13
13
|
module InstanceMethods
|
14
|
-
def
|
15
|
-
|
16
|
-
|
14
|
+
def gift_card_match(line_item, options)
|
15
|
+
return true unless line_item.gift_card?
|
16
|
+
return true unless options["gift_card_details"]
|
17
|
+
line_item.gift_cards.any? do |gift_card|
|
18
|
+
gc_detail_set = gift_card.details.stringify_keys.except("send_email_at").to_set
|
19
|
+
options_set = options["gift_card_details"].except("send_email_at").to_set
|
20
|
+
gc_detail_set.superset?(options_set)
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
+
def finalize!
|
25
|
+
super
|
26
|
+
gift_cards.each do |gift_card|
|
27
|
+
gift_card.make_redeemable!(purchaser: user)
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
31
|
def send_gift_card_emails
|
28
32
|
gift_cards.each do |gift_card|
|
29
|
-
|
33
|
+
if gift_card.send_email_at.nil? || gift_card.send_email_at <= DateTime.now
|
34
|
+
gift_card.send_email
|
35
|
+
end
|
30
36
|
end
|
31
37
|
end
|
32
38
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Spree
|
2
|
+
module GiftCards::OrderContentsConcerns
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
class GiftCardDateFormatError < StandardError; end
|
5
|
+
|
6
|
+
included do
|
7
|
+
prepend(InstanceMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
def add(variant, quantity = 1, options = {})
|
12
|
+
line_item = super
|
13
|
+
create_gift_cards(line_item, quantity, options["gift_card_details"] || {})
|
14
|
+
line_item
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove(variant, quantity = 1, options = {})
|
18
|
+
line_item = super
|
19
|
+
remove_gift_cards(line_item, quantity)
|
20
|
+
line_item
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_cart(params)
|
24
|
+
update_success = super(params)
|
25
|
+
|
26
|
+
if update_success && params[:line_items_attributes]
|
27
|
+
line_item = Spree::LineItem.find_by(id: params[:line_items_attributes][:id])
|
28
|
+
new_quantity = params[:line_items_attributes][:quantity].to_i
|
29
|
+
update_gift_cards(line_item, new_quantity)
|
30
|
+
end
|
31
|
+
|
32
|
+
update_success
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def create_gift_cards(line_item, quantity_diff, gift_card_details = {})
|
38
|
+
if line_item.gift_card?
|
39
|
+
quantity_diff.to_i.times do
|
40
|
+
Spree::VirtualGiftCard.create!(
|
41
|
+
amount: line_item.price,
|
42
|
+
currency: line_item.currency,
|
43
|
+
line_item: line_item,
|
44
|
+
recipient_name: gift_card_details["recipient_name"],
|
45
|
+
recipient_email: gift_card_details["recipient_email"],
|
46
|
+
purchaser_name: gift_card_details["purchaser_name"],
|
47
|
+
gift_message: gift_card_details["gift_message"],
|
48
|
+
send_email_at: format_date(gift_card_details["send_email_at"])
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def remove_gift_cards(line_item, quantity_diff)
|
55
|
+
if line_item.gift_card?
|
56
|
+
line_item.gift_cards.order(:created_at).last(quantity_diff).each(&:destroy!)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def update_gift_cards(line_item, new_quantity)
|
61
|
+
if line_item && line_item.gift_card?
|
62
|
+
gift_card_count = line_item.gift_cards.count
|
63
|
+
if new_quantity > gift_card_count
|
64
|
+
create_gift_cards(line_item, new_quantity - gift_card_count)
|
65
|
+
elsif new_quantity < line_item.gift_cards.count
|
66
|
+
remove_gift_cards(line_item, gift_card_count - new_quantity)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def format_date(date)
|
72
|
+
return date if date.acts_like?(:date) || date.acts_like?(:time)
|
73
|
+
return Date.today if date.nil?
|
74
|
+
|
75
|
+
begin
|
76
|
+
Date.parse(date)
|
77
|
+
rescue ArgumentError
|
78
|
+
raise GiftCardDateFormatError
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
Spree::OrderContents.include Spree::GiftCards::OrderContentsConcerns
|
@@ -5,22 +5,25 @@ 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
|
-
before_create :set_redemption_code, unless: -> { redemption_code }
|
9
|
-
|
10
8
|
|
11
9
|
validates :amount, numericality: { greater_than: 0 }
|
12
|
-
validates_uniqueness_of :redemption_code, conditions: -> { where(redeemed_at: nil) }
|
13
|
-
validates_presence_of :purchaser_id
|
10
|
+
validates_uniqueness_of :redemption_code, conditions: -> { where(redeemed_at: nil, redeemable: true) }
|
11
|
+
validates_presence_of :purchaser_id, if: Proc.new { |gc| gc.redeemable? }
|
14
12
|
|
15
13
|
scope :unredeemed, -> { where(redeemed_at: nil) }
|
16
14
|
scope :by_redemption_code, -> (redemption_code) { where(redemption_code: redemption_code) }
|
15
|
+
scope :purchased, -> { where(redeemable: true) }
|
16
|
+
|
17
|
+
ransacker :sent_at do
|
18
|
+
Arel.sql('date(sent_at)')
|
19
|
+
end
|
17
20
|
|
18
21
|
def redeemed?
|
19
22
|
redeemed_at.present?
|
20
23
|
end
|
21
24
|
|
22
25
|
def redeem(redeemer)
|
23
|
-
return false if redeemed?
|
26
|
+
return false if redeemed? || !redeemable?
|
24
27
|
create_store_credit!({
|
25
28
|
amount: amount,
|
26
29
|
currency: currency,
|
@@ -33,18 +36,51 @@ class Spree::VirtualGiftCard < ActiveRecord::Base
|
|
33
36
|
self.update_attributes( redeemed_at: Time.now, redeemer: redeemer )
|
34
37
|
end
|
35
38
|
|
39
|
+
def make_redeemable!(purchaser:)
|
40
|
+
update_attributes!(redeemable: true, purchaser: purchaser, redemption_code: (self.redemption_code || generate_unique_redemption_code))
|
41
|
+
end
|
42
|
+
|
36
43
|
def memo
|
37
44
|
"Gift Card ##{self.redemption_code}"
|
38
45
|
end
|
39
46
|
|
47
|
+
def details
|
48
|
+
{
|
49
|
+
amount: formatted_amount,
|
50
|
+
redemption_code: formatted_redemption_code,
|
51
|
+
recipient_email: recipient_email,
|
52
|
+
recipient_name: recipient_name,
|
53
|
+
purchaser_name: purchaser_name,
|
54
|
+
gift_message: gift_message,
|
55
|
+
send_email_at: send_email_at,
|
56
|
+
formatted_send_email_at: formatted_send_email_at
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
40
60
|
def formatted_redemption_code
|
41
|
-
redemption_code.scan(/.{4}/).join('-')
|
61
|
+
redemption_code.present? ? redemption_code.scan(/.{4}/).join('-') : ""
|
42
62
|
end
|
43
63
|
|
44
64
|
def formatted_amount
|
45
65
|
number_to_currency(amount, precision: 0)
|
46
66
|
end
|
47
67
|
|
68
|
+
def formatted_send_email_at
|
69
|
+
send_email_at.strftime("%-m/%-d/%y") if send_email_at
|
70
|
+
end
|
71
|
+
|
72
|
+
def formatted_sent_at
|
73
|
+
sent_at.strftime("%-m/%-d/%y") if sent_at
|
74
|
+
end
|
75
|
+
|
76
|
+
def formatted_created_at
|
77
|
+
created_at.localtime.strftime("%F %I:%M%p")
|
78
|
+
end
|
79
|
+
|
80
|
+
def formatted_redeemed_at
|
81
|
+
redeemed_at.localtime.strftime("%F %I:%M%p") if redeemed_at
|
82
|
+
end
|
83
|
+
|
48
84
|
def store_credit_category
|
49
85
|
Spree::StoreCreditCategory.where(name: Spree::StoreCreditCategory::GIFT_CARD_CATEGORY_NAME).first
|
50
86
|
end
|
@@ -53,12 +89,13 @@ class Spree::VirtualGiftCard < ActiveRecord::Base
|
|
53
89
|
Spree::VirtualGiftCard.unredeemed.by_redemption_code(redemption_code).first
|
54
90
|
end
|
55
91
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
self.redemption_code = generate_unique_redemption_code
|
92
|
+
def send_email
|
93
|
+
Spree::GiftCardMailer.gift_card_email(self).deliver_later
|
94
|
+
update_attributes!(sent_at: DateTime.now)
|
60
95
|
end
|
61
96
|
|
97
|
+
private
|
98
|
+
|
62
99
|
def generate_unique_redemption_code
|
63
100
|
redemption_code = Spree::RedemptionCodeGenerator.generate_redemption_code
|
64
101
|
|
@@ -1,13 +1,20 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: "spree/admin/orders/_line_items",
|
3
|
+
name: "add_gift_cards_to_admin_line_items",
|
4
|
+
insert_bottom: ".line-item-name",
|
5
|
+
partial: "spree/admin/orders/cart_gift_card_details",
|
6
|
+
)
|
7
|
+
|
1
8
|
Deface::Override.new(
|
2
9
|
virtual_path: "spree/admin/orders/_shipment_manifest",
|
3
10
|
name: "admin_item_view_gift_card_codes",
|
4
11
|
insert_bottom: ".item-name",
|
5
|
-
partial: "spree/admin/orders/
|
12
|
+
partial: "spree/admin/orders/shipments_gift_card_details",
|
6
13
|
)
|
7
14
|
|
8
15
|
Deface::Override.new(
|
9
16
|
virtual_path: "spree/admin/orders/_carton_manifest",
|
10
17
|
name: "admin_item_view_gift_card_codes",
|
11
18
|
insert_bottom: ".item-name",
|
12
|
-
partial: "spree/admin/orders/
|
19
|
+
partial: "spree/admin/orders/shipments_gift_card_details",
|
13
20
|
)
|
@@ -1,8 +1,33 @@
|
|
1
|
-
<script async='true'>GiftCards.init()</script>
|
2
|
-
|
3
1
|
<div class='gift-card-code-lookup'>
|
4
|
-
<%=
|
5
|
-
|
6
|
-
|
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 %>
|
7
|
+
</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 %>
|
13
|
+
</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 %>
|
19
|
+
</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 %>
|
25
|
+
</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>
|
7
31
|
<% end %>
|
8
|
-
</div>
|
32
|
+
</div>
|
33
|
+
|