caboose-cms 0.5.134 → 0.5.135
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/app/assets/javascripts/caboose/cart.js +28 -27
- data/app/controllers/caboose/checkout_controller.rb +3 -1
- data/app/controllers/caboose/line_items_controller.rb +1 -2
- data/app/controllers/caboose/order_packages_controller.rb +1 -2
- data/app/controllers/caboose/store_controller.rb +38 -29
- data/app/models/caboose/order.rb +2 -3
- data/app/models/caboose/order_package.rb +2 -2
- data/app/models/caboose/order_package_calculator.rb +2 -2
- data/app/models/caboose/schema.rb +39 -31
- data/app/models/caboose/shipping_calculator.rb +8 -8
- data/app/models/caboose/store_config.rb +8 -2
- data/app/models/caboose/tax_calculator.rb +74 -5
- data/app/views/caboose/checkout/gift_cards.html.erb +4 -1
- data/app/views/caboose/store/admin_edit.html.erb +110 -56
- data/lib/caboose/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjUxMjFiZDZmNDQ4YmM5ZTBkODRkNDdmMDZhNjM3N2MyZjgzNjFkNg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZTIyNGU4NzczZTAyMDczYjQ4NzNjN2Q5NTY5YTQxMmFmZGQyYjdkYw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODllZTllY2JhMGFlODhlNzAyMDMyZTExMDE1ZmRmZGJlOTE0MjYxMzg1YjIy
|
10
|
+
MDM4NDIwNTNhNzlhZDAwMWUxYjVkOWZjM2QxMjM5ZWMwOTNmY2I2Y2U5NTdl
|
11
|
+
YTlhMjNhOTE4OTAyNmZiNDM3ODhiM2JhMGU4NjhiYjBjODdmNzU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZTM3ODQ3OWUwZDEyZTJiYTFmMDc5NjhlOGZhMjRkMzhjNTdjNTIxMzBkMzJh
|
14
|
+
ZWE0YzRkYmM2N2Q3ZWU5NzNjZDE5Zjk5NjdmNzAwODYzZGRjMDU4ZjVkMzhj
|
15
|
+
MzFmYmU3ZTAwMjIyODlmZmM5YzIzNjcwYjlhM2NmMTE1NGRkZWE=
|
@@ -59,11 +59,17 @@ Cart.prototype = {
|
|
59
59
|
|
60
60
|
var item = $('<td/>').attr('valign', 'top').append(p.title + '<br/>' + v.title);
|
61
61
|
if (that.allow_edit_line_items == true)
|
62
|
-
item.append('<
|
62
|
+
item.append($('<div/>').append($('<a/>').attr('href','#').html('Remove').click(function(e) { e.preventDefault(); that.remove_item(li.id); })));
|
63
63
|
if (that.show_gift_options)
|
64
64
|
{
|
65
|
-
if (
|
65
|
+
if (that.allow_edit_line_items == true)
|
66
66
|
{
|
67
|
+
var gift_options_tbody = $('<tbody/>');
|
68
|
+
if (li.variant.product.allow_gift_wrap == true)
|
69
|
+
gift_options_tbody.append($('<tr/>').append($('<td/>').addClass('checkbox').append($('<div/>').attr('id', 'lineitem_' + li.id + '_gift_wrap' ))).append($('<td/>').append("Gift wrap ($" + parseFloat(li.variant.product.gift_wrap_price).toFixed(2) + ')')));
|
70
|
+
gift_options_tbody.append($('<tr/>').append($('<td/>').addClass('checkbox').append($('<div/>').attr('id', 'lineitem_' + li.id + '_hide_prices'))).append($('<td/>').append("Hide prices in receipt")));
|
71
|
+
gift_options_tbody.append($('<tr/>').append($('<td/>').attr('colspan', '2').append('Gift message<br/>').append($('<div/>').attr('id', 'lineitem_' + li.id + '_gift_message'))));
|
72
|
+
|
67
73
|
item
|
68
74
|
.append($('<div/>').addClass('gift_options_checkbox')
|
69
75
|
.append($('<table/>')
|
@@ -72,14 +78,8 @@ Cart.prototype = {
|
|
72
78
|
)
|
73
79
|
)
|
74
80
|
)
|
75
|
-
.append($('<div/>').attr('id', 'gift_options_' + li.id).addClass('gift_options').css('display', li.is_gift ? 'block' : 'none')
|
76
|
-
.append($('<table/>')
|
77
|
-
.append($('<tbody/>')
|
78
|
-
.append($('<tr/>').append($('<td/>').addClass('checkbox').append($('<div/>').attr('id', 'lineitem_' + li.id + '_gift_wrap' ))).append($('<td/>').append("Gift wrap ($" + parseFloat(li.variant.product.gift_wrap_price).toFixed(2) + ')')))
|
79
|
-
.append($('<tr/>').append($('<td/>').addClass('checkbox').append($('<div/>').attr('id', 'lineitem_' + li.id + '_hide_prices'))).append($('<td/>').append("Hide prices in receipt")))
|
80
|
-
.append($('<tr/>').append($('<td/>').attr('colspan', '2').append('Gift message<br/>').append($('<div/>').attr('id', 'lineitem_' + li.id + '_gift_message'))))
|
81
|
-
)
|
82
|
-
)
|
81
|
+
.append($('<div/>').attr('id', 'gift_options_' + li.id).addClass('gift_options').css('display', li.is_gift ? 'block' : 'none')
|
82
|
+
.append($('<table/>').append(gift_options_tbody))
|
83
83
|
);
|
84
84
|
}
|
85
85
|
else
|
@@ -116,27 +116,28 @@ Cart.prototype = {
|
|
116
116
|
.append($('<td/>').css('text-align', 'right').attr('colspan', 4).html('Subtotal'))
|
117
117
|
.append($('<td/>').css('text-align', 'right').html('$' + parseFloat(that.order.subtotal).toFixed(2)))
|
118
118
|
);
|
119
|
-
if (that.
|
119
|
+
if (that.show_tax)
|
120
120
|
{
|
121
121
|
tbody.append($('<tr/>')
|
122
|
-
.append($('<td/>').css('text-align', 'right').attr('colspan', 4).html('
|
123
|
-
.append($('<td/>').css('text-align', 'right').html('$' + parseFloat(that.order.
|
122
|
+
.append($('<td/>').css('text-align', 'right').attr('colspan', 4).html('Tax'))
|
123
|
+
.append($('<td/>').css('text-align', 'right').html('$' + parseFloat(that.order.tax).toFixed(2)))
|
124
124
|
);
|
125
125
|
}
|
126
|
-
if (that.
|
126
|
+
if (that.show_shipping)
|
127
127
|
{
|
128
|
+
var x = parseFloat(that.order.shipping) + parseFloat(that.order.handling);
|
128
129
|
tbody.append($('<tr/>')
|
129
|
-
.append($('<td/>').css('text-align', 'right').attr('colspan', 4).html('
|
130
|
-
.append($('<td/>').css('text-align', 'right').html('$' +
|
130
|
+
.append($('<td/>').css('text-align', 'right').attr('colspan', 4).html('Shipping & Handling'))
|
131
|
+
.append($('<td/>').css('text-align', 'right').html('$' + x.toFixed(2)))
|
131
132
|
);
|
132
133
|
}
|
133
|
-
if (that.
|
134
|
+
if (that.show_gift_wrap && that.order.gift_wrap > 0)
|
134
135
|
{
|
135
136
|
tbody.append($('<tr/>')
|
136
|
-
.append($('<td/>').css('text-align', 'right').attr('colspan', 4).html('
|
137
|
-
.append($('<td/>').css('text-align', 'right').html('$' + parseFloat(that.order.
|
137
|
+
.append($('<td/>').css('text-align', 'right').attr('colspan', 4).html('Gift Wrapping'))
|
138
|
+
.append($('<td/>').css('text-align', 'right').html('$' + parseFloat(that.order.gift_wrap).toFixed(2)))
|
138
139
|
);
|
139
|
-
}
|
140
|
+
}
|
140
141
|
if (that.show_discounts && that.order.discounts.length > 0)
|
141
142
|
{
|
142
143
|
$.each(that.order.discounts, function(i, d) {
|
@@ -169,20 +170,20 @@ Cart.prototype = {
|
|
169
170
|
$('#cart').empty().append($('<table/>').append(tbody));
|
170
171
|
|
171
172
|
// Make anything editable that needs to be
|
172
|
-
if (
|
173
|
+
if (that.allow_edit_line_items)
|
173
174
|
{
|
174
175
|
$.each(this.order.line_items, function(i, li) {
|
175
176
|
var p = li.variant.product;
|
176
|
-
var attribs = [];
|
177
|
-
|
178
|
-
attribs.push({ name: 'quantity', nice_name: 'Qty', type: 'text', value: li.quantity, width: 50, fixed_placeholder: false, after_update: function() { that.refresh(); } });
|
177
|
+
var attribs = [];
|
178
|
+
attribs.push({ name: 'quantity', nice_name: 'Qty', type: 'text', value: li.quantity, width: 50, fixed_placeholder: false, after_update: function() { that.refresh(); } });
|
179
179
|
if (that.show_gift_options)
|
180
180
|
{
|
181
181
|
attribs.push({ name: 'is_gift' , nice_name: 'This item is a gift' , type: 'checkbox' , value: li.is_gift , width: 40 , fixed_placeholder: false, after_update: function() { that.toggle_gift_options(this.li_id); }, li_id: li.id });
|
182
|
-
attribs.push({ name: 'hide_prices' , nice_name: 'Hide prices' , type: 'checkbox' , value: li.hide_prices , width: 40 , fixed_placeholder: false, after_update: function() { } });
|
183
|
-
|
182
|
+
attribs.push({ name: 'hide_prices' , nice_name: 'Hide prices' , type: 'checkbox' , value: li.hide_prices , width: 40 , fixed_placeholder: false, after_update: function() { } });
|
183
|
+
if (p.allow_gift_wrap == true)
|
184
|
+
attribs.push({ name: 'gift_wrap' , nice_name: 'Gift wrap' , type: 'checkbox' , value: li.gift_wrap , width: 40 , fixed_placeholder: false, after_update: function() { that.refresh(); } });
|
184
185
|
attribs.push({ name: 'gift_message' , nice_name: 'Gift message' , type: 'textarea' , value: li.gift_message , width: 400 , height: 75 , fixed_placeholder: false, after_update: function() { } });
|
185
|
-
}
|
186
|
+
}
|
186
187
|
m = new ModelBinder({
|
187
188
|
name: 'LineItem',
|
188
189
|
id: li.id,
|
@@ -34,7 +34,9 @@ module Caboose
|
|
34
34
|
# GET /checkout/shipping
|
35
35
|
def shipping
|
36
36
|
redirect_to '/checkout' and return if !logged_in?
|
37
|
-
redirect_to '/checkout/addresses' and return if @order.billing_address.nil? || (@order.has_shippable_items? && @order.shipping_address.nil?)
|
37
|
+
redirect_to '/checkout/addresses' and return if @order.billing_address.nil? || (@order.has_shippable_items? && @order.shipping_address.nil?)
|
38
|
+
|
39
|
+
@order.calculate
|
38
40
|
|
39
41
|
if !@order.has_shippable_items?
|
40
42
|
redirect_to '/checkout/gift-cards'
|
@@ -61,8 +61,7 @@ module Caboose
|
|
61
61
|
r = ShippingCalculator.rate(li.order, li.order.shipping_method_code)
|
62
62
|
li.order.shipping = r['negotiated_rate'] / 100
|
63
63
|
li.order.handling = (r['negotiated_rate'] / 100) * 0.05
|
64
|
-
|
65
|
-
li.order.tax = li.order.subtotal * tax_rate
|
64
|
+
li.order.tax = TaxCalculator.tax(li.order)
|
66
65
|
li.order.calculate_total
|
67
66
|
li.order.save
|
68
67
|
|
@@ -81,8 +81,7 @@ module Caboose
|
|
81
81
|
r = ShippingCalculator.rate(li.order, li.order.shipping_method_code)
|
82
82
|
li.order.shipping = r['negotiated_rate'] / 100
|
83
83
|
li.order.handling = (r['negotiated_rate'] / 100) * 0.05
|
84
|
-
|
85
|
-
li.order.tax = li.order.subtotal * tax_rate
|
84
|
+
li.order.tax = TaxCalculator.tax(li.order)
|
86
85
|
li.order.calculate_total
|
87
86
|
li.order.save
|
88
87
|
|
@@ -22,35 +22,44 @@ module Caboose
|
|
22
22
|
save = true
|
23
23
|
params.each do |name,value|
|
24
24
|
case name
|
25
|
-
when 'site_id'
|
26
|
-
when 'pp_name'
|
27
|
-
when 'pp_username'
|
28
|
-
when 'pp_password'
|
29
|
-
when 'pp_testing'
|
30
|
-
when 'pp_relay_domain'
|
31
|
-
when 'ups_username'
|
32
|
-
when 'ups_password'
|
33
|
-
when 'ups_key'
|
34
|
-
when 'ups_origin_account'
|
35
|
-
when 'usps_username'
|
36
|
-
when 'usps_secret_key'
|
37
|
-
when 'usps_publishable_key'
|
38
|
-
when 'fedex_username'
|
39
|
-
when 'fedex_password'
|
40
|
-
when 'fedex_key'
|
41
|
-
when 'fedex_account'
|
42
|
-
when '
|
43
|
-
when '
|
44
|
-
when '
|
45
|
-
when '
|
46
|
-
when '
|
47
|
-
when '
|
48
|
-
when '
|
49
|
-
when '
|
50
|
-
when '
|
51
|
-
when '
|
52
|
-
when '
|
53
|
-
when '
|
25
|
+
when 'site_id' then sc.site_id = value
|
26
|
+
when 'pp_name' then sc.pp_name = value
|
27
|
+
when 'pp_username' then sc.pp_username = value
|
28
|
+
when 'pp_password' then sc.pp_password = value
|
29
|
+
when 'pp_testing' then sc.pp_testing = value
|
30
|
+
when 'pp_relay_domain' then sc.pp_relay_domain = value
|
31
|
+
when 'ups_username' then sc.ups_username = value
|
32
|
+
when 'ups_password' then sc.ups_password = value
|
33
|
+
when 'ups_key' then sc.ups_key = value
|
34
|
+
when 'ups_origin_account' then sc.ups_origin_account = value
|
35
|
+
when 'usps_username' then sc.usps_username = value
|
36
|
+
when 'usps_secret_key' then sc.usps_secret_key = value
|
37
|
+
when 'usps_publishable_key' then sc.usps_publishable_key = value
|
38
|
+
when 'fedex_username' then sc.fedex_username = value
|
39
|
+
when 'fedex_password' then sc.fedex_password = value
|
40
|
+
when 'fedex_key' then sc.fedex_key = value
|
41
|
+
when 'fedex_account' then sc.fedex_account = value
|
42
|
+
when 'taxcloud_api_id' then sc.taxcloud_api_id = value
|
43
|
+
when 'taxcloud_api_key' then sc.taxcloud_api_key = value
|
44
|
+
when 'origin_address1' then sc.origin_address1 = value
|
45
|
+
when 'origin_address2' then sc.origin_address2 = value
|
46
|
+
when 'origin_state' then sc.origin_state = value
|
47
|
+
when 'origin_city' then sc.origin_city = value
|
48
|
+
when 'origin_zip' then sc.origin_zip = value
|
49
|
+
when 'origin_country' then sc.origin_country = value
|
50
|
+
when 'fulfillment_email' then sc.fulfillment_email = value
|
51
|
+
when 'shipping_email' then sc.shipping_email = value
|
52
|
+
when 'handling_percentage' then sc.handling_percentage = value
|
53
|
+
when 'auto_calculate_packages' then sc.auto_calculate_packages = value
|
54
|
+
when 'auto_calculate_shipping' then sc.auto_calculate_shipping = value
|
55
|
+
when 'auto_calculate_tax' then sc.auto_calculate_tax = value
|
56
|
+
when 'custom_packages_function' then sc.custom_packages_function = value
|
57
|
+
when 'custom_shipping_function' then sc.custom_shipping_function = value
|
58
|
+
when 'custom_tax_function' then sc.custom_tax_function = value
|
59
|
+
when 'length_unit' then sc.length_unit = value
|
60
|
+
when 'weight_unit' then sc.weight_unit = value
|
61
|
+
when 'download_url_expires_in' then sc.download_url_expires_in = value
|
62
|
+
when 'starting_order_number' then sc.starting_order_number = value
|
54
63
|
end
|
55
64
|
end
|
56
65
|
|
data/app/models/caboose/order.rb
CHANGED
@@ -154,9 +154,8 @@ module Caboose
|
|
154
154
|
return x
|
155
155
|
end
|
156
156
|
|
157
|
-
def calculate_tax
|
158
|
-
return
|
159
|
-
self.subtotal * TaxCalculator.tax_rate(self.shipping_address)
|
157
|
+
def calculate_tax
|
158
|
+
return TaxCalculator.tax(self)
|
160
159
|
end
|
161
160
|
|
162
161
|
def calculate_shipping
|
@@ -24,14 +24,14 @@ module Caboose
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def self.custom_order_packages(store_config, order)
|
27
|
-
eval(store_config.
|
27
|
+
eval(store_config.custom_packages_function)
|
28
28
|
end
|
29
29
|
|
30
30
|
# Calculates the shipping packages required for all the items in the order
|
31
31
|
def self.create_for_order(order)
|
32
32
|
|
33
33
|
store_config = order.site.store_config
|
34
|
-
if !store_config.
|
34
|
+
if !store_config.auto_calculate_packages
|
35
35
|
self.custom_order_packages(store_config, order)
|
36
36
|
return
|
37
37
|
end
|
@@ -5,14 +5,14 @@ module Caboose
|
|
5
5
|
class OrderPackageCalculator
|
6
6
|
|
7
7
|
def self.custom_order_packages(store_config, order)
|
8
|
-
return eval(store_config.
|
8
|
+
return eval(store_config.custom_packages_function)
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.order_packages(order)
|
12
12
|
return [] if Caboose::store_shipping.nil?
|
13
13
|
|
14
14
|
sc = order.site.store_config
|
15
|
-
if sc.
|
15
|
+
if !sc.auto_calculate_packages
|
16
16
|
order_packages = self.custom_order_packages(sc, order)
|
17
17
|
return order_packages
|
18
18
|
end
|
@@ -347,6 +347,7 @@ class Caboose::Schema < Caboose::Utilities::Schema
|
|
347
347
|
[ :alternate_id , :integer ],
|
348
348
|
[ :subtotal , :decimal , { :precision => 8, :scale => 2 }],
|
349
349
|
[ :tax , :decimal , { :precision => 8, :scale => 2 }],
|
350
|
+
[ :tax_rate , :decimal , { :precision => 8, :scale => 2 }],
|
350
351
|
[ :shipping , :decimal , { :precision => 8, :scale => 2 }],
|
351
352
|
[ :handling , :decimal , { :precision => 8, :scale => 2 }],
|
352
353
|
[ :gift_wrap , :decimal , { :precision => 8, :scale => 2 }],
|
@@ -605,37 +606,44 @@ class Caboose::Schema < Caboose::Utilities::Schema
|
|
605
606
|
[ :max_height , :decimal ]
|
606
607
|
],
|
607
608
|
Caboose::StoreConfig => [
|
608
|
-
[ :site_id
|
609
|
-
[ :pp_name
|
610
|
-
[ :pp_username
|
611
|
-
[ :pp_password
|
612
|
-
[ :pp_testing
|
613
|
-
[ :pp_relay_domain
|
614
|
-
[ :ups_username
|
615
|
-
[ :ups_password
|
616
|
-
[ :ups_key
|
617
|
-
[ :ups_origin_account
|
618
|
-
[ :usps_username
|
619
|
-
[ :usps_secret_key
|
620
|
-
[ :usps_publishable_key
|
621
|
-
[ :fedex_username
|
622
|
-
[ :fedex_password
|
623
|
-
[ :fedex_key
|
624
|
-
[ :fedex_account
|
625
|
-
[ :
|
626
|
-
[ :
|
627
|
-
[ :
|
628
|
-
[ :
|
629
|
-
[ :
|
630
|
-
[ :
|
631
|
-
[ :
|
632
|
-
[ :
|
633
|
-
[ :
|
634
|
-
[ :
|
635
|
-
[ :
|
636
|
-
[ :
|
637
|
-
[ :
|
638
|
-
[ :
|
609
|
+
[ :site_id , :integer ],
|
610
|
+
[ :pp_name , :string ],
|
611
|
+
[ :pp_username , :string ],
|
612
|
+
[ :pp_password , :string ],
|
613
|
+
[ :pp_testing , :boolean , { :default => true }],
|
614
|
+
[ :pp_relay_domain , :string ],
|
615
|
+
[ :ups_username , :string ],
|
616
|
+
[ :ups_password , :string ],
|
617
|
+
[ :ups_key , :string ],
|
618
|
+
[ :ups_origin_account , :string ],
|
619
|
+
[ :usps_username , :string ],
|
620
|
+
[ :usps_secret_key , :string ],
|
621
|
+
[ :usps_publishable_key , :string ],
|
622
|
+
[ :fedex_username , :string ],
|
623
|
+
[ :fedex_password , :string ],
|
624
|
+
[ :fedex_key , :string ],
|
625
|
+
[ :fedex_account , :string ],
|
626
|
+
[ :taxcloud_api_id , :string ],
|
627
|
+
[ :taxcloud_api_key , :string ],
|
628
|
+
[ :origin_address1 , :string ],
|
629
|
+
[ :origin_address2 , :string ],
|
630
|
+
[ :origin_state , :string ],
|
631
|
+
[ :origin_city , :string ],
|
632
|
+
[ :origin_zip , :string ],
|
633
|
+
[ :origin_country , :string ],
|
634
|
+
[ :fulfillment_email , :string ],
|
635
|
+
[ :shipping_email , :string ],
|
636
|
+
[ :handling_percentage , :string ],
|
637
|
+
[ :auto_calculate_packages , :boolean , { :default => true }],
|
638
|
+
[ :auto_calculate_shipping , :boolean , { :default => true }],
|
639
|
+
[ :auto_calculate_tax , :boolean , { :default => true }],
|
640
|
+
[ :custom_packages_function , :text ],
|
641
|
+
[ :custom_shipping_function , :text ],
|
642
|
+
[ :custom_tax_function , :text ],
|
643
|
+
[ :length_unit , :string , { :default => 'in' }],
|
644
|
+
[ :weight_unit , :string , { :default => 'oz' }],
|
645
|
+
[ :download_url_expires_in , :string , { :default => 5 }],
|
646
|
+
[ :starting_order_number , :integer , { :default => 1000 }]
|
639
647
|
],
|
640
648
|
Caboose::User => [
|
641
649
|
[ :site_id , :integer ],
|
@@ -5,14 +5,14 @@ module Caboose
|
|
5
5
|
class ShippingCalculator
|
6
6
|
|
7
7
|
def self.custom_rates(store_config, order)
|
8
|
-
return eval(store_config.
|
8
|
+
return eval(store_config.custom_shipping_function)
|
9
9
|
end
|
10
10
|
|
11
11
|
def self.rates(order)
|
12
12
|
|
13
13
|
return [] if order.site.nil? || order.site.store_config.nil?
|
14
14
|
sc = order.site.store_config
|
15
|
-
if sc.
|
15
|
+
if !sc.auto_calculate_shipping
|
16
16
|
rates = self.custom_rates(sc, order)
|
17
17
|
return rates
|
18
18
|
end
|
@@ -39,16 +39,16 @@ module Caboose
|
|
39
39
|
sp = op.shipping_package
|
40
40
|
package = op.activemerchant_package
|
41
41
|
rates = []
|
42
|
-
carriers.each do |name, carrier|
|
43
|
-
|
44
|
-
if sp.uses_carrier(name)
|
45
|
-
Caboose.log("Shipping package does use carrier #{name}.")
|
42
|
+
carriers.each do |name, carrier|
|
43
|
+
if sp.uses_carrier(name)
|
46
44
|
resp = carrier.find_rates(origin, destination, package)
|
47
|
-
resp.rates.sort_by(&:price).each do |rate|
|
45
|
+
resp.rates.sort_by(&:price).each do |rate|
|
48
46
|
sm = ShippingMethod.where( :carrier => name, :service_code => rate.service_code, :service_name => rate.service_name).first
|
49
47
|
sm = ShippingMethod.create(:carrier => name, :service_code => rate.service_code, :service_name => rate.service_name) if sm.nil?
|
50
48
|
next if !sp.uses_shipping_method(sm)
|
51
|
-
|
49
|
+
price = rate.total_price
|
50
|
+
price = rate.package_rates[0].rate if price.nil? && rate.package_rates && rate.package_rates.count > 0
|
51
|
+
rates << { :shipping_method => sm, :total_price => (price.to_d/100) }
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
@@ -21,6 +21,8 @@ module Caboose
|
|
21
21
|
:fedex_password,
|
22
22
|
:fedex_key,
|
23
23
|
:fedex_account,
|
24
|
+
:taxcloud_api_id,
|
25
|
+
:taxcloud_api_key,
|
24
26
|
:origin_country,
|
25
27
|
:origin_state,
|
26
28
|
:origin_city,
|
@@ -28,8 +30,12 @@ module Caboose
|
|
28
30
|
:fulfillment_email,
|
29
31
|
:shipping_email,
|
30
32
|
:handling_percentage,
|
31
|
-
:
|
32
|
-
:
|
33
|
+
:auto_calculate_packages,
|
34
|
+
:auto_calculate_shipping,
|
35
|
+
:auto_calculate_tax,
|
36
|
+
:custom_packages_function,
|
37
|
+
:custom_shipping_function,
|
38
|
+
:custom_tax_function,
|
33
39
|
:length_unit,
|
34
40
|
:weight_unit
|
35
41
|
|
@@ -1,9 +1,78 @@
|
|
1
|
+
require 'tax_cloud'
|
2
|
+
|
1
3
|
module Caboose
|
2
4
|
class TaxCalculator
|
3
|
-
|
4
|
-
|
5
|
-
return
|
6
|
-
|
5
|
+
|
6
|
+
def self.custom_tax(store_config, order)
|
7
|
+
return eval(store_config.custom_tax_function)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.tax(order)
|
11
|
+
return 0.00 if !order.shipping_address
|
12
|
+
|
13
|
+
sc = order.site.store_config
|
14
|
+
if !sc.auto_calculate_tax
|
15
|
+
tax = self.custom_tax(sc, order)
|
16
|
+
return tax
|
17
|
+
end
|
18
|
+
|
19
|
+
# See if the tax rate has already been calculated
|
20
|
+
# If so, use that instead of doing another web service call
|
21
|
+
if order.tax_rate
|
22
|
+
return order.subtotal * order.tax_rate
|
23
|
+
end
|
24
|
+
|
25
|
+
sa = order.shipping_address
|
26
|
+
|
27
|
+
TaxCloud.configure do |config|
|
28
|
+
config.api_login_id = sc.taxcloud_api_id
|
29
|
+
config.api_key = sc.taxcloud_api_key
|
30
|
+
config.usps_username = sc.usps_username
|
31
|
+
end
|
32
|
+
|
33
|
+
origin = TaxCloud::Address.new(
|
34
|
+
:address1 => sc.origin_address1,
|
35
|
+
:address2 => sc.origin_address2,
|
36
|
+
:city => sc.origin_city,
|
37
|
+
:state => sc.origin_state,
|
38
|
+
:zip5 => sc.origin_zip
|
39
|
+
)
|
40
|
+
destination = TaxCloud::Address.new(
|
41
|
+
:address1 => sa.address1,
|
42
|
+
:address2 => sa.address2,
|
43
|
+
:city => sa.city,
|
44
|
+
:state => sa.state,
|
45
|
+
:zip5 => sa.zip
|
46
|
+
)
|
47
|
+
transaction = TaxCloud::Transaction.new(
|
48
|
+
:customer_id => order.customer_id,
|
49
|
+
:cart_id => order.id,
|
50
|
+
:origin => origin,
|
51
|
+
:destination => destination
|
52
|
+
)
|
53
|
+
order.line_items.each_with_index do |li, i|
|
54
|
+
transaction.cart_items << TaxCloud::CartItem.new(
|
55
|
+
:index => i,
|
56
|
+
:item_id => li.variant.id,
|
57
|
+
:tic => TaxCloud::TaxCodes::GENERAL,
|
58
|
+
:price => li.unit_price,
|
59
|
+
:quantity => li.quantity
|
60
|
+
)
|
61
|
+
end
|
62
|
+
lookup = transaction.lookup
|
63
|
+
tax = lookup.tax_amount
|
64
|
+
|
65
|
+
# Save the tax rate
|
66
|
+
order.tax_rate = tax/order.subtotal
|
67
|
+
order.save
|
68
|
+
|
69
|
+
# Return the tax amount
|
70
|
+
return tax
|
71
|
+
|
72
|
+
#return 0.00 if address.nil? || address.city.nil? || address.state.nil?
|
73
|
+
#return 0 if address.state.downcase != 'al'
|
74
|
+
#return 0.09
|
75
|
+
|
7
76
|
#rate = 0.00
|
8
77
|
#city = address.city.downcase
|
9
78
|
#rate = rate + 0.05 if city == 'brookwood'
|
@@ -18,7 +87,7 @@ module Caboose
|
|
18
87
|
#rate = rate + 0.05 if city == 'vance'
|
19
88
|
#rate = rate + 0.05 if city == 'woodstock'
|
20
89
|
#rate = rate + 0.04 if address.state.downcase == 'al' || address.state.downcase == 'alabama'
|
21
|
-
#return rate.round(2)
|
90
|
+
#return rate.round(2)
|
22
91
|
end
|
23
92
|
end
|
24
93
|
end
|
@@ -3,45 +3,88 @@ sc = @store_config
|
|
3
3
|
%>
|
4
4
|
<h1>Edit Store</h1>
|
5
5
|
|
6
|
-
<p><div id='site_<%= @site.id %>_use_store'
|
6
|
+
<p><div id='site_<%= @site.id %>_use_store' ></div></p>
|
7
7
|
|
8
8
|
<h2>Payment Processor</h2>
|
9
|
-
<p><div id='storeconfig_<%= sc.id %>_pp_name'
|
10
|
-
<p><div id='storeconfig_<%= sc.id %>_pp_username'
|
11
|
-
<p><div id='storeconfig_<%= sc.id %>_pp_password'
|
12
|
-
<p><div id='storeconfig_<%= sc.id %>_pp_relay_domain'
|
13
|
-
<p><div id='storeconfig_<%= sc.id %>_pp_testing'
|
9
|
+
<p><div id='storeconfig_<%= sc.id %>_pp_name' ></div></p>
|
10
|
+
<p><div id='storeconfig_<%= sc.id %>_pp_username' ></div></p>
|
11
|
+
<p><div id='storeconfig_<%= sc.id %>_pp_password' ></div></p>
|
12
|
+
<p><div id='storeconfig_<%= sc.id %>_pp_relay_domain' ></div></p>
|
13
|
+
<p><div id='storeconfig_<%= sc.id %>_pp_testing' ></div></p>
|
14
|
+
<hr />
|
14
15
|
|
15
16
|
<h2>Fulfillment Contacts</h2>
|
16
|
-
<p><div id='storeconfig_<%= sc.id %>_fulfillment_email'
|
17
|
-
<p><div id='storeconfig_<%= sc.id %>_shipping_email'
|
17
|
+
<p><div id='storeconfig_<%= sc.id %>_fulfillment_email' ></div></p>
|
18
|
+
<p><div id='storeconfig_<%= sc.id %>_shipping_email' ></div></p>
|
19
|
+
<hr />
|
18
20
|
|
19
21
|
<h2>Dimension Units</h2>
|
20
|
-
<p><div id='storeconfig_<%= sc.id %>_length_unit'
|
21
|
-
<p><div id='storeconfig_<%= sc.id %>_weight_unit'
|
22
|
+
<p><div id='storeconfig_<%= sc.id %>_length_unit' ></div></p>
|
23
|
+
<p><div id='storeconfig_<%= sc.id %>_weight_unit' ></div></p>
|
24
|
+
<hr />
|
22
25
|
|
23
|
-
<h2>
|
24
|
-
<p
|
25
|
-
<p><div id='storeconfig_<%= sc.id %>
|
26
|
-
<p><div id='storeconfig_<%= sc.id %>
|
27
|
-
<p><div id='storeconfig_<%= sc.id %>
|
28
|
-
<
|
29
|
-
<p><
|
30
|
-
<p><div id='storeconfig_<%= sc.id %>
|
31
|
-
<p><
|
32
|
-
<
|
33
|
-
<p><div id='storeconfig_<%= sc.id %>_fedex_key' ></div></p>
|
34
|
-
<p><div id='storeconfig_<%= sc.id %>_fedex_account' ></div></p>
|
26
|
+
<h2>Tax</h2>
|
27
|
+
<p>If calculating tax automatically, a TaxCloud (<a href='http://taxcloud.net'>taxcloud.net</a>) account is required. Otherwise, a custom tax function is required.</p>
|
28
|
+
<p><div id='storeconfig_<%= sc.id %>_auto_calculate_tax' ></div></p>
|
29
|
+
<p><div id='storeconfig_<%= sc.id %>_taxcloud_api_id' ></div></p>
|
30
|
+
<p><div id='storeconfig_<%= sc.id %>_taxcloud_api_key' ></div></p>
|
31
|
+
<h3>Custom Tax Function</h3>
|
32
|
+
<p><code>def custom_tax_function(order) {</code></p>
|
33
|
+
<p><div id='storeconfig_<%= sc.id %>_custom_tax_function' ></div></p>
|
34
|
+
<p><code># return 0.00<br />}</code></p>
|
35
|
+
<hr />
|
35
36
|
|
36
|
-
<h2>
|
37
|
-
<p
|
38
|
-
<p><div id='storeconfig_<%= sc.id %>
|
39
|
-
<
|
40
|
-
<p><
|
37
|
+
<h2>Order Packages</h2>
|
38
|
+
<p>If calculating order packages automatically, all shippable variants must have dimensions and weights populated. Otherwise, a custom order packages function is required.</p>
|
39
|
+
<p><div id='storeconfig_<%= sc.id %>_auto_calculate_packages' ></div></p>
|
40
|
+
<h3>Custom Order Packages Function</h3>
|
41
|
+
<p><code>def custom_order_packages_function(order) {</code></p>
|
42
|
+
<p><div id='storeconfig_<%= sc.id %>_custom_packages_function' ></div></p>
|
43
|
+
<p><code># This function does not return anything, but creates the Caboose::OrderPackage objects for the given order<br />}</code></p>
|
44
|
+
<hr />
|
45
|
+
|
46
|
+
<h2>Shipping</h2>
|
47
|
+
<p>If calculating shipping rates automatically, all shippable variants must have dimensions and weights populated. Otherwise, a custom shipping rates function is required.</p>
|
48
|
+
<p><div id='storeconfig_<%= sc.id %>_auto_calculate_shipping' ></div></p>
|
49
|
+
<h3>Custom Shipping Rates Function</h3>
|
50
|
+
<p><code>def custom_shipping_rates_function(order) {</code></p>
|
51
|
+
<p><div id='storeconfig_<%= sc.id %>_custom_shipping_function' ></div></p>
|
52
|
+
<p><code>
|
53
|
+
# Returns an empty array by default.<br />
|
54
|
+
# Return an array of order packages and their rates<br />
|
55
|
+
# return [{<br />
|
56
|
+
# :order_package => Caboose::OrderPackage.new,<br />
|
57
|
+
# :rates => [{ <br />
|
58
|
+
# :shipping_method => Caboose::ShippingMethod.new,<br />
|
59
|
+
# :total_price => 3.50 <br />
|
60
|
+
# }]<br />
|
61
|
+
# }]<br />
|
62
|
+
}</code></p>
|
63
|
+
<h3>Shipping Origin</h3>
|
64
|
+
<p><div id='storeconfig_<%= sc.id %>_origin_address1' ></div></p>
|
65
|
+
<p><div id='storeconfig_<%= sc.id %>_origin_address2' ></div></p>
|
66
|
+
<p><div id='storeconfig_<%= sc.id %>_origin_city' ></div></p>
|
67
|
+
<p><div id='storeconfig_<%= sc.id %>_origin_state' ></div></p>
|
68
|
+
<p><div id='storeconfig_<%= sc.id %>_origin_zip' ></div></p>
|
69
|
+
<p><div id='storeconfig_<%= sc.id %>_origin_country' ></div></p>
|
70
|
+
<h3>Shipping Carriers</h3>
|
71
|
+
<p><div id='storeconfig_<%= sc.id %>_ups_username' ></div></p>
|
72
|
+
<p><div id='storeconfig_<%= sc.id %>_ups_password' ></div></p>
|
73
|
+
<p><div id='storeconfig_<%= sc.id %>_ups_key' ></div></p>
|
74
|
+
<p><div id='storeconfig_<%= sc.id %>_ups_origin_account' ></div></p>
|
75
|
+
<p><div id='storeconfig_<%= sc.id %>_usps_username' ></div></p>
|
76
|
+
<p><div id='storeconfig_<%= sc.id %>_usps_secret_key' ></div></p>
|
77
|
+
<p><div id='storeconfig_<%= sc.id %>_usps_publishable_key' ></div></p>
|
78
|
+
<p><div id='storeconfig_<%= sc.id %>_fedex_username' ></div></p>
|
79
|
+
<p><div id='storeconfig_<%= sc.id %>_fedex_password' ></div></p>
|
80
|
+
<p><div id='storeconfig_<%= sc.id %>_fedex_key' ></div></p>
|
81
|
+
<p><div id='storeconfig_<%= sc.id %>_fedex_account' ></div></p>
|
82
|
+
<hr />
|
41
83
|
|
42
84
|
<h2>Other</h2>
|
43
|
-
<p><div id='storeconfig_<%= sc.id %>_handling_percentage'
|
44
|
-
<p><div id='storeconfig_<%= sc.id %>_download_url_expires_in'
|
85
|
+
<p><div id='storeconfig_<%= sc.id %>_handling_percentage' ></div></p>
|
86
|
+
<p><div id='storeconfig_<%= sc.id %>_download_url_expires_in' ></div></p>
|
87
|
+
<p><div id='storeconfig_<%= sc.id %>_starting_order_number' ></div></p>
|
45
88
|
|
46
89
|
<div id='message'></div>
|
47
90
|
|
@@ -67,35 +110,46 @@ $(document).ready(function() {
|
|
67
110
|
update_url: '/admin/store',
|
68
111
|
authenticity_token: '<%= form_authenticity_token %>',
|
69
112
|
attributes: [
|
70
|
-
{ name: 'pp_name'
|
71
|
-
{ name: 'pp_username'
|
72
|
-
{ name: 'pp_password'
|
73
|
-
{ name: 'pp_relay_domain'
|
74
|
-
{ name: 'pp_testing'
|
75
|
-
{ name: 'fulfillment_email'
|
76
|
-
{ name: 'shipping_email'
|
77
|
-
{ name: 'handling_percentage'
|
78
|
-
{ name: 'length_unit'
|
79
|
-
{ name: 'weight_unit'
|
80
|
-
{ name: 'ups_username'
|
81
|
-
{ name: 'ups_password'
|
82
|
-
{ name: 'ups_key'
|
83
|
-
{ name: 'ups_origin_account'
|
84
|
-
{ name: 'usps_username'
|
85
|
-
{ name: 'usps_secret_key'
|
86
|
-
{ name: 'usps_publishable_key'
|
87
|
-
{ name: 'fedex_username'
|
88
|
-
{ name: 'fedex_password'
|
89
|
-
{ name: 'fedex_key'
|
90
|
-
{ name: 'fedex_account'
|
91
|
-
{ name: '
|
92
|
-
{ name: '
|
93
|
-
{ name: '
|
94
|
-
{ name: '
|
95
|
-
{ name: '
|
113
|
+
{ name: 'pp_name' , nice_name: 'Type' , type: 'select' , value: <%= raw Caboose.json(sc.pp_name ) %>, width: 400 , options_url: '/admin/store/payment-processor-options' },
|
114
|
+
{ name: 'pp_username' , nice_name: 'Username' , type: 'text' , value: <%= raw Caboose.json(sc.pp_username ) %>, width: 400 },
|
115
|
+
{ name: 'pp_password' , nice_name: 'Password' , type: 'text' , value: <%= raw Caboose.json(sc.pp_password ) %>, width: 400 },
|
116
|
+
{ name: 'pp_relay_domain' , nice_name: 'Relay Domain' , type: 'text' , value: <%= raw Caboose.json(sc.pp_relay_domain ) %>, width: 400 },
|
117
|
+
{ name: 'pp_testing' , nice_name: 'Test Mode' , type: 'checkbox' , value: <%= raw Caboose.json(sc.pp_testing ? 1 : 0 ) %>, width: 400 },
|
118
|
+
{ name: 'fulfillment_email' , nice_name: 'Fulfillment Email' , type: 'text' , value: <%= raw Caboose.json(sc.fulfillment_email ) %>, width: 400 },
|
119
|
+
{ name: 'shipping_email' , nice_name: 'Shipping Email' , type: 'text' , value: <%= raw Caboose.json(sc.shipping_email ) %>, width: 400 },
|
120
|
+
{ name: 'handling_percentage' , nice_name: 'Handling Percentage' , type: 'text' , value: <%= raw Caboose.json(sc.handling_percentage ) %>, width: 400 },
|
121
|
+
{ name: 'length_unit' , nice_name: 'Length' , type: 'select' , value: <%= raw Caboose.json(sc.length_unit ) %>, width: 400 , options_url: '/admin/store/length-unit-options' },
|
122
|
+
{ name: 'weight_unit' , nice_name: 'Weight' , type: 'select' , value: <%= raw Caboose.json(sc.weight_unit ) %>, width: 400 , options_url: '/admin/store/weight-unit-options' },
|
123
|
+
{ name: 'ups_username' , nice_name: 'UPS Username' , type: 'text' , value: <%= raw Caboose.json(sc.ups_username ) %>, width: 400 },
|
124
|
+
{ name: 'ups_password' , nice_name: 'UPS Password' , type: 'text' , value: <%= raw Caboose.json(sc.ups_password ) %>, width: 400 },
|
125
|
+
{ name: 'ups_key' , nice_name: 'UPS Key' , type: 'text' , value: <%= raw Caboose.json(sc.ups_key ) %>, width: 400 },
|
126
|
+
{ name: 'ups_origin_account' , nice_name: 'UPS Origin Account' , type: 'text' , value: <%= raw Caboose.json(sc.ups_origin_account ) %>, width: 400 },
|
127
|
+
{ name: 'usps_username' , nice_name: 'USPS Username' , type: 'text' , value: <%= raw Caboose.json(sc.usps_username ) %>, width: 400 },
|
128
|
+
{ name: 'usps_secret_key' , nice_name: 'USPS Secret Key' , type: 'text' , value: <%= raw Caboose.json(sc.usps_secret_key ) %>, width: 400 },
|
129
|
+
{ name: 'usps_publishable_key' , nice_name: 'USPS Publishable Key' , type: 'text' , value: <%= raw Caboose.json(sc.usps_publishable_key ) %>, width: 400 },
|
130
|
+
{ name: 'fedex_username' , nice_name: 'FedEx Username' , type: 'text' , value: <%= raw Caboose.json(sc.fedex_username ) %>, width: 400 },
|
131
|
+
{ name: 'fedex_password' , nice_name: 'FedEx Password' , type: 'text' , value: <%= raw Caboose.json(sc.fedex_password ) %>, width: 400 },
|
132
|
+
{ name: 'fedex_key' , nice_name: 'FedEx Key' , type: 'text' , value: <%= raw Caboose.json(sc.fedex_key ) %>, width: 400 },
|
133
|
+
{ name: 'fedex_account' , nice_name: 'FedEx Account' , type: 'text' , value: <%= raw Caboose.json(sc.fedex_account ) %>, width: 400 },
|
134
|
+
{ name: 'taxcloud_api_id' , nice_name: 'TaxCloud API ID' , type: 'text' , value: <%= raw Caboose.json(sc.taxcloud_api_id ) %>, width: 400 },
|
135
|
+
{ name: 'taxcloud_api_key' , nice_name: 'TaxCloud API Key' , type: 'text' , value: <%= raw Caboose.json(sc.taxcloud_api_key ) %>, width: 400 },
|
136
|
+
{ name: 'origin_address1' , nice_name: 'Address 1' , type: 'text' , value: <%= raw Caboose.json(sc.origin_address1 ) %>, width: 400 },
|
137
|
+
{ name: 'origin_address2' , nice_name: 'Address 2' , type: 'text' , value: <%= raw Caboose.json(sc.origin_address2 ) %>, width: 400 },
|
138
|
+
{ name: 'origin_city' , nice_name: 'City' , type: 'text' , value: <%= raw Caboose.json(sc.origin_city ) %>, width: 400 },
|
139
|
+
{ name: 'origin_state' , nice_name: 'State' , type: 'text' , value: <%= raw Caboose.json(sc.origin_state ) %>, width: 400 },
|
140
|
+
{ name: 'origin_zip' , nice_name: 'Zip' , type: 'text' , value: <%= raw Caboose.json(sc.origin_zip ) %>, width: 400 },
|
141
|
+
{ name: 'origin_country' , nice_name: 'Country' , type: 'text' , value: <%= raw Caboose.json(sc.origin_country ) %>, width: 400 },
|
142
|
+
{ name: 'download_url_expires_in' , nice_name: 'Download URL Expires In (minutes)' , type: 'text' , value: <%= raw Caboose.json(sc.download_url_expires_in ) %>, width: 400 },
|
143
|
+
{ name: 'starting_order_number' , nice_name: 'Starting Order Number' , type: 'text' , value: <%= raw Caboose.json(sc.starting_order_number ) %>, width: 400 },
|
144
|
+
{ name: 'auto_calculate_packages' , nice_name: 'Automatically Calculate Packages' , type: 'checkbox' , value: <%= raw Caboose.json(sc.auto_calculate_packages ? 1 : 0 ) %>, width: 400 },
|
145
|
+
{ name: 'auto_calculate_shipping' , nice_name: 'Calculate Shipping Automatically' , type: 'checkbox' , value: <%= raw Caboose.json(sc.auto_calculate_shipping ? 1 : 0 ) %>, width: 400 },
|
146
|
+
{ name: 'auto_calculate_tax' , nice_name: 'Automatically Calculate Tax' , type: 'checkbox' , value: <%= raw Caboose.json(sc.auto_calculate_tax ? 1 : 0 ) %>, width: 400 },
|
147
|
+
{ name: 'custom_packages_function' , nice_name: 'Custom Packages Function' , type: 'textarea' , value: <%= raw Caboose.json(sc.custom_packages_function ) %>, width: 800, height: 200, fixed_placeholder: false },
|
148
|
+
{ name: 'custom_shipping_function' , nice_name: 'Custom Shipping Function' , type: 'textarea' , value: <%= raw Caboose.json(sc.custom_shipping_function ) %>, width: 800, height: 200, fixed_placeholder: false },
|
149
|
+
{ name: 'custom_tax_function' , nice_name: 'Custom Tax Function' , type: 'textarea' , value: <%= raw Caboose.json(sc.custom_tax_function ) %>, width: 800, height: 200, fixed_placeholder: false },
|
96
150
|
]
|
97
151
|
});
|
98
|
-
|
152
|
+
|
99
153
|
});
|
100
154
|
|
101
155
|
</script>
|
data/lib/caboose/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caboose-cms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.135
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Barry
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -262,6 +262,20 @@ dependencies:
|
|
262
262
|
- - ! '>='
|
263
263
|
- !ruby/object:Gem::Version
|
264
264
|
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: tax_cloud
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - ! '>='
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
type: :runtime
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ! '>='
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
265
279
|
- !ruby/object:Gem::Dependency
|
266
280
|
name: rspec-rails
|
267
281
|
requirement: !ruby/object:Gem::Requirement
|