stall 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +60 -23
- data/app/assets/javascripts/para/stall.coffee +1 -0
- data/app/assets/javascripts/para/stall/inputs/variant-select.coffee +62 -0
- data/app/assets/javascripts/para/stall/inputs/variants-matrix.coffee +12 -0
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/helpers.coffee +40 -0
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/input.coffee +133 -0
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/nested-fields.coffee +38 -0
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/properties_select.coffee +45 -0
- data/app/assets/javascripts/para/stall/inputs/variants-matrix/variant.coffee +59 -0
- data/app/assets/javascripts/stall.coffee +1 -0
- data/app/assets/javascripts/stall/add-to-cart-form.coffee +53 -28
- data/app/assets/javascripts/stall/cart-form.coffee +7 -2
- data/app/assets/stylesheets/para/stall.sass +28 -0
- data/app/controllers/para/stall/admin/carts_controller.rb +27 -0
- data/app/controllers/stall/cart_credits_controller.rb +27 -0
- data/app/controllers/stall/carts_controller.rb +1 -1
- data/app/controllers/stall/checkout/steps_controller.rb +22 -12
- data/app/controllers/stall/checkouts_controller.rb +1 -0
- data/app/controllers/stall/line_items_controller.rb +1 -0
- data/app/controllers/stall/payments_controller.rb +16 -1
- data/app/helpers/stall/credit_notes_helper.rb +25 -0
- data/app/helpers/stall/customers_helper.rb +3 -1
- data/app/models/billing_address.rb +2 -0
- data/app/models/cart_credit_note_adjustment.rb +3 -0
- data/app/models/credit_note.rb +3 -0
- data/app/models/credit_note_adjustment.rb +3 -0
- data/app/models/credit_note_usage.rb +3 -0
- data/app/models/product.rb +3 -0
- data/app/models/product_category.rb +3 -0
- data/app/models/product_detail.rb +3 -0
- data/app/models/property.rb +3 -0
- data/app/models/property_value.rb +3 -0
- data/app/models/shipping_address.rb +2 -0
- data/app/models/stall/models/address.rb +2 -2
- data/app/models/stall/models/cart.rb +2 -15
- data/app/models/stall/models/cart_credit_note_adjustment.rb +11 -0
- data/app/models/stall/models/credit_note.rb +50 -0
- data/app/models/stall/models/credit_note_adjustment.rb +13 -0
- data/app/models/stall/models/credit_note_usage.rb +16 -0
- data/app/models/stall/models/customer.rb +20 -8
- data/app/models/stall/models/line_item.rb +9 -0
- data/app/models/stall/models/product.rb +45 -0
- data/app/models/stall/models/product_category.rb +31 -0
- data/app/models/stall/models/product_detail.rb +17 -0
- data/app/models/stall/models/product_list.rb +9 -45
- data/app/models/stall/models/property.rb +20 -0
- data/app/models/stall/models/property_value.rb +23 -0
- data/app/models/stall/models/variant.rb +34 -0
- data/app/models/stall/models/variant_property_value.rb +18 -0
- data/app/models/variant.rb +3 -0
- data/app/models/variant_property_value.rb +3 -0
- data/app/services/stall/cart_credit_note_creation_service.rb +40 -0
- data/app/services/stall/cart_payment_validation_service.rb +28 -0
- data/app/services/stall/cart_update_service.rb +17 -6
- data/app/services/stall/credit_usage_service.rb +102 -0
- data/app/services/stall/payment_notification_service.rb +4 -8
- data/app/services/stall/product_list_staleness_handling_service.rb +33 -0
- data/app/views/admin/addresses/_fields.html.haml +9 -0
- data/app/views/admin/carts/_filters.html.haml +17 -0
- data/app/views/admin/carts/_form.html.haml +43 -0
- data/app/views/admin/carts/_table.html.haml +17 -0
- data/app/views/admin/customers/_fields.html.haml +1 -0
- data/app/views/admin/line_items/_fields.html.haml +15 -0
- data/app/views/admin/products/_table.html.haml +12 -0
- data/app/views/admin/properties/_form.html.haml +6 -0
- data/app/views/admin/properties/_table.html.haml +8 -0
- data/app/views/admin/property_values/_fields.html.haml +1 -0
- data/app/views/admin/shipments/_fields.html.haml +7 -0
- data/app/views/checkout/steps/_informations.html.haml +3 -1
- data/app/views/checkout/steps/_payment.html.haml +2 -0
- data/app/views/checkout/steps/_payment_return.html.haml +0 -1
- data/app/views/para/admin/resources/_variant_row.html.haml +24 -0
- data/app/views/para/stall/inputs/_variant_select.html.haml +14 -0
- data/app/views/para/stall/inputs/_variants_matrix.html.haml +41 -0
- data/app/views/stall/addresses/_fields.html.haml +6 -12
- data/app/views/stall/carts/_cart.html.haml +45 -37
- data/app/views/stall/carts/_widget.html.haml +28 -0
- data/app/views/stall/carts/show.html.haml +2 -0
- data/app/views/stall/checkout/steps/_navigation.html.haml +13 -0
- data/app/views/stall/credit_note_adjustments/_form.html.haml +28 -0
- data/app/views/stall/line_items/_added.html.haml +2 -2
- data/app/views/stall/line_items/_form.html.haml +1 -1
- data/app/views/stall/payments/manual_payment_gateway/_form.html.haml +10 -0
- data/app/views/stall/shared/mailers/_cart.html.haml +1 -1
- data/config/locales/stall.fr.yml +82 -2
- data/db/migrate/20161129101956_add_type_to_stall_address_ownerships.rb +52 -0
- data/db/migrate/20161202080218_add_reference_to_product_lists.rb +17 -0
- data/db/migrate/20170118103916_create_credit_notes.rb +17 -0
- data/db/migrate/20170118144047_create_credit_note_adjustments.rb +13 -0
- data/db/migrate/20170123123115_create_stall_product_categories.rb +12 -0
- data/db/migrate/20170123123326_create_stall_products.rb +17 -0
- data/db/migrate/20170123125030_create_stall_variants.rb +13 -0
- data/db/migrate/20170123131748_create_stall_product_category_hierarchies.rb +16 -0
- data/db/migrate/20170123143704_create_stall_product_details.rb +14 -0
- data/db/migrate/20170125152622_convert_all_money_fields_to_decimal_to_use_infinite_precision.rb +27 -0
- data/db/migrate/20170131162537_add_data_to_stall_adjustments.rb +5 -0
- data/db/migrate/20170202165514_create_stall_properties.rb +9 -0
- data/db/migrate/20170202165516_create_stall_property_values.rb +13 -0
- data/db/migrate/20170202165518_create_stall_variant_property_values.rb +13 -0
- data/lib/generators/stall/install/templates/initializer.rb +21 -0
- data/lib/generators/stall/view/view_generator.rb +41 -19
- data/lib/para/stall.rb +32 -0
- data/lib/para/stall/inputs.rb +13 -0
- data/lib/para/stall/inputs/variant_input_helper.rb +34 -0
- data/lib/para/stall/inputs/variant_select_input.rb +79 -0
- data/lib/para/stall/inputs/variants_matrix_input.rb +72 -0
- data/lib/para/stall/routes.rb +11 -0
- data/lib/para/stall/variants_property_config.rb +78 -0
- data/lib/stall.rb +10 -0
- data/lib/stall/addressable.rb +11 -59
- data/lib/stall/addresses.rb +1 -0
- data/lib/stall/addresses/copier_base.rb +3 -1
- data/lib/stall/addresses/copy.rb +10 -0
- data/lib/stall/addresses/copy_source_to_target.rb +10 -24
- data/lib/stall/addresses/prefill_target_from_source.rb +8 -16
- data/lib/stall/adjustable.rb +20 -0
- data/lib/stall/archived_paid_cart_helper.rb +36 -0
- data/lib/stall/cart_helper.rb +15 -7
- data/lib/stall/checkout/informations_checkout_step.rb +47 -50
- data/lib/stall/checkout/payment_return_checkout_step.rb +4 -1
- data/lib/stall/checkout/step.rb +24 -3
- data/lib/stall/checkout/step_form.rb +11 -5
- data/lib/stall/checkout/wizard.rb +7 -6
- data/lib/stall/config.rb +9 -0
- data/lib/stall/default_currency_manager.rb +27 -0
- data/lib/stall/engine.rb +14 -3
- data/lib/stall/payments.rb +2 -0
- data/lib/stall/payments/gateway_request.rb +15 -0
- data/lib/stall/payments/gateway_response.rb +33 -0
- data/lib/stall/payments/manual_payment_gateway.rb +86 -0
- data/lib/stall/priceable.rb +4 -0
- data/lib/stall/reference_manager.rb +17 -0
- data/lib/stall/routes.rb +1 -0
- data/lib/stall/shippable.rb +18 -0
- data/lib/stall/total_prices_manager.rb +40 -0
- data/lib/stall/version.rb +1 -1
- metadata +120 -5
- data/app/models/address_ownership.rb +0 -3
- data/app/models/stall/models/address_ownership.rb +0 -26
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Stall
|
|
2
|
+
module Adjustable
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
has_many :adjustments, dependent: :destroy, inverse_of: :cart
|
|
7
|
+
accepts_nested_attributes_for :adjustments
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def items
|
|
13
|
+
super.tap do |items|
|
|
14
|
+
adjustments.each do |adjustment|
|
|
15
|
+
items << adjustment
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
module Stall
|
|
2
|
+
module ArchivedPaidCartHelper
|
|
3
|
+
def archived_paid_cart
|
|
4
|
+
RequestStore.store[archived_paid_cart_key] ||= load_archived_paid_cart
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def archived_paid_cart?
|
|
8
|
+
!!archived_paid_cart
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def archive_paid_cart_cookie(identifier)
|
|
12
|
+
cookies.delete(cart_key(identifier))
|
|
13
|
+
store_cart_cookie_for(current_cart.identifier, current_cart, namespace: :paid)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def archivable_cart?(cart)
|
|
17
|
+
!cart.active? && cart.token != archived_paid_cart_token
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def load_archived_paid_cart
|
|
23
|
+
if (cart_token = archived_paid_cart_token)
|
|
24
|
+
ProductList.find_by_token(archived_paid_cart_token)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def archived_paid_cart_key
|
|
29
|
+
cart_key(current_cart_key, namespace: :paid)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def archived_paid_cart_token
|
|
33
|
+
cookies.encrypted[archived_paid_cart_key]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/stall/cart_helper.rb
CHANGED
|
@@ -46,11 +46,19 @@ module Stall
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def prepare_cart(cart)
|
|
49
|
-
cart.tap do
|
|
49
|
+
cart.tap do
|
|
50
50
|
cart.customer = current_customer if current_customer
|
|
51
51
|
# Keep track of potential customer locale switching to allow e-mailing
|
|
52
52
|
# him in his last used locale
|
|
53
|
-
|
|
53
|
+
#
|
|
54
|
+
# Only applicable if the locale is an available locale to avoid strange
|
|
55
|
+
# issues with some URL locale management systems that could set the
|
|
56
|
+
# `assets` prefix as a locale, for instance.
|
|
57
|
+
if cart.customer && I18n.locale.in?(I18n.available_locales)
|
|
58
|
+
cart.customer.locale = I18n.locale
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
Stall.config.service_for(:product_list_staleness_handling).new(cart).call
|
|
54
62
|
|
|
55
63
|
# Only update locale change for existing carts. New carts don't need
|
|
56
64
|
# to be saved, avoiding each robot or simple visitors to create a
|
|
@@ -78,8 +86,8 @@ module Stall
|
|
|
78
86
|
cookies.delete(cart_key(identifier))
|
|
79
87
|
end
|
|
80
88
|
|
|
81
|
-
def cart_key(identifier = current_cart_key)
|
|
82
|
-
['stall', 'cart', identifier.to_s].join('.')
|
|
89
|
+
def cart_key(identifier = current_cart_key, namespace: nil)
|
|
90
|
+
['stall', 'cart', namespace, identifier.to_s].compact.join('.')
|
|
83
91
|
end
|
|
84
92
|
|
|
85
93
|
def cart_class
|
|
@@ -87,13 +95,13 @@ module Stall
|
|
|
87
95
|
end
|
|
88
96
|
|
|
89
97
|
def store_cart_to_cookies
|
|
90
|
-
if current_cart.persisted?
|
|
98
|
+
if current_cart.persisted? && current_cart.active?
|
|
91
99
|
store_cart_cookie_for(current_cart.identifier, current_cart)
|
|
92
100
|
end
|
|
93
101
|
end
|
|
94
102
|
|
|
95
|
-
def store_cart_cookie_for(identifier, cart)
|
|
96
|
-
cookies.encrypted.permanent[cart_key(identifier)] = cart.token
|
|
103
|
+
def store_cart_cookie_for(identifier, cart, namespace: nil)
|
|
104
|
+
cookies.encrypted.permanent[cart_key(identifier, namespace: namespace)] = cart.token
|
|
97
105
|
end
|
|
98
106
|
end
|
|
99
107
|
end
|
|
@@ -28,10 +28,10 @@ module Stall
|
|
|
28
28
|
|
|
29
29
|
def process
|
|
30
30
|
prepare_user_attributes
|
|
31
|
+
prepare_addresses_attributes
|
|
31
32
|
cart.assign_attributes(cart_params)
|
|
32
|
-
process_addresses
|
|
33
33
|
|
|
34
|
-
return unless valid?
|
|
34
|
+
return false unless valid?
|
|
35
35
|
|
|
36
36
|
cart.save.tap do |valid|
|
|
37
37
|
assign_addresses_to_customer!
|
|
@@ -41,22 +41,45 @@ module Stall
|
|
|
41
41
|
|
|
42
42
|
private
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
# To easily add permitted parameters, use the following method in your
|
|
45
|
+
# subclass :
|
|
46
|
+
#
|
|
47
|
+
# def cart_params
|
|
48
|
+
# super(customer_attributes: [nested: :attribute])
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# Note : If you want to remove permitted parameters, you need to rewrite
|
|
52
|
+
# the full permissions nested array
|
|
53
|
+
#
|
|
54
|
+
def cart_params(*attributes)
|
|
45
55
|
@cart_params ||= params.require(:cart).permit(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
*merge_arrays(
|
|
57
|
+
[
|
|
58
|
+
:use_another_address_for_billing, :terms,
|
|
59
|
+
:payment_method_id, :shipping_method_id,
|
|
60
|
+
customer_attributes: [
|
|
61
|
+
:id, :email, user_attributes: [
|
|
62
|
+
:password, :password_confirmation
|
|
63
|
+
]
|
|
64
|
+
],
|
|
65
|
+
shipping_address_attributes: [
|
|
66
|
+
:id, :civility, :first_name, :last_name, :address,
|
|
67
|
+
:address_details, :country, :zip, :city, :phone, :state
|
|
68
|
+
],
|
|
69
|
+
billing_address_attributes: [
|
|
70
|
+
:id, :civility, :first_name, :last_name, :address,
|
|
71
|
+
:address_details, :country, :zip, :city, :phone, :state,
|
|
72
|
+
:_destroy
|
|
73
|
+
],
|
|
74
|
+
shipment_attributes: [
|
|
75
|
+
:id, :shipping_method_id
|
|
76
|
+
],
|
|
77
|
+
payment_attributes: [
|
|
78
|
+
:id, :payment_method_id
|
|
79
|
+
]
|
|
80
|
+
],
|
|
81
|
+
attributes
|
|
82
|
+
)
|
|
60
83
|
)
|
|
61
84
|
end
|
|
62
85
|
|
|
@@ -64,23 +87,6 @@ module Stall
|
|
|
64
87
|
cart.build_customer unless cart.customer
|
|
65
88
|
end
|
|
66
89
|
|
|
67
|
-
def ensure_address(type)
|
|
68
|
-
ownership = cart.address_ownership_for(type) || cart.address_ownerships.build(type => true)
|
|
69
|
-
ownership.address || ownership.build_address
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def ensure_billing_address
|
|
73
|
-
return ensure_address(:billing) unless cart_params[:use_another_address_for_billing] == '0'
|
|
74
|
-
|
|
75
|
-
# If the form was submitted and we merged both shipping and billing
|
|
76
|
-
# addresses together, we must separate them back to present them to
|
|
77
|
-
# the user form, avoiding to render errors in a form that the user
|
|
78
|
-
# didn't even see before
|
|
79
|
-
ownership = cart.address_ownership_for(:billing)
|
|
80
|
-
ownership.billing = false if ownership.shipping
|
|
81
|
-
ensure_address(:billing)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
90
|
def ensure_shipment
|
|
85
91
|
cart.build_shipment unless cart.shipment
|
|
86
92
|
end
|
|
@@ -108,23 +114,14 @@ module Stall
|
|
|
108
114
|
end
|
|
109
115
|
end
|
|
110
116
|
|
|
111
|
-
#
|
|
112
|
-
#
|
|
117
|
+
# If the billing address should be set to the same as the filled shipping
|
|
118
|
+
# address, we remove the billing address parameters
|
|
113
119
|
#
|
|
114
|
-
def
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return if billing_ownership == shipping_ownership
|
|
121
|
-
|
|
122
|
-
# If the user choosed to receive his order by shipping and that he
|
|
123
|
-
# choosed not to fill a billing address, we remove the billing address
|
|
124
|
-
# hidden form that was submitted in the step, and make the shipping
|
|
125
|
-
# address be used as billing address too
|
|
126
|
-
cart.address_ownerships.destroy(billing_ownership) if billing_ownership
|
|
127
|
-
cart.mark_address_ownership_as_billing(shipping_ownership) if shipping_ownership
|
|
120
|
+
def prepare_addresses_attributes
|
|
121
|
+
unless use_another_address_for_billing?
|
|
122
|
+
cart_params.delete(:billing_address_attributes)
|
|
123
|
+
cart.billing_address.try(:mark_for_destruction)
|
|
124
|
+
end
|
|
128
125
|
end
|
|
129
126
|
|
|
130
127
|
# Assigns the shipping fees to the cart based on the selected shipping
|
|
@@ -2,9 +2,12 @@ module Stall
|
|
|
2
2
|
module Checkout
|
|
3
3
|
class PaymentReturnCheckoutStep < Stall::Checkout::Step
|
|
4
4
|
include Stall::CartHelper
|
|
5
|
+
include Stall::ArchivedPaidCartHelper
|
|
5
6
|
|
|
6
7
|
def prepare
|
|
7
|
-
|
|
8
|
+
if archivable_cart?(cart)
|
|
9
|
+
archive_paid_cart_cookie(cart.identifier)
|
|
10
|
+
end
|
|
8
11
|
end
|
|
9
12
|
|
|
10
13
|
# When we access this step, the cart is "inactive", since it is paid, so
|
data/lib/stall/checkout/step.rb
CHANGED
|
@@ -33,8 +33,9 @@ module Stall
|
|
|
33
33
|
false
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
def is?(
|
|
37
|
-
identifier
|
|
36
|
+
def is?(other)
|
|
37
|
+
step_identifier = (Step === other ? other.identifier : other.to_sym)
|
|
38
|
+
identifier == step_identifier
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
def identifier
|
|
@@ -61,7 +62,7 @@ module Stall
|
|
|
61
62
|
#
|
|
62
63
|
def valid?
|
|
63
64
|
cart.validate
|
|
64
|
-
run_step_validations!(clear:
|
|
65
|
+
run_step_validations!(clear: false)
|
|
65
66
|
|
|
66
67
|
cart.errors.empty?
|
|
67
68
|
end
|
|
@@ -75,6 +76,26 @@ module Stall
|
|
|
75
76
|
|
|
76
77
|
private
|
|
77
78
|
|
|
79
|
+
def cart_params(*attributes)
|
|
80
|
+
@cart_params ||= if params.key?(:cart)
|
|
81
|
+
params.require(:cart).permit(attributes)
|
|
82
|
+
else
|
|
83
|
+
{}
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Allows overriding the nested array of permitted parameters to add other
|
|
88
|
+
# params at a given path. Rails default behavior doesn't allow merging
|
|
89
|
+
# nested arrays, neither top-level arrays.
|
|
90
|
+
#
|
|
91
|
+
# Note : We use the `deep_merge` gem for the nested arrays merging.
|
|
92
|
+
#
|
|
93
|
+
def merge_arrays(defaults, overrides)
|
|
94
|
+
defaults_hash = defaults.extract_options!
|
|
95
|
+
overrides_hash = overrides.extract_options!
|
|
96
|
+
(defaults + overrides) << defaults_hash.deeper_merge!(overrides_hash)
|
|
97
|
+
end
|
|
98
|
+
|
|
78
99
|
def run_step_validations!(clear: true)
|
|
79
100
|
if (validations = self.class.validations)
|
|
80
101
|
validations.new(cart, self, clear: clear).validate
|
|
@@ -5,14 +5,14 @@ module Stall
|
|
|
5
5
|
|
|
6
6
|
class_attribute :nested_forms
|
|
7
7
|
|
|
8
|
-
attr_reader :object, :step, :
|
|
8
|
+
attr_reader :object, :step, :clear_cart_errors
|
|
9
9
|
|
|
10
10
|
delegate :errors, to: :object
|
|
11
11
|
|
|
12
12
|
def initialize(object, step, clear: true)
|
|
13
13
|
@object = object
|
|
14
14
|
@step = step
|
|
15
|
-
@
|
|
15
|
+
@clear_cart_errors = clear
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# Runs form and nested forms validations and returns wether they all
|
|
@@ -23,7 +23,7 @@ module Stall
|
|
|
23
23
|
# form constructor, aggregating both validation sources' errors
|
|
24
24
|
#
|
|
25
25
|
def validate
|
|
26
|
-
errors.clear if
|
|
26
|
+
errors.clear if clear_cart_errors
|
|
27
27
|
run_validations!
|
|
28
28
|
validate_nested_forms
|
|
29
29
|
!errors.any?
|
|
@@ -72,8 +72,14 @@ module Stall
|
|
|
72
72
|
|
|
73
73
|
# Run all validations on all nested forms and ensure they're all valid
|
|
74
74
|
nested_forms.map do |name, form|
|
|
75
|
-
if object.respond_to?(name) && (resource = object.send(name))
|
|
76
|
-
|
|
75
|
+
if object.respond_to?(name) && (resource = object.send(name)) &&
|
|
76
|
+
!(resource.respond_to?(:marked_for_destruction?) && resource.marked_for_destruction?)
|
|
77
|
+
then
|
|
78
|
+
valid = Array.wrap(resource).map { |m| form.new(m, step, clear: @clear_cart_errors).validate }.all?
|
|
79
|
+
# Bubble up nested errors
|
|
80
|
+
errors.add(name, :invalid) unless valid
|
|
81
|
+
|
|
82
|
+
valid
|
|
77
83
|
else
|
|
78
84
|
# Nested validations shouldn't be run on undefined relations
|
|
79
85
|
true
|
|
@@ -57,8 +57,13 @@ module Stall
|
|
|
57
57
|
step_index && step_index >= steps_count - 1
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
def
|
|
61
|
-
steps
|
|
60
|
+
def steps
|
|
61
|
+
@steps ||= self.class.steps
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def step_complete?(step)
|
|
65
|
+
step_identifier = (Step === step ? step.identifier : step.to_sym)
|
|
66
|
+
steps.index(cart.state) > steps.index(step_identifier)
|
|
62
67
|
end
|
|
63
68
|
|
|
64
69
|
def steps_count
|
|
@@ -87,10 +92,6 @@ module Stall
|
|
|
87
92
|
|
|
88
93
|
private
|
|
89
94
|
|
|
90
|
-
def steps
|
|
91
|
-
@steps ||= self.class.steps
|
|
92
|
-
end
|
|
93
|
-
|
|
94
95
|
def step_name_for(index)
|
|
95
96
|
steps[index]
|
|
96
97
|
end
|
data/lib/stall/config.rb
CHANGED
|
@@ -57,6 +57,8 @@ module Stall
|
|
|
57
57
|
# Configure the terms of service page path
|
|
58
58
|
param :terms_path, 'about:blank'
|
|
59
59
|
|
|
60
|
+
param :convert_cart_remainder_to_credit_note, false
|
|
61
|
+
|
|
60
62
|
def shipping
|
|
61
63
|
@shipping ||= Stall::Shipping::Config.new
|
|
62
64
|
end
|
|
@@ -99,5 +101,12 @@ module Stall
|
|
|
99
101
|
def default_user_model
|
|
100
102
|
default_user_model_name.try(:constantize)
|
|
101
103
|
end
|
|
104
|
+
|
|
105
|
+
def default_currency_as_money
|
|
106
|
+
raw_default_currency && Money::Currency.new(raw_default_currency)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
alias_method :raw_default_currency, :default_currency
|
|
110
|
+
alias_method :default_currency, :default_currency_as_money
|
|
102
111
|
end
|
|
103
112
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Stall
|
|
2
|
+
module DefaultCurrencyManager
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
after_initialize :ensure_currency
|
|
7
|
+
|
|
8
|
+
scope :for_currency, ->(currency) {
|
|
9
|
+
where(table_name => { currency: currency.to_s })
|
|
10
|
+
}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def currency
|
|
14
|
+
if (currency = read_attribute(:currency).presence)
|
|
15
|
+
Money::Currency.new(currency)
|
|
16
|
+
else
|
|
17
|
+
self.currency = Stall.config.default_currency
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def ensure_currency
|
|
24
|
+
self.currency ||= Stall.config.default_currency
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/stall/engine.rb
CHANGED
|
@@ -4,10 +4,12 @@ module Stall
|
|
|
4
4
|
Money.default_currency = Stall.config.default_currency
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
+
initializer 'stall.set_money_gem_infinite_precision' do
|
|
8
|
+
Money.infinite_precision = true
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
initializer 'stall.add_routing_mapper_extension' do
|
|
8
|
-
|
|
9
|
-
ActionDispatch::Routing::Mapper.send(:include, Stall::RoutingMapper)
|
|
10
|
-
end
|
|
12
|
+
ActionDispatch::Routing::Mapper.send(:include, Stall::RoutingMapper)
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
initializer 'stall.override_actionview_number_helpers' do
|
|
@@ -19,6 +21,7 @@ module Stall
|
|
|
19
21
|
initializer 'stall.include_cart_helper' do
|
|
20
22
|
ActiveSupport.on_load(:action_controller) do
|
|
21
23
|
include Stall::CartHelper
|
|
24
|
+
include Stall::ArchivedPaidCartHelper
|
|
22
25
|
end
|
|
23
26
|
end
|
|
24
27
|
|
|
@@ -30,6 +33,10 @@ module Stall
|
|
|
30
33
|
end
|
|
31
34
|
end
|
|
32
35
|
|
|
36
|
+
initializer 'stall.require_manual_payment_gateway' do
|
|
37
|
+
require 'stall/payments/manual_payment_gateway'
|
|
38
|
+
end
|
|
39
|
+
|
|
33
40
|
initializer 'stall.ensure_payment_method_for_all_gateways' do
|
|
34
41
|
Stall::Payments.gateways.each_key do |name|
|
|
35
42
|
PaymentMethod.where(identifier: name).first_or_create do |method|
|
|
@@ -38,6 +45,10 @@ module Stall
|
|
|
38
45
|
end
|
|
39
46
|
end
|
|
40
47
|
|
|
48
|
+
initializer 'stall.add_stall_plugin_to_para_config' do
|
|
49
|
+
Para.config.plugins += [:stall]
|
|
50
|
+
end
|
|
51
|
+
|
|
41
52
|
# Development : Configure rails generators to only generate the target
|
|
42
53
|
# files and not try to generate useless complementary files
|
|
43
54
|
#
|