caboose-store 0.0.11 → 0.0.12

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.
Files changed (32) hide show
  1. checksums.yaml +8 -8
  2. data/app/assets/javascripts/caboose_store/application.js +0 -2
  3. data/app/assets/javascripts/caboose_store/checkout.js +143 -143
  4. data/app/assets/javascripts/caboose_store/modules/checkout.js +31 -32
  5. data/app/assets/javascripts/caboose_store/modules/checkout_step1.js +157 -0
  6. data/app/assets/javascripts/caboose_store/modules/checkout_step2.js +39 -0
  7. data/app/assets/javascripts/caboose_store/modules/checkout_step3.js +34 -0
  8. data/app/assets/javascripts/caboose_store/modules/checkout_step4.js +102 -0
  9. data/app/assets/templates/caboose_store/checkout/forms/guest.jst.ejs +1 -1
  10. data/app/assets/templates/caboose_store/checkout/forms/register.jst.ejs +1 -1
  11. data/app/assets/templates/caboose_store/checkout/forms/signin.jst.ejs +1 -1
  12. data/app/assets/templates/caboose_store/checkout/line_items.jst.ejs +1 -2
  13. data/app/assets/templates/caboose_store/checkout/login.jst.ejs +4 -4
  14. data/app/controllers/caboose_store/checkout_controller.rb +108 -46
  15. data/app/helpers/caboose_store/checkout_helper.rb +15 -0
  16. data/app/models/caboose_store/schema.rb +4 -0
  17. data/app/models/caboose_store/states.rb +66 -0
  18. data/app/views/caboose_store/cart/index.html.erb +4 -0
  19. data/app/views/caboose_store/checkout/_confirm.html.erb +61 -0
  20. data/app/views/caboose_store/checkout/index.html.erb +1 -1
  21. data/app/views/caboose_store/checkout/relay.html.erb +2 -2
  22. data/app/views/caboose_store/checkout/relay_old.html.erb +12 -0
  23. data/app/views/caboose_store/checkout/step_four.html.erb +91 -0
  24. data/app/views/caboose_store/checkout/step_one.html.erb +46 -11
  25. data/app/views/caboose_store/checkout/step_one_old.html.erb +13 -0
  26. data/app/views/caboose_store/checkout/step_three.html.erb +23 -0
  27. data/app/views/caboose_store/checkout/step_two.html.erb +49 -13
  28. data/app/views/caboose_store/checkout/step_two_old.html.erb +14 -0
  29. data/app/views/caboose_store/products/details.html.erb +2 -0
  30. data/config/routes.rb +10 -7
  31. data/lib/caboose-store/version.rb +1 -1
  32. metadata +13 -2
@@ -0,0 +1,157 @@
1
+ //
2
+ // Checkout
3
+ //
4
+
5
+ Caboose.Store.Modules.CheckoutStep1 = (function() {
6
+
7
+ // Steps
8
+ // Step 1: Present non-editable cart and login/register/guest buttons.
9
+ // Step 2: Present shipping address form.
10
+ // Step 3: Present shipping options.
11
+ // Step 4: Present credit card form.
12
+ // Step 5: Thank you.
13
+
14
+ self = {};
15
+
16
+ //
17
+ // Initialize
18
+ //
19
+
20
+ self.initialize = function() {
21
+ switch (window.location.pathname.replace(/\/$/, "")) {
22
+ case '/checkout':
23
+ case '/checkout/step-one': self.step = 1; break;
24
+ }
25
+
26
+ $('#signin_form_container' ).slideUp();
27
+ $('#register_form_container' ).slideUp();
28
+ $('#guest_form_container' ).slideUp();
29
+
30
+ self.$checkout = $('#checkout')
31
+ self.bindEventHandlers();
32
+ };
33
+
34
+ //
35
+ // Events
36
+ //
37
+
38
+ self.bindEventHandlers = function() {
39
+ self.$checkout.on('click' , '[data-login-action]', self.loginClickHandler);
40
+ self.$checkout.on('submit', '#checkout-login form', self.loginSubmitHandler);
41
+ self.$checkout.on('click' , '#checkout-continue button', self.continueHandler);
42
+
43
+ $('#signin_form' ).submit(self.login_form_submit_handler);
44
+ $('#register_form').submit(self.register_form_submit_handler);
45
+ $('#guest_form' ).submit(self.guest_form_submit_handler);
46
+ };
47
+
48
+ self.loginClickHandler = function(event) {
49
+ var form = $(event.target).data('login-action');
50
+ if (self.current_form && form == self.current_form)
51
+ return;
52
+ if (self.current_form)
53
+ {
54
+ $('#' + self.current_form + '_form_container').slideUp(400, function() {
55
+ $('#' + form + '_form_container').slideDown();
56
+ });
57
+ $('#' + self.current_form + '_button').removeClass('selected');
58
+ }
59
+ else
60
+ {
61
+ $('#' + form + '_form_container').slideDown();
62
+ }
63
+ $('#' + form + '_button').addClass('selected');
64
+ self.current_form = form;
65
+ };
66
+
67
+ self.loginSubmitHandler = function(event) {
68
+ event.preventDefault();
69
+ var $form = $(event.target);
70
+
71
+ $.ajax({
72
+ type: $form.attr('method'),
73
+ url: $form.attr('action'),
74
+ data: $form.serialize(),
75
+ success: function(response) {
76
+ if (response.error || (response.errors && response.errors.length > 0)) {
77
+ if ($form.find('.message').length) {
78
+ $form.find('.message').empty().addClass('error').text(response.error || response.errors[0]);
79
+ } else {
80
+ $form.append($('<span/>').addClass('message error').text(response.error || response.errors[0]));
81
+ }
82
+ } else {
83
+ if (response.logged_in) {
84
+ self.$login.after($('<p/>').addClass('alert').text('You are now signed in').css('text-align', 'center')).remove();
85
+ $.post('/checkout/attach-user');
86
+ } else {
87
+ self.$login.after($('<p/>').addClass('alert').text('Email successfully saved').css('text-align', 'center')).remove();
88
+ }
89
+ }
90
+
91
+ self.fetch(self.render);
92
+ }
93
+ });
94
+ };
95
+
96
+ self.continueHandler = function(event) {
97
+ $form = self.$address.find('form');
98
+
99
+ $.ajax({
100
+ type: $form.attr('method'),
101
+ url: $form.attr('action'),
102
+ data: $form.serialize(),
103
+ success: function(response) {
104
+ if (response.success) {
105
+ window.location = '/checkout/step-two';
106
+ } else {
107
+ $form.find('.message').remove();
108
+ $form.find('#' + response.address + ' h3').append($('<span/>').addClass('message error').text(response.errors[0]));
109
+ }
110
+ }
111
+ });
112
+ };
113
+
114
+ self.login_form_submit_handler = function(event) {
115
+ $('#message').html("<p class='loading'>Logging in...</p>");
116
+ $.ajax({
117
+ url: '/login',
118
+ type: 'post',
119
+ data: $('#signin_form').serialize(),
120
+ success: function(resp) {
121
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
122
+ else window.location = '/checkout/step-two';
123
+ }
124
+ });
125
+ return false;
126
+ };
127
+
128
+ self.register_form_submit_handler = function(event) {
129
+ $('#message').html("<p class='loading'>Registering...</p>");
130
+ $.ajax({
131
+ url: '/register',
132
+ type: 'post',
133
+ data: $('#register_form').serialize(),
134
+ success: function(resp) {
135
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
136
+ else window.location = '/checkout/step-two';
137
+ }
138
+ });
139
+ return false;
140
+ };
141
+
142
+ self.guest_form_submit_handler = function(event) {
143
+ $('#message').html("<p class='loading'>Submitting...</p>");
144
+ $.ajax({
145
+ url: '/checkout/attach-guest',
146
+ type: 'post',
147
+ data: $('#guest_form').serialize(),
148
+ success: function(resp) {
149
+ if (resp.error) $('#message').html("<p class='note error'>" + resp.error + "</p>");
150
+ else window.location = '/checkout/step-two';
151
+ }
152
+ });
153
+ return false;
154
+ };
155
+
156
+ return self
157
+ }).call(Caboose.Store);
@@ -0,0 +1,39 @@
1
+
2
+ Caboose.Store.Modules.CheckoutStep2 = (function() {
3
+
4
+ self = {};
5
+
6
+ self.initialize = function() {
7
+ self.bind_event_handlers();
8
+ };
9
+
10
+ self.bind_event_handlers = function() {
11
+ $('input[type=checkbox][name=use_as_billing]').on('change', self.use_as_billing_handler);
12
+ $('#address_form').submit(self.continue_handler);
13
+ };
14
+
15
+ self.use_as_billing_handler = function(event) {
16
+ if (event.target.checked)
17
+ $('#billing').hide();
18
+ else
19
+ $('#billing').show();
20
+ };
21
+
22
+ self.continue_handler = function(event) {
23
+ $('#message').html("<p class='loading'>Saving information...</p>");
24
+ $.ajax({
25
+ url: '/checkout/address',
26
+ type: 'put',
27
+ data: $('#address_form').serialize(),
28
+ success: function(resp) {
29
+ if (resp.errors && resp.errors.length > 0)
30
+ $('#message').html("<p class='note error'>" + resp.errors[0] + "</p>");
31
+ else if (resp.success)
32
+ window.location = '/checkout/step-three';
33
+ }
34
+ });
35
+ return false;
36
+ };
37
+
38
+ return self
39
+ }).call(Caboose.Store);
@@ -0,0 +1,34 @@
1
+
2
+ Caboose.Store.Modules.CheckoutStep3 = (function() {
3
+
4
+ self = {};
5
+
6
+ self.initialize = function() {
7
+ self.bind_event_handlers();
8
+ };
9
+
10
+ self.bind_event_handlers = function() {
11
+ $('#checkout button').click(self.shipping_click_handler);
12
+ };
13
+
14
+ self.shipping_click_handler = function(event) {
15
+ $('#message').html("<p class='loading'>Saving information...</p>");
16
+ $.ajax({
17
+ url: '/checkout/shipping',
18
+ type: 'put',
19
+ data: {
20
+ shipping_method: $(event.target).data('shipping-method'),
21
+ shipping_code: $(event.target).data('shipping-code')
22
+ },
23
+ success: function(resp) {
24
+ if (resp.errors && resp.errors.length > 0)
25
+ $('#message').html("<p class='note error'>" + resp.errors[0] + "</p>");
26
+ else if (resp.success)
27
+ window.location = '/checkout/step-four';
28
+ }
29
+ });
30
+ return false;
31
+ };
32
+
33
+ return self
34
+ }).call(Caboose.Store);
@@ -0,0 +1,102 @@
1
+
2
+ Caboose.Store.Modules.CheckoutStep4 = (function() {
3
+
4
+ self = {
5
+ is_confirm: false
6
+ };
7
+
8
+ self.initialize = function() {
9
+ $('#checkout-confirm').hide();
10
+ $('#relay').hide();
11
+ self.bind_event_handlers();
12
+ };
13
+
14
+ self.bind_event_handlers = function() {
15
+ $('#checkout-payment form#payment select').change(self.expiration_change_handler);
16
+ $('#checkout-continue button').click(self.continue_handler);
17
+ $('#checkout-confirm #edit_payment').click(self.edit_payment_handler);
18
+ //$('#relay').on('load', self.relay_handler);
19
+ };
20
+
21
+ self.expiration_change_handler = function(event) {
22
+ var form = $('#checkout-payment #payment')
23
+ month = form.find('select[name=month]').val()
24
+ year = form.find('select[name=year]').val();
25
+ $('#expiration').val(month + year);
26
+ };
27
+
28
+ self.continue_handler = function(event) {
29
+ if (!self.is_confirm)
30
+ {
31
+ var cc = $('#billing-cc-number').val();
32
+ if (cc.length < 15)
33
+ $('#message').html("<p class='note error'>Please enter a valid credit card number.</p>");
34
+ else
35
+ {
36
+ $('#message').empty();
37
+ $('#checkout-payment').hide();
38
+ $('#checkout-confirm').show();
39
+ $('#checkout_nav4 a').removeClass('current').addClass('done');
40
+ $('#checkout_nav5 a').removeClass('not_done').addClass('current');
41
+ $('#confirm_card_number').html("Card ending in " + cc.substr(-4));
42
+ $('#checkout-continue button').html("Confirm order");
43
+ self.is_confirm = true;
44
+ }
45
+ }
46
+ else
47
+ {
48
+ $('#message').html("<p class='loading'>Processing payment...</p>");
49
+ $('form#payment').submit();
50
+ }
51
+ };
52
+
53
+ self.edit_payment_handler = function(event) {
54
+ $('#checkout-confirm').hide();
55
+ $('#checkout-payment').show();
56
+ $('#checkout_nav4 a').removeClass('done').addClass('current');
57
+ $('#checkout_nav5 a').removeClass('current').addClass('not_done');
58
+ $('#checkout-continue button').html("Continue");
59
+ self.is_confirm = false;
60
+ };
61
+
62
+ //self.relay_handler = function(event) {
63
+ // alert('Relay handler');
64
+ // var iframe = $('#relay');
65
+ // var form = $('#payment');
66
+ // var resp = iframe.contents().find('#response');
67
+ //
68
+ // if (!resp.length || form.length)
69
+ // {
70
+ // alert('No response found.');
71
+ // return false;
72
+ // }
73
+ //
74
+ // resp = JSON.parse(resp.html());
75
+ // if (resp.error)
76
+ // $('#message').html("<p class='note error'>" + resp.error + "</p>");
77
+ // else if (resp.success == true)
78
+ // window.location = '/checkout/thanks';
79
+ //};
80
+
81
+ return self
82
+ }).call(Caboose.Store);
83
+
84
+ function relay_handler()
85
+ {
86
+ alert('Relay handler');
87
+ var iframe = $('#relay');
88
+ var form = $('#payment');
89
+ var resp = iframe.contents().find('#response');
90
+
91
+ if (!resp.length || form.length)
92
+ {
93
+ alert('No response found.');
94
+ return false;
95
+ }
96
+
97
+ resp = JSON.parse(resp.html());
98
+ if (resp.error)
99
+ $('#message').html("<p class='note error'>" + resp.error + "</p>");
100
+ else if (resp.success == true)
101
+ window.location = '/checkout/thanks';
102
+ }
@@ -1,4 +1,4 @@
1
- <div class="wrapper">
1
+ <div class="wrapper">
2
2
  <form action="/checkout/attach-guest" method="post">
3
3
  <input name="email" type="text" placeholder="Email" />
4
4
  <input name="confirm_email" type="email" placeholder="Confirm email" />
@@ -1,4 +1,4 @@
1
- <div class="wrapper">
1
+ <div class="wrapper">
2
2
  <form action="/register" method="post">
3
3
  <input name="first_name" type="text" placeholder="First Name" />
4
4
  <input name="last_name" type="text" placeholder="Last Name" />
@@ -1,4 +1,4 @@
1
- <div class="wrapper">
1
+ <div class="wrapper">
2
2
  <form action="/login" method="post">
3
3
  <input name="username" type="text" placeholder="Email" />
4
4
  <input name="password" type="password" placeholder="Password" />
@@ -7,8 +7,7 @@
7
7
  <aside>
8
8
  <figure style="background-image: url(<%= lineItem.variant.images[0].urls.thumb %>)"></figure>
9
9
  <p><%= lineItem.title %><br />Qty: <%= lineItem.quantity %><br /><span class="price">$<%= ((parseFloat(lineItem.price) * 100) / 100).toFixed(2) %></span></p>
10
- </aside>
11
-
10
+ </aside>
12
11
  <section>
13
12
  <p>$<%= ((parseFloat(lineItem.price) * 100) / 100).toFixed(2) %></p>
14
13
  </section>
@@ -1,18 +1,18 @@
1
- <div class="wrapper">
1
+ <div class="wrapper" class='login-choices'>
2
2
  <ul>
3
3
  <li>
4
4
  <p>Already a member<p>
5
- <button data-login-action="signin">Sign in</button>
5
+ <button data-login-action="signin" id='signin_button'>Sign in</button>
6
6
  </li>
7
7
 
8
8
  <li>
9
9
  <p>Sign up for all of our member benefits</p>
10
- <button data-login-action="register">New Customer</button>
10
+ <button data-login-action="register" id='register_button'>New Customer</button>
11
11
  </li>
12
12
 
13
13
  <li>
14
14
  <p>No thanks</p>
15
- <button data-login-action="continue">Continue As Guest</button>
15
+ <button data-login-action="continue" id='continue_button'>Continue As Guest</button>
16
16
  </li>
17
17
  </ul>
18
18
  </div>
@@ -7,15 +7,57 @@ module CabooseStore
7
7
  redirect_to '/checkout/empty' if @order.line_items.empty?
8
8
  end
9
9
 
10
- # GET /checkout || GET /checkout/step-one
10
+ # GET /checkout
11
+ def index
12
+ redirect_to '/checkout/step-one'
13
+ end
14
+
15
+ # GET /checkout/step-one
11
16
  def step_one
17
+ redirect_to '/checkout/step-two' if logged_in?
12
18
  end
13
19
 
14
20
  # GET /checkout/step-two
15
21
  def step_two
16
- redirect_to '/checkout/step-one' if !@order.shipping_address || !@order.billing_address
22
+ #redirect_to '/checkout/step-one' if !@order.shipping_address || !@order.billing_address
23
+ redirect_to '/checkout/step-one' if !logged_in?
24
+ end
25
+
26
+ # GET /checkout/step-three
27
+ def step_three
28
+ redirect_to '/checkout/step-one' and return if !logged_in?
29
+ redirect_to '/checkout/step-two' and return if @order.shipping_address.nil? || @order.billing_address.nil?
30
+ @rates = ShippingCalculator.rates(@order)
31
+ @selected_rate = ShippingCalculator.rate(@order)
32
+ end
33
+
34
+ # GET /checkout/step-four
35
+ def step_four
36
+ redirect_to '/checkout/step-one' and return if !logged_in?
37
+ redirect_to '/checkout/step-two' and return if @order.shipping_address.nil? || @order.billing_address.nil?
38
+ redirect_to '/checkout/step-three' and return if @order.shipping_code.nil?
39
+
40
+ case CabooseStore::payment_processor
41
+ when 'authorize.net'
42
+ @sim_transaction = AuthorizeNet::SIM::Transaction.new(
43
+ CabooseStore::authorize_net_login_id,
44
+ CabooseStore::authorize_net_transaction_key,
45
+ @order.total,
46
+ :relay_url => "#{CabooseStore::root_url}/checkout/relay/#{@order.id}",
47
+ :transaction_type => 'AUTH_ONLY',
48
+ :test => true
49
+ )
50
+ when 'payscape'
51
+ @form_url = CabooseStore::PaymentProcessor.form_url(@order)
52
+ end
17
53
  end
18
54
 
55
+ # GET /checkout/thanks
56
+ def thanks
57
+ end
58
+
59
+ #===========================================================================
60
+
19
61
  # GET /checkout/address
20
62
  def address
21
63
  render :json => {
@@ -68,7 +110,7 @@ module CabooseStore
68
110
  end
69
111
 
70
112
  # POST /checkout/attach-user
71
- def attach_user
113
+ def attach_user
72
114
  render :json => { :success => false, :errors => ['User is not logged in'] } and return if !logged_in?
73
115
  @order.customer_id = logged_in_user.id
74
116
  render :json => { :success => @order.save, :errors => @order.errors.full_messages, :logged_in => logged_in? }
@@ -76,54 +118,82 @@ module CabooseStore
76
118
 
77
119
  # POST /checkout/guest
78
120
  def attach_guest
79
- render :json => { :success => false, :errors => ['Emails do not match'] } and return if params[:email] != params[:confirm_email]
80
- @order.email = params[:email]
81
- render :json => { :succes => @order.save, :errors => @order.errors.full_messages, :logged_in => logged_in? }
121
+ resp = Caboose::StdClass.new
122
+ email = params[:email]
123
+
124
+ if email != params[:confirm_email]
125
+ resp.error = "Emails do not match."
126
+ elsif Caboose::User.where(:email => email, :is_guest => false).exists?
127
+ resp.error = "A user with that email address already exists."
128
+ else
129
+ user = Caboose::User.where(:email => email, :is_guest => true).first
130
+ if user.nil?
131
+ user = Caboose::User.create(:email => email)
132
+ user.is_guest = true
133
+ user.save
134
+ user = Caboose::User.where(:email => email).first
135
+ end
136
+ @order.customer_id = user.id
137
+ login_user(user)
138
+
139
+ if !@order.valid?
140
+ resp.errors = @order.errors.full_messages
141
+ else
142
+ @order.save
143
+ resp.redirect = '/checkout/step-two'
144
+ end
145
+ end
146
+ render :json => resp
82
147
  end
83
148
 
84
- # GET /checkout/shipping
85
- def shipping
86
- render :json => { :rates => ShippingCalculator.rates(@order), :selected_rate => ShippingCalculator.rate(@order) }
87
- end
149
+ ## GET /checkout/shipping
150
+ #def shipping
151
+ # render :json => { :rates => ShippingCalculator.rates(@order), :selected_rate => ShippingCalculator.rate(@order) }
152
+ #end
88
153
 
89
154
  # PUT /checkout/shipping
90
- def update_shipping
91
- @order.shipping_code = params[:shipping_code]
92
- render :json => { :success => @order.save, :errors => @order.errors.full_messages, :order => @order, :selected_rate => ShippingCalculator.rate(@order) }
155
+ def update_shipping
156
+ @order.shipping_method = params[:shipping_method]
157
+ @order.shipping_code = params[:shipping_code]
158
+ render :json => {
159
+ :success => @order.save,
160
+ :errors => @order.errors.full_messages
161
+ #:order => @order,
162
+ #:selected_rate => ShippingCalculator.rate(@order)
163
+ }
93
164
  end
94
165
 
95
166
  # GET /checkout/payment
96
- def payment
97
- case CabooseStore::payment_processor
98
- when 'authorize.net'
99
- @sim_transaction = AuthorizeNet::SIM::Transaction.new(
100
- CabooseStore::authorize_net_login_id,
101
- CabooseStore::authorize_net_transaction_key,
102
- @order.total,
103
- :relay_url => "#{CabooseStore::root_url}/checkout/relay/#{@order.id}",
104
- :transaction_type => 'AUTH_ONLY',
105
- :test => true
106
- )
107
- when 'payscape'
108
- @form_url = CabooseStore::PaymentProcessor.form_url(@order)
109
- end
110
-
111
- render :layout => false
112
- end
167
+ #def payment
168
+ # case CabooseStore::payment_processor
169
+ # when 'authorize.net'
170
+ # @sim_transaction = AuthorizeNet::SIM::Transaction.new(
171
+ # CabooseStore::authorize_net_login_id,
172
+ # CabooseStore::authorize_net_transaction_key,
173
+ # @order.total,
174
+ # :relay_url => "#{CabooseStore::root_url}/checkout/relay/#{@order.id}",
175
+ # :transaction_type => 'AUTH_ONLY',
176
+ # :test => true
177
+ # )
178
+ # when 'payscape'
179
+ # @form_url = CabooseStore::PaymentProcessor.form_url(@order)
180
+ # end
181
+ # render :layout => false
182
+ #end
113
183
 
114
184
  # POST /checkout/relay/:order_id
115
185
  def relay
116
186
  @order = CabooseStore::Order.find(params[:order_id])
117
187
 
118
188
  case CabooseStore::payment_processor
119
- when 'authorize.net'
120
- @success = params[:x_response_code] == '1'
121
- @message = params[:x_response_reason_text]
122
- @order.transaction_id = params[:x_trans_id] if params[:x_trans_id]
123
- when 'payscape'
124
- @success = CabooseStore::PaymentProcessor.authorize(@order, params)
125
- @message = @success ? 'Payment processed successfully' : 'There was a problem processing your payment'
126
- @order.transaction_id = params['transaction-id'] if params['transaction-id']
189
+ when 'authorize.net'
190
+ @success = params[:x_response_code] == '1'
191
+ @message = params[:x_response_reason_text]
192
+ @order.transaction_id = params[:x_trans_id] if params[:x_trans_id]
193
+ when 'payscape'
194
+ @success = CabooseStore::PaymentProcessor.authorize(@order, params)
195
+ @message = @success ? 'Payment processed successfully' : 'There was a problem processing your payment'
196
+ @order.transaction_id = params['transaction-id'] if params['transaction-id']
127
197
  end
128
198
  ap @success
129
199
  ap '---------'
@@ -150,14 +220,6 @@ module CabooseStore
150
220
  render :layout => false
151
221
  end
152
222
 
153
- # GET /checkout/empty
154
- def empty
155
- end
156
-
157
- # GET /checkout/thanks
158
- def thanks
159
- end
160
-
161
223
  # GET /checkout/discount
162
224
  #def discount
163
225
  # # TODO make it possible to use multiple discounts