stall 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +41 -3
- data/app/assets/javascripts/stall/add-to-cart-form.coffee +55 -3
- data/app/assets/javascripts/stall/addresses-fields.coffee +17 -0
- data/app/assets/javascripts/stall/remote-sign-in-form.coffee +55 -0
- data/app/assets/javascripts/stall.coffee +3 -1
- data/app/controllers/stall/application_controller.rb +1 -1
- data/app/controllers/stall/carts_controller.rb +1 -3
- data/app/controllers/stall/checkout/steps_controller.rb +18 -1
- data/app/helpers/stall/checkout_helper.rb +7 -8
- data/app/helpers/stall/customers_helper.rb +25 -0
- data/app/models/stall/models/cart.rb +2 -0
- data/app/models/stall/models/customer.rb +20 -0
- data/app/models/stall/models/product_list.rb +13 -0
- data/app/views/checkout/steps/_informations.html.haml +24 -35
- data/app/views/checkout/steps/_payment.html.haml +1 -45
- data/app/views/checkout/steps/_shipping_method.html.haml +0 -1
- data/app/views/stall/addresses/_fields.html.haml +16 -0
- data/app/views/stall/addresses/_nested_fields.html.haml +14 -0
- data/app/views/stall/carts/_cart.html.haml +45 -0
- data/app/views/stall/carts/show.html.haml +2 -2
- data/app/views/stall/customers/_fields.html.haml +32 -0
- data/app/views/stall/customers/_sign_in.html.haml +20 -0
- data/app/views/stall/line_items/_form.html.haml +2 -2
- data/app/views/stall/payments/_fields.html.haml +2 -0
- data/app/views/stall/shared/mailers/_cart.html.haml +31 -29
- data/app/views/stall/shipments/_fields.html.haml +2 -0
- data/config/locales/stall.fr.yml +35 -8
- data/lib/generators/stall/checkout/step/templates/step.rb.erb +9 -0
- data/lib/generators/stall/checkout/wizard/templates/wizard.rb.erb +1 -1
- data/lib/generators/stall/install/install_generator.rb +6 -0
- data/lib/generators/stall/install/templates/initializer.rb +10 -1
- data/lib/generators/stall/view/view_generator.rb +38 -0
- data/lib/stall/addressable.rb +2 -0
- data/lib/stall/addresses/copier_base.rb +24 -0
- data/lib/stall/addresses/copy_source_to_target.rb +45 -0
- data/lib/stall/addresses/prefill_target_from_source.rb +29 -0
- data/lib/stall/addresses.rb +9 -0
- data/lib/stall/cart_helper.rb +14 -1
- data/lib/stall/checkout/informations_checkout_step.rb +133 -14
- data/lib/stall/checkout/payment_checkout_step.rb +21 -1
- data/lib/stall/checkout/step.rb +22 -15
- data/lib/stall/checkout/step_form.rb +22 -8
- data/lib/stall/config.rb +17 -3
- data/lib/stall/engine.rb +6 -0
- data/lib/stall/payable.rb +9 -0
- data/lib/stall/payments/gateway.rb +16 -6
- data/lib/stall/payments/urls_config.rb +2 -2
- data/lib/stall/rails/routing_mapper.rb +4 -6
- data/lib/stall/routes.rb +4 -1
- data/lib/stall/sellable.rb +13 -3
- data/lib/stall/version.rb +1 -1
- data/lib/stall.rb +1 -0
- metadata +25 -6
- data/lib/stall/checkout/payment_method_checkout_step.rb +0 -9
- data/lib/stall/checkout/shipping_method_checkout_step.rb +0 -21
@@ -0,0 +1,32 @@
|
|
1
|
+
-# When stall a user is signed in, a customer autoatically exist and is assigned
|
2
|
+
-# to the cart, by default, we notify the visitor that he's signed in and will
|
3
|
+
-# order with that account, making customer and user related fields unnecessary
|
4
|
+
- if stall_user_signed_in?
|
5
|
+
.alert.alert-info
|
6
|
+
%i.fa.fa-info-circle
|
7
|
+
= t('stall.checkout.informations.signed_in_as', email: current_stall_user.email)
|
8
|
+
|
9
|
+
- else
|
10
|
+
-# The `#with_errors_from_user` helper ensures that user e-mail errors, like
|
11
|
+
-# format or uniqueness, are actually bubbled up to the customer e-mail field.
|
12
|
+
= form.fields_for :customer, with_errors_from_user(form.object.customer) do |customer_form|
|
13
|
+
= customer_form.input :email
|
14
|
+
|
15
|
+
= form.fields_for :customer do |customer_form|
|
16
|
+
= customer_form.fields_for :user, customer_form.object.user_or_default do |user_form|
|
17
|
+
%fieldset.collapse{ class: ('in' if params[:create_account] == '1'), data: { :'user-fields' => true } }
|
18
|
+
= user_form.input :password
|
19
|
+
= user_form.input :password_confirmation
|
20
|
+
|
21
|
+
%p.help-block
|
22
|
+
%label
|
23
|
+
-# This field allows the step to determine wether an account should be
|
24
|
+
-# created or not while creating the customer, allowing it to clean
|
25
|
+
-# user related fields if it's not needed.
|
26
|
+
-#
|
27
|
+
-# The `autocomplete="off"` clears the Firefox cache that autofills the
|
28
|
+
-# checked attribute and breaks the unerlying basic bootstrap collapse
|
29
|
+
-# behavior
|
30
|
+
= check_box_tag :create_account, '1', (params[:create_account] == '1'), class: 'collapsed', autocomplete: 'off', data: { target: '[data-user-fields]', toggle: 'collapse' }
|
31
|
+
= t('stall.checkout.informations.create_an_account')
|
32
|
+
%hr
|
@@ -0,0 +1,20 @@
|
|
1
|
+
.panel.panel-info
|
2
|
+
.panel-heading
|
3
|
+
%i.fa.fa-user
|
4
|
+
= t('stall.checkout.sign_in.already_have_an_account')
|
5
|
+
= link_to '#sign-in-form', data: { toggle: 'collapse' } do
|
6
|
+
= t('stall.checkout.sign_in.click_to_sign_in')
|
7
|
+
|
8
|
+
#sign-in-form.panel-body.collapse{ data: { :'sign-in-form' => true } }
|
9
|
+
%p.help-block
|
10
|
+
= t('stall.checkout.sign_in.sign_in_instructions', label: t('stall.checkout.sign_in.button_label'))
|
11
|
+
|
12
|
+
= simple_form_for resource, as: resource_name, url: session_path(resource_name), remote: true, html: { data: { :'stall-remote-sign-in-form' => true } } do |form|
|
13
|
+
.row
|
14
|
+
.col-md-6
|
15
|
+
= form.input :email
|
16
|
+
.col-md-6
|
17
|
+
= form.input :password
|
18
|
+
|
19
|
+
%button.btn.btn-primary{ type: 'submit', autocomplete: 'off', data: { :'sign-in-submit-btn' => true, :'loading-text' => t('stall.shared.sending') } }
|
20
|
+
= t('stall.checkout.sign_in.button_label')
|
@@ -1,4 +1,4 @@
|
|
1
|
-
= simple_form_for line_item, as: :line_item, url: cart_line_items_path(cart), remote: true, data: { :'add-to-cart-form' => true } do |form|
|
1
|
+
= simple_form_for line_item, as: :line_item, url: cart_line_items_path(cart), remote: true, data: { :'add-to-cart-form' => true, :'error-messages' => { choose: t('stall.line_items.errors.choose'), quantity: t('stall.line_items.errors.quantity') } } do |form|
|
2
2
|
= form.hidden_field :sellable_type
|
3
3
|
= form.hidden_field :sellable_id
|
4
4
|
|
@@ -6,7 +6,7 @@
|
|
6
6
|
= form.input_field :quantity, spinner: false, value: 1, class: 'form-group', data: { :'quantity-field' => true }
|
7
7
|
|
8
8
|
%span.input-group-btn
|
9
|
-
%button.btn.btn-primary{ type: 'submit',
|
9
|
+
%button.btn.btn-primary{ type: 'submit', data: { :'loading-text' => t('stall.shared.sending') } }
|
10
10
|
%i.fa.fa-shopping-cart
|
11
11
|
= t('stall.line_items.form.add_to_cart')
|
12
12
|
|
@@ -78,37 +78,39 @@
|
|
78
78
|
%td
|
79
79
|
%table
|
80
80
|
%tbody
|
81
|
-
|
82
|
-
%
|
83
|
-
%
|
81
|
+
- if cart.payment && cart.payment.payment_method
|
82
|
+
%tr
|
83
|
+
%td{ colspan: 2 }
|
84
|
+
%strong= Cart.human_attribute_name(:payment)
|
84
85
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
86
|
+
%tr
|
87
|
+
%td
|
88
|
+
= Payment.human_attribute_name(:payment_method)
|
89
|
+
%td
|
90
|
+
= cart.payment.payment_method.name
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
92
|
+
%tr
|
93
|
+
%td
|
94
|
+
= Payment.human_attribute_name(:state)
|
95
|
+
%td
|
96
|
+
- if cart.payment.paid?
|
97
|
+
= t("stall.carts.recap.paid_at", at: cart.payment.paid_at)
|
98
|
+
- else
|
99
|
+
= t("activerecord.enums.payment.state.#{ cart.payment.state }")
|
99
100
|
|
100
|
-
|
101
|
-
%
|
102
|
-
%
|
101
|
+
- if cart.shipment && cart.shipment.shipping_method
|
102
|
+
%tr
|
103
|
+
%td{ colspan: 2 }
|
104
|
+
%strong= Cart.human_attribute_name(:shipment)
|
103
105
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
%tr
|
107
|
+
%td
|
108
|
+
= Shipment.human_attribute_name(:shipping_method)
|
109
|
+
%td
|
110
|
+
= cart.shipment.shipping_method.name
|
109
111
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
112
|
+
%tr
|
113
|
+
%td
|
114
|
+
= Shipment.human_attribute_name(:state)
|
115
|
+
%td
|
116
|
+
= t("activerecord.enums.payment.state.#{ cart.shipment.state }")
|
data/config/locales/stall.fr.yml
CHANGED
@@ -2,14 +2,17 @@ fr:
|
|
2
2
|
stall:
|
3
3
|
shared:
|
4
4
|
close: "Fermer"
|
5
|
+
sending: "Envoi en cours ..."
|
5
6
|
|
6
7
|
carts:
|
7
8
|
formats:
|
8
9
|
name: "Commande n°%{ref}"
|
10
|
+
|
9
11
|
flashes:
|
10
12
|
update:
|
11
13
|
success: "Votre panier a bien été mis à jour."
|
12
14
|
error: "Votre panier n'a pu être mis à jour, merci de vérifier les champs."
|
15
|
+
|
13
16
|
recap:
|
14
17
|
order_ref: "Commande n°%{ref}"
|
15
18
|
ordered_at: "Passée le %{at}"
|
@@ -32,20 +35,28 @@ fr:
|
|
32
35
|
add_error:
|
33
36
|
title: "Votre produit n'a pu être ajouté"
|
34
37
|
description: "Merci de vérifier que vous avez bien rempli la quantité avant d'ajouter le produit au panier."
|
38
|
+
errors:
|
39
|
+
choose: "Merci de choisir un produit afin de l'ajouter au panier"
|
40
|
+
quantity: "Merci de choisir une quantité à ajouter au panier"
|
35
41
|
|
36
42
|
checkout:
|
37
43
|
shared:
|
38
|
-
not_checkoutable: "
|
44
|
+
not_checkoutable: "Le panier a expiré, celui-ci a probablement déjà été payé."
|
39
45
|
informations:
|
40
46
|
title: "Vos informations"
|
41
|
-
validate: "Valider
|
47
|
+
validate: "Valider la commande et passer au paiement"
|
42
48
|
error: "Vos informations n'ont pu être enregistrées, merci de vérifier les champs"
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
signed_in_as: "Vous êtes actuellement connectés en tant que %{email}"
|
50
|
+
create_an_account: "Me créer un compte"
|
51
|
+
accept_the: "J'accepte les "
|
52
|
+
sign_in:
|
53
|
+
already_have_an_account: "J'ai déjà un compte :"
|
54
|
+
click_to_sign_in: "Cliquez-ici pour vous connecter"
|
55
|
+
sign_in_instructions: |
|
56
|
+
Renseigez dans les champs suivant vos identifiants de connexion puis
|
57
|
+
cliquez sur le bouton "%{label}"
|
58
|
+
button_label: "Me connecter"
|
59
|
+
|
49
60
|
payment:
|
50
61
|
title: "Paiement"
|
51
62
|
error: |
|
@@ -91,6 +102,7 @@ fr:
|
|
91
102
|
state:
|
92
103
|
pending: "En attente"
|
93
104
|
shipped: "Payé"
|
105
|
+
|
94
106
|
models:
|
95
107
|
line_item: "Produit"
|
96
108
|
customer: "Client"
|
@@ -98,6 +110,7 @@ fr:
|
|
98
110
|
cart: "Panier"
|
99
111
|
shipment: "Livraison"
|
100
112
|
payment: "Paiement"
|
113
|
+
|
101
114
|
attributes:
|
102
115
|
line_item:
|
103
116
|
sellable: "Produit source"
|
@@ -129,6 +142,7 @@ fr:
|
|
129
142
|
customer: "Client"
|
130
143
|
created_at: "Date"
|
131
144
|
line_items: "Produits"
|
145
|
+
use_another_address_for_billing: "Utiliser une autre adresse pour la facturation"
|
132
146
|
cart:
|
133
147
|
state: "Étape du panier"
|
134
148
|
total_price: "Montant total"
|
@@ -136,6 +150,7 @@ fr:
|
|
136
150
|
shipment: "Livraison"
|
137
151
|
shipping_address: "Adresse de livraison"
|
138
152
|
billing_address: "Adresse de facturation"
|
153
|
+
terms: "Conditions générales de vente"
|
139
154
|
shipment:
|
140
155
|
price: "Prix"
|
141
156
|
eot_price: "Prix HT"
|
@@ -149,3 +164,15 @@ fr:
|
|
149
164
|
paid_at: "Payé le"
|
150
165
|
transaction_id: "Numéro de transaction"
|
151
166
|
state: "État"
|
167
|
+
|
168
|
+
simple_form:
|
169
|
+
placeholders:
|
170
|
+
address:
|
171
|
+
first_name: "Votre prénom"
|
172
|
+
last_name: "Votre nom"
|
173
|
+
address: "Numéro et rue"
|
174
|
+
address_details: "Autres informations : bâtiment, escalier, interphone etc."
|
175
|
+
country: "Votre pays"
|
176
|
+
zip: "Votre code postal"
|
177
|
+
city: "Votre ville"
|
178
|
+
phone: "Votre numéro de téléphone (portable / fixe)"
|
@@ -24,4 +24,13 @@ class <%= class_name %> < Stall::Checkout::Step
|
|
24
24
|
# def skip?
|
25
25
|
# false
|
26
26
|
# end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Process `params` here, defaults to assigning the cart with `cart_params`
|
31
|
+
# (params[:cart]) to the cart, running the step validations
|
32
|
+
#
|
33
|
+
def cart_params
|
34
|
+
params.require(:cart).permit({})
|
35
|
+
end
|
27
36
|
end
|
@@ -13,5 +13,11 @@ module Stall
|
|
13
13
|
def copy_default_checkout_wizard
|
14
14
|
generate 'stall:checkout:wizard', 'default'
|
15
15
|
end
|
16
|
+
|
17
|
+
def mount_engine_in_routes
|
18
|
+
say "Mounting Stall engine in routes"
|
19
|
+
gsub_file 'config/routes.rb', /mount_stall.+\n/, ''
|
20
|
+
route "mount_stall '/'"
|
21
|
+
end
|
16
22
|
end
|
17
23
|
end
|
@@ -56,7 +56,7 @@ Stall.configure do |config|
|
|
56
56
|
# that you create your line items, carts and orders with the right currency
|
57
57
|
# set.
|
58
58
|
#
|
59
|
-
#
|
59
|
+
# config.default_currency = 'EUR'
|
60
60
|
|
61
61
|
# Default app domain use for building URLs in payment gateway forms and in
|
62
62
|
# e-mails.
|
@@ -75,6 +75,15 @@ Stall.configure do |config|
|
|
75
75
|
# A default one is generated on stall's installation and can be found in your
|
76
76
|
# app at : lib/default_checkout_wizard.rb
|
77
77
|
#
|
78
|
+
# Note :
|
79
|
+
#
|
80
|
+
# If you do not autoload files in your app's lib folder, please require your
|
81
|
+
# checkout wizard with the following command here
|
82
|
+
#
|
83
|
+
# require 'default_checkout_wizard'
|
84
|
+
#
|
85
|
+
#
|
86
|
+
#
|
78
87
|
# config.default_checkout_wizard = 'DefaultCheckoutWizard'
|
79
88
|
|
80
89
|
# Default line items weight when added to cart and no weight is found on
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Stall
|
2
|
+
class ViewGenerator < ::Rails::Generators::Base
|
3
|
+
class ViewNotFound < StandardError; end
|
4
|
+
|
5
|
+
VIEWS_DIR = File.expand_path('../../../../../app/views', __FILE__)
|
6
|
+
source_root VIEWS_DIR
|
7
|
+
|
8
|
+
argument :file_paths, type: :array, required: true
|
9
|
+
|
10
|
+
def copy_view_template
|
11
|
+
paths = file_paths.map do |file_path|
|
12
|
+
source_path = source_path_for(file_path)
|
13
|
+
raise ViewNotFound, "Could not find any stall view for #{ file_path }" unless File.exist?(source_path)
|
14
|
+
target_path = "app/views/#{ file_path_with_ext_for(file_path) }"
|
15
|
+
|
16
|
+
[source_path, target_path]
|
17
|
+
end
|
18
|
+
|
19
|
+
paths.each do |source_path, target_path|
|
20
|
+
template(source_path, target_path)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def source_path_for(file_path)
|
27
|
+
File.join(VIEWS_DIR, file_path_with_ext_for(file_path))
|
28
|
+
end
|
29
|
+
|
30
|
+
def file_path_with_ext_for(file_path)
|
31
|
+
if file_path.match(/\.html\.haml\z/)
|
32
|
+
file_path
|
33
|
+
else
|
34
|
+
"#{ file_path }.html.haml"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/stall/addressable.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Stall
|
2
|
+
module Addresses
|
3
|
+
class CopierBase
|
4
|
+
attr_reader :source, :target
|
5
|
+
|
6
|
+
def initialize(source, target)
|
7
|
+
@source = source
|
8
|
+
@target = target
|
9
|
+
end
|
10
|
+
|
11
|
+
def copy
|
12
|
+
fail NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def duplicate_attributes(model)
|
18
|
+
model.attributes.dup.tap do |attributes|
|
19
|
+
attributes.delete('id')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Allows copying
|
2
|
+
module Stall
|
3
|
+
module Addresses
|
4
|
+
class CopySourceToTarget < Stall::Addresses::CopierBase
|
5
|
+
def copy!
|
6
|
+
copy
|
7
|
+
target.save!
|
8
|
+
end
|
9
|
+
|
10
|
+
def copy
|
11
|
+
copy_shipping_address
|
12
|
+
copy_billing_address
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def copy_shipping_address
|
18
|
+
# Update or create target's shipping address with source's shipping
|
19
|
+
# address attributes
|
20
|
+
if target.shipping_address
|
21
|
+
target.shipping_address.assign_attributes(duplicate_attributes(source.shipping_address))
|
22
|
+
else
|
23
|
+
target.build_shipping_address(duplicate_attributes(source.shipping_address))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def copy_billing_address
|
28
|
+
# If the source uses the same address for shipping and billing, we
|
29
|
+
# reproduce this behavior ont the target
|
30
|
+
if source.shipping_address == source.billing_address
|
31
|
+
shipping_ownership = target.address_ownership_for(:shipping)
|
32
|
+
target.mark_address_ownership_as_billing(shipping_ownership)
|
33
|
+
# If the source has a separate billing address, we update or create the
|
34
|
+
# target's billing address with the source's one attributes
|
35
|
+
else
|
36
|
+
if target.billing_address
|
37
|
+
target.billing_address.assign_attributes(duplicate_attributes(source.billing_address))
|
38
|
+
else
|
39
|
+
target.build_billing_address(duplicate_attributes(source.billing_address))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Stall
|
2
|
+
module Addresses
|
3
|
+
class PrefillTargetFromSource < Stall::Addresses::CopierBase
|
4
|
+
def copy
|
5
|
+
prefill_shipping_address
|
6
|
+
prefill_billing_address
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def prefill_shipping_address
|
12
|
+
if source.shipping_address && !target.shipping_address
|
13
|
+
target.build_shipping_address(duplicate_attributes(source.shipping_address))
|
14
|
+
elsif !target.shipping_address
|
15
|
+
target.build_shipping_address
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def prefill_billing_address
|
20
|
+
if source.billing_address && !target.billing_address
|
21
|
+
target.build_billing_address(duplicate_attributes(source.billing_address))
|
22
|
+
elsif !target.billing_address || target.billing_address == target.shipping_address
|
23
|
+
target.address_ownership_for(:shipping).billing = false
|
24
|
+
target.build_billing_address
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/stall/cart_helper.rb
CHANGED
@@ -3,8 +3,10 @@ module Stall
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
+
include Stall::CustomersHelper
|
7
|
+
|
6
8
|
if respond_to?(:helper_method)
|
7
|
-
helper_method :current_cart, :current_cart_key
|
9
|
+
helper_method :current_cart, :current_cart_key, :current_customer
|
8
10
|
end
|
9
11
|
|
10
12
|
if respond_to?(:after_action)
|
@@ -16,6 +18,16 @@ module Stall
|
|
16
18
|
RequestStore.store[cart_key] ||= load_current_cart
|
17
19
|
end
|
18
20
|
|
21
|
+
def current_customer
|
22
|
+
@current_customer ||= if stall_user_signed_in?
|
23
|
+
if (customer = current_stall_user.customer)
|
24
|
+
customer
|
25
|
+
else
|
26
|
+
current_stall_user.create_customer(email: current_stall_user.email)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
19
31
|
protected
|
20
32
|
|
21
33
|
def current_cart_key
|
@@ -35,6 +47,7 @@ module Stall
|
|
35
47
|
|
36
48
|
def prepare_cart(cart)
|
37
49
|
cart.tap do |cart|
|
50
|
+
cart.customer = current_customer if current_customer
|
38
51
|
# Keep track of potential customer locale switching to allow e-mailing
|
39
52
|
# him in his last used locale
|
40
53
|
cart.customer.locale = I18n.locale if cart.customer
|