locomotive_ecommerce_plugin 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/Gemfile +40 -0
- data/app/assets/javascripts/locomotive/ecommerce/application.js +15 -0
- data/app/assets/stylesheets/locomotive/ecommerce/application.css +13 -0
- data/app/assets/stylesheets/locomotive/ecommerce/flash_dance.alerts.bootstrap.css +107 -0
- data/app/controllers/locomotive/ecommerce/application_controller.rb +35 -0
- data/app/controllers/locomotive/ecommerce/cart_controller.rb +12 -0
- data/app/controllers/locomotive/ecommerce/order_controller.rb +18 -0
- data/app/controllers/locomotive/ecommerce/purchase_controller.rb +56 -0
- data/app/helpers/locomotive/ecommerce/ecommerce_cart_helper.rb +11 -0
- data/app/helpers/locomotive/ecommerce/ecommerce_helper.rb +25 -0
- data/app/helpers/locomotive/ecommerce/ecommerce_url_helper.rb +52 -0
- data/app/mailers/locomotive/ecommerce/purchase_mailer.rb +19 -0
- data/app/models/locomotive/ecommerce/cart.rb +162 -0
- data/app/models/locomotive/ecommerce/order.rb +100 -0
- data/app/models/locomotive/ecommerce/purchase.rb +148 -0
- data/app/views/flash_dance/_alert.html.erb +4 -0
- data/app/views/flash_dance/_error.html.erb +4 -0
- data/app/views/flash_dance/_info.html.erb +4 -0
- data/app/views/flash_dance/_notice.html.erb +4 -0
- data/app/views/flash_dance/_success.html.erb +4 -0
- data/app/views/flash_dance/_warning.html.erb +4 -0
- data/app/views/kaminari/_first_page.html.erb +11 -0
- data/app/views/kaminari/_gap.html.erb +8 -0
- data/app/views/kaminari/_last_page.html.erb +11 -0
- data/app/views/kaminari/_next_page.html.erb +11 -0
- data/app/views/kaminari/_page.html.erb +12 -0
- data/app/views/kaminari/_paginator.html.erb +23 -0
- data/app/views/kaminari/_prev_page.html.erb +11 -0
- data/app/views/locomotive/ecommerce/purchase_mailer/purchase_confirmation.text.erb +11 -0
- data/config/initializers/active_resource.rb +1 -0
- data/config/initializers/kaminari_config.rb +16 -0
- data/config/initializers/liquid_stack_trace.rb +7 -0
- data/config/initializers/stripe_setup.rb +40 -0
- data/config/routes.rb +14 -0
- data/lib/locomotive/ecommerce/plugin.rb +74 -0
- data/lib/locomotive/ecommerce/plugin/config.html +111 -0
- data/lib/locomotive/ecommerce/plugin/ecommerce_drop.rb +106 -0
- data/lib/locomotive/ecommerce/plugin/ecommerce_filters.rb +35 -0
- data/lib/locomotive/ecommerce/plugin/ecommerce_tags.rb +31 -0
- data/lib/locomotive/ecommerce/plugin/engine.rb +42 -0
- data/lib/locomotive/ecommerce/plugin/inventory_interface.rb +15 -0
- data/lib/locomotive/ecommerce/plugin/version.rb +5 -0
- data/lib/locomotive_ecommerce_plugin.rb +1 -0
- metadata +184 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YWE5M2U2MDk3N2QxMGEwZTJjZTlkMTdiYTkyYTY1MGZiYzJhNWYwNg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YmY0ZDQ1YzA2Y2E5NDU3MzhhNzBlNzliOThjNWQ5NzliN2VmMTRlMg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YTRmZTY0YTM1YjZhYjVkMTQ3Mzc0OGNlN2ZhOWZhNGI0NmY1NGZjOWY2YWYz
|
10
|
+
OThlNTY3ZTI3ZDgyZmE4Y2Q4NzkxNTdjYjVkZDA5NDBlMTg5ZWY0ZDgwM2E0
|
11
|
+
OTkxMGE1MTM4YzQ1YTlhYTJkNTM4MWMxMjIwM2U1MmRiZTNjOWY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZjlkNDAwMTdkYTdkYWU0NTdmZjZlOWQ4OWJhYjM0MjEwOWRmNDJmNzc0NWQ0
|
14
|
+
OTFjMzg1YTNkZDBjNjMxNjNkOTdlMjc2NzlkZGUzNWJiMTJiMTgzMTBlMjdl
|
15
|
+
OWI3OWU1M2YxZWM4ZmJkNWYxYzc0OTJlYTkxNzJiMGVkOWZmMDI=
|
data/Gemfile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# Declare your gem's dependencies in hbird_ecommerce.gemspec.
|
4
|
+
# Bundler will treat runtime dependencies like base dependencies, and
|
5
|
+
# development dependencies will be added by default to the :development group.
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
# Stripe helper
|
9
|
+
gem 'stripe_helper', path: '../../stripe_helper'
|
10
|
+
|
11
|
+
# jquery-rails is used by the dummy application
|
12
|
+
group :test do
|
13
|
+
gem 'rspec-rails'
|
14
|
+
gem 'capybara'
|
15
|
+
gem "factory_girl"
|
16
|
+
gem "mocha"
|
17
|
+
gem "database_cleaner"
|
18
|
+
gem "factory_girl_rails"
|
19
|
+
gem "simplecov", require: false
|
20
|
+
gem 'shoulda-matchers', require: false
|
21
|
+
gem "debugger"
|
22
|
+
gem "poltergeist"
|
23
|
+
end
|
24
|
+
|
25
|
+
# gem "locomotive_cms", path: '../../locomotive_engine', require: 'locomotive/engine'
|
26
|
+
# gem "locomotive_plugins", path: '../../locomotive_plugins'
|
27
|
+
|
28
|
+
group :assets do
|
29
|
+
gem 'compass-rails', '~> 1.1.7'
|
30
|
+
gem 'sass-rails', '~> 3.2.4'
|
31
|
+
gem 'coffee-rails', '~> 3.2.2'
|
32
|
+
gem 'uglifier', '~> 1.2.4'
|
33
|
+
end
|
34
|
+
|
35
|
+
group :locomotive_plugins do
|
36
|
+
gem "locomotive_ecommerce_plugin", path: '.'
|
37
|
+
end
|
38
|
+
|
39
|
+
# TEMP
|
40
|
+
gem 'flash-dance', :git => 'https://github.com/MunkiPhD/flash-dance.git' # It may be not being used.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,107 @@
|
|
1
|
+
/*!
|
2
|
+
* Bootstrap v2.2.1
|
3
|
+
*
|
4
|
+
* Copyright 2012 Twitter, Inc
|
5
|
+
* Licensed under the Apache License v2.0
|
6
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
*
|
8
|
+
* Designed and built with all the love in the world @twitter by @mdo and @fat.
|
9
|
+
*/
|
10
|
+
.clearfix {
|
11
|
+
*zoom: 1;
|
12
|
+
}
|
13
|
+
.clearfix:before,
|
14
|
+
.clearfix:after {
|
15
|
+
display: table;
|
16
|
+
content: "";
|
17
|
+
line-height: 0;
|
18
|
+
}
|
19
|
+
.clearfix:after {
|
20
|
+
clear: both;
|
21
|
+
}
|
22
|
+
.hide-text {
|
23
|
+
font: 0/0 a;
|
24
|
+
color: transparent;
|
25
|
+
text-shadow: none;
|
26
|
+
background-color: transparent;
|
27
|
+
border: 0;
|
28
|
+
}
|
29
|
+
.input-block-level {
|
30
|
+
display: block;
|
31
|
+
width: 100%;
|
32
|
+
min-height: 30px;
|
33
|
+
-webkit-box-sizing: border-box;
|
34
|
+
-moz-box-sizing: border-box;
|
35
|
+
box-sizing: border-box;
|
36
|
+
}
|
37
|
+
.alert {
|
38
|
+
padding: 8px 35px 8px 14px;
|
39
|
+
margin-bottom: 20px;
|
40
|
+
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
|
41
|
+
background-color: #fcf8e3;
|
42
|
+
border: 1px solid #fbeed5;
|
43
|
+
-webkit-border-radius: 4px;
|
44
|
+
-moz-border-radius: 4px;
|
45
|
+
border-radius: 4px;
|
46
|
+
color: #c09853;
|
47
|
+
}
|
48
|
+
.alert h4 {
|
49
|
+
margin: 0;
|
50
|
+
}
|
51
|
+
.alert .close {
|
52
|
+
position: relative;
|
53
|
+
top: -2px;
|
54
|
+
right: -21px;
|
55
|
+
line-height: 20px;
|
56
|
+
}
|
57
|
+
.alert-success {
|
58
|
+
background-color: #dff0d8;
|
59
|
+
border-color: #d6e9c6;
|
60
|
+
color: #468847;
|
61
|
+
}
|
62
|
+
.alert-danger,
|
63
|
+
.alert-error {
|
64
|
+
background-color: #f2dede;
|
65
|
+
border-color: #eed3d7;
|
66
|
+
color: #b94a48;
|
67
|
+
}
|
68
|
+
.alert-info {
|
69
|
+
background-color: #d9edf7;
|
70
|
+
border-color: #bce8f1;
|
71
|
+
color: #3a87ad;
|
72
|
+
}
|
73
|
+
.alert-block {
|
74
|
+
padding-top: 14px;
|
75
|
+
padding-bottom: 14px;
|
76
|
+
}
|
77
|
+
.alert-block > p,
|
78
|
+
.alert-block > ul {
|
79
|
+
margin-bottom: 0;
|
80
|
+
}
|
81
|
+
.alert-block p + p {
|
82
|
+
margin-top: 5px;
|
83
|
+
}
|
84
|
+
.close {
|
85
|
+
float: right;
|
86
|
+
font-size: 20px;
|
87
|
+
font-weight: bold;
|
88
|
+
line-height: 20px;
|
89
|
+
color: #000000;
|
90
|
+
text-shadow: 0 1px 0 #ffffff;
|
91
|
+
opacity: 0.2;
|
92
|
+
filter: alpha(opacity=20);
|
93
|
+
}
|
94
|
+
.close:hover {
|
95
|
+
color: #000000;
|
96
|
+
text-decoration: none;
|
97
|
+
cursor: pointer;
|
98
|
+
opacity: 0.4;
|
99
|
+
filter: alpha(opacity=40);
|
100
|
+
}
|
101
|
+
button.close {
|
102
|
+
padding: 0;
|
103
|
+
cursor: pointer;
|
104
|
+
background: transparent;
|
105
|
+
border: 0;
|
106
|
+
-webkit-appearance: none;
|
107
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Ecommerce
|
3
|
+
class ApplicationController < ::ActionController::Base
|
4
|
+
include ::Locomotive::Ecommerce::EcommerceHelper
|
5
|
+
|
6
|
+
before_filter :set_current_site
|
7
|
+
|
8
|
+
def authenticate_user!
|
9
|
+
if current_user(self) == nil
|
10
|
+
flash[:error] = "Authentication needed. Please log in to continue."
|
11
|
+
redirect_to cart_path
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def locomotive_user?
|
16
|
+
locomotive_account_signed_in?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def fetch_site
|
22
|
+
if Locomotive.config.multi_sites?
|
23
|
+
@current_site ||= ::Locomotive::Site.match_domain(request.host).first
|
24
|
+
else
|
25
|
+
@current_site ||= ::Locomotive::Site.first
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_current_site
|
30
|
+
Thread.current[:site] = fetch_site
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Ecommerce
|
3
|
+
class CartController < ::Locomotive::Ecommerce::ApplicationController
|
4
|
+
def update
|
5
|
+
@cart = Cart.find(params[:id])
|
6
|
+
@cart.update_from_params(params)
|
7
|
+
flash[:success] = 'Updated cart'
|
8
|
+
redirect_to cart_path
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Ecommerce
|
3
|
+
class OrderController < ::Locomotive::Ecommerce::ApplicationController
|
4
|
+
def create
|
5
|
+
@order = current_user_cart(self).add_product_by_sku(params[:item_sku])
|
6
|
+
flash[:success] = 'Added product to cart'
|
7
|
+
redirect_to cart_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def destroy
|
11
|
+
@order = current_user_cart(self).remove_product_by_sku(
|
12
|
+
params[:product_id])
|
13
|
+
flash[:success] = 'Removed product from cart'
|
14
|
+
redirect_to cart_path
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'stripe'
|
2
|
+
|
3
|
+
module Locomotive
|
4
|
+
module Ecommerce
|
5
|
+
class PurchaseController < ::Locomotive::Ecommerce::ApplicationController
|
6
|
+
before_filter :authenticate_user!, except: [:do_new_purchase]
|
7
|
+
|
8
|
+
def create
|
9
|
+
@purchase = current_user_cart(self).purchase
|
10
|
+
@purchase.shipping_info = params[:shipping_info]
|
11
|
+
@purchase.shipping_method = params[:shipping_method]
|
12
|
+
if @purchase.save
|
13
|
+
redirect_to confirm_order_path
|
14
|
+
return
|
15
|
+
elsif @purchase.errors.any?
|
16
|
+
flash_ar = []
|
17
|
+
@purchase.errors.full_messages.each { |msg| flash_ar << msg }
|
18
|
+
flash[:error] = flash_ar.join(', ')
|
19
|
+
end
|
20
|
+
|
21
|
+
redirect_to checkout_path
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.complete(purchase_id, user, cart, stripeToken)
|
25
|
+
purchase = Purchase.where(_id: purchase_id).first
|
26
|
+
|
27
|
+
#Reset user cart
|
28
|
+
purchase.cart.user_id = nil
|
29
|
+
purchase.cart.save!
|
30
|
+
new_cart = Cart.create
|
31
|
+
new_cart.user_id = user.id
|
32
|
+
new_cart.save!
|
33
|
+
|
34
|
+
#complete purchase
|
35
|
+
purchase.stripe_token = stripeToken
|
36
|
+
purchase.complete
|
37
|
+
purchase.completed = true
|
38
|
+
purchase.user_id = user.id
|
39
|
+
purchase.save!
|
40
|
+
PurchaseMailer.purchase_confirmation(user, purchase).deliver
|
41
|
+
after_purchase_hook(purchase, user)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def self.after_purchase_hook(purchase, user)
|
47
|
+
|
48
|
+
site = Thread.current[:site]
|
49
|
+
cxt = site.plugin_object_for_id('ecommerce').js3_context
|
50
|
+
cxt['user'] = user
|
51
|
+
cxt['purchase'] = purchase
|
52
|
+
last = cxt.eval(Engine.config_or_default('after_purchase_hook'))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'locomotive/ecommerce/plugin/inventory_interface'
|
2
|
+
|
3
|
+
module Locomotive
|
4
|
+
module Ecommerce
|
5
|
+
module EcommerceHelper
|
6
|
+
include ::Locomotive::Ecommerce::EcommerceCartHelper
|
7
|
+
include ::Locomotive::Ecommerce::EcommerceUrlHelper
|
8
|
+
include ::Locomotive::Ecommerce::InventoryInterface
|
9
|
+
|
10
|
+
# User
|
11
|
+
def current_user(controller)
|
12
|
+
if controller.session[:user_id]
|
13
|
+
site = Thread.current[:site]
|
14
|
+
user_from_plugin = site.plugin_object_for_id('identity_plugin').js3_context['identity_plugin_users']
|
15
|
+
@current_user ||= user_from_plugin.find(controller.session[:user_id])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# View Helper
|
20
|
+
def as_currency(val)
|
21
|
+
"$#{'%.2f' % val}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Ecommerce
|
3
|
+
module EcommerceUrlHelper
|
4
|
+
##################
|
5
|
+
# configured urls
|
6
|
+
##################
|
7
|
+
def cart_path(*args)
|
8
|
+
Engine.config_or_default('cart_url')
|
9
|
+
end
|
10
|
+
|
11
|
+
def checkout_path
|
12
|
+
Engine.config_or_default('checkout_url')
|
13
|
+
end
|
14
|
+
|
15
|
+
def confirm_order_path
|
16
|
+
Engine.config_or_default('confirm_order_url')
|
17
|
+
end
|
18
|
+
|
19
|
+
def purchases_path
|
20
|
+
Engine.config_or_default('purchases_url')
|
21
|
+
end
|
22
|
+
|
23
|
+
def post_checkout_path
|
24
|
+
Engine.config_or_default('post_checkout_url')
|
25
|
+
end
|
26
|
+
|
27
|
+
###########################
|
28
|
+
# non-configured urls
|
29
|
+
# (provided by the engine)
|
30
|
+
# #########################
|
31
|
+
def cart_update_path(stem, cart)
|
32
|
+
"#{stem}cart/#{cart.id}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_to_cart_path(stem, product)
|
36
|
+
"#{stem}add_to_cart/#{product.id}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def remove_from_cart_path(stem, product_id)
|
40
|
+
"#{stem}remove_from_cart/#{product_id}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def checkout_update_path(stem, purchase)
|
44
|
+
"#{stem}checkout/#{purchase.id}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def checkout_index_path(stem)
|
48
|
+
"#{stem}checkout"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Ecommerce
|
3
|
+
class PurchaseMailer < ActionMailer::Base
|
4
|
+
default from: Engine.config_or_default('contact')
|
5
|
+
|
6
|
+
# Subject can be set in your I18n file at config/locales/en.yml
|
7
|
+
# with the following lookup:
|
8
|
+
#
|
9
|
+
# en.purchase_mailer.purchase_confirmation.subject
|
10
|
+
#
|
11
|
+
def purchase_confirmation(user, purchase)
|
12
|
+
@purchase = purchase
|
13
|
+
@contact = Engine.config_or_default('contact')
|
14
|
+
@shop_name = Engine.config_or_default('shop_name')
|
15
|
+
mail to: user.email, subject: "Purchase Confirmation"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Ecommerce
|
3
|
+
class Cart
|
4
|
+
include ::Locomotive::Ecommerce::EcommerceHelper
|
5
|
+
include Mongoid::Document
|
6
|
+
field :user_id, :type => ::BSON::ObjectId
|
7
|
+
belongs_to :purchase, :class_name => "::Locomotive::Ecommerce::Purchase"
|
8
|
+
has_many :orders, :class_name => "::Locomotive::Ecommerce::Order"
|
9
|
+
|
10
|
+
def add_product_by_sku(sku)
|
11
|
+
already_existing_order = orders.where(:sku => sku)
|
12
|
+
if already_existing_order.count > 0
|
13
|
+
order = already_existing_order.first
|
14
|
+
order.quantity += 1
|
15
|
+
else
|
16
|
+
order = Order.new
|
17
|
+
order.sku = sku
|
18
|
+
order.cart = self
|
19
|
+
end
|
20
|
+
order.save!
|
21
|
+
return order
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_product_by_sku(sku)
|
25
|
+
order = orders.where(:sku => sku)
|
26
|
+
order.destroy if order
|
27
|
+
end
|
28
|
+
|
29
|
+
def purchase_total
|
30
|
+
total = 0
|
31
|
+
orders.each { |order| total += order.price }
|
32
|
+
return total
|
33
|
+
end
|
34
|
+
|
35
|
+
def estimated_tax
|
36
|
+
purchase_total * ((Engine.config_or_default('estimated_tax_rate').to_f/100))
|
37
|
+
end
|
38
|
+
|
39
|
+
def subtotal_est_tax
|
40
|
+
purchase_total + estimated_tax + extras_total
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_extras_js
|
44
|
+
ext = Engine.config_or_default('edit_extra')
|
45
|
+
return nil unless ext
|
46
|
+
site = Thread.current[:site]
|
47
|
+
cxt = site.plugin_object_for_id('inventory').js3_context
|
48
|
+
cxt['purchase_total'] = purchase_total
|
49
|
+
cxt['orders'] = orders
|
50
|
+
js = cxt.eval(ext)
|
51
|
+
|
52
|
+
return js
|
53
|
+
end
|
54
|
+
|
55
|
+
def extras_total
|
56
|
+
ext = 0
|
57
|
+
arr = add_extras_js
|
58
|
+
# Adding all the values returned by the javascript function
|
59
|
+
if arr
|
60
|
+
arr.values.each do |value|
|
61
|
+
ext += value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
return ext
|
66
|
+
end
|
67
|
+
|
68
|
+
def extras
|
69
|
+
orders ? arr = add_extras_js : ''
|
70
|
+
# Converting the prices to currency
|
71
|
+
extras_hash = Hash[arr.map {|k,v| [k,as_currency(v) ]}]
|
72
|
+
extras_hash.to_liquid
|
73
|
+
end
|
74
|
+
|
75
|
+
def update_from_params(params)
|
76
|
+
to_update = Order.find(params[:order_ids])
|
77
|
+
count = 0
|
78
|
+
to_update.each do |order|
|
79
|
+
order.quantity = params[:quantity_ids][count] if order.cart_id == id
|
80
|
+
count += 1
|
81
|
+
order.save!
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# merge in contents of another cart
|
86
|
+
def merge(cart)
|
87
|
+
cart.orders.each do |order|
|
88
|
+
(1..order.quantity).each { |c| add_product_by_sku(order.sku) }
|
89
|
+
cart.remove_product_by_sku(order.sku)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def valid_stock?
|
94
|
+
orders.each { |order| return false if order.out_of_stock? }
|
95
|
+
return true
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_liquid
|
99
|
+
CartDrop.new(self)
|
100
|
+
end
|
101
|
+
|
102
|
+
# self methods
|
103
|
+
def self.for_user(id)
|
104
|
+
cart = where(:user_id => id).first || create(:user_id => id)
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.find_or_create(id, session)
|
108
|
+
cart_id = session[:cart_id]
|
109
|
+
if cart_id != nil
|
110
|
+
cart = where(:_id => cart_id).first
|
111
|
+
|
112
|
+
if cart == nil
|
113
|
+
session[:cart_id] = nil
|
114
|
+
return find_or_create(id, session)
|
115
|
+
end
|
116
|
+
|
117
|
+
return cart if id == nil
|
118
|
+
|
119
|
+
session[:cart_id] = nil
|
120
|
+
user_cart = Cart.for_user(id)
|
121
|
+
user_cart.merge(cart)
|
122
|
+
cart.destroy
|
123
|
+
return user_cart
|
124
|
+
end
|
125
|
+
|
126
|
+
return Cart.for_user(id) if id != nil
|
127
|
+
|
128
|
+
cart = create
|
129
|
+
cart.save!
|
130
|
+
session[:cart_id] = cart.id.to_s
|
131
|
+
return cart
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class CartDrop < ::Liquid::Drop
|
136
|
+
def initialize(source)
|
137
|
+
@source = source
|
138
|
+
end
|
139
|
+
|
140
|
+
def line_items
|
141
|
+
@source.orders
|
142
|
+
end
|
143
|
+
|
144
|
+
def id
|
145
|
+
@source.id.to_s
|
146
|
+
end
|
147
|
+
|
148
|
+
def extras
|
149
|
+
@source.extras
|
150
|
+
end
|
151
|
+
|
152
|
+
[:purchase_total, :estimated_tax, :subtotal_est_tax, :extras_total].each do |method|
|
153
|
+
define_method(method) {"%0.2f" % @source.send(method).round(2)}
|
154
|
+
end
|
155
|
+
|
156
|
+
delegate :valid_stock?, to: :@source
|
157
|
+
|
158
|
+
protected
|
159
|
+
attr_accessor :source
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|