locomotive_ecommerce_plugin 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +40 -0
  3. data/app/assets/javascripts/locomotive/ecommerce/application.js +15 -0
  4. data/app/assets/stylesheets/locomotive/ecommerce/application.css +13 -0
  5. data/app/assets/stylesheets/locomotive/ecommerce/flash_dance.alerts.bootstrap.css +107 -0
  6. data/app/controllers/locomotive/ecommerce/application_controller.rb +35 -0
  7. data/app/controllers/locomotive/ecommerce/cart_controller.rb +12 -0
  8. data/app/controllers/locomotive/ecommerce/order_controller.rb +18 -0
  9. data/app/controllers/locomotive/ecommerce/purchase_controller.rb +56 -0
  10. data/app/helpers/locomotive/ecommerce/ecommerce_cart_helper.rb +11 -0
  11. data/app/helpers/locomotive/ecommerce/ecommerce_helper.rb +25 -0
  12. data/app/helpers/locomotive/ecommerce/ecommerce_url_helper.rb +52 -0
  13. data/app/mailers/locomotive/ecommerce/purchase_mailer.rb +19 -0
  14. data/app/models/locomotive/ecommerce/cart.rb +162 -0
  15. data/app/models/locomotive/ecommerce/order.rb +100 -0
  16. data/app/models/locomotive/ecommerce/purchase.rb +148 -0
  17. data/app/views/flash_dance/_alert.html.erb +4 -0
  18. data/app/views/flash_dance/_error.html.erb +4 -0
  19. data/app/views/flash_dance/_info.html.erb +4 -0
  20. data/app/views/flash_dance/_notice.html.erb +4 -0
  21. data/app/views/flash_dance/_success.html.erb +4 -0
  22. data/app/views/flash_dance/_warning.html.erb +4 -0
  23. data/app/views/kaminari/_first_page.html.erb +11 -0
  24. data/app/views/kaminari/_gap.html.erb +8 -0
  25. data/app/views/kaminari/_last_page.html.erb +11 -0
  26. data/app/views/kaminari/_next_page.html.erb +11 -0
  27. data/app/views/kaminari/_page.html.erb +12 -0
  28. data/app/views/kaminari/_paginator.html.erb +23 -0
  29. data/app/views/kaminari/_prev_page.html.erb +11 -0
  30. data/app/views/locomotive/ecommerce/purchase_mailer/purchase_confirmation.text.erb +11 -0
  31. data/config/initializers/active_resource.rb +1 -0
  32. data/config/initializers/kaminari_config.rb +16 -0
  33. data/config/initializers/liquid_stack_trace.rb +7 -0
  34. data/config/initializers/stripe_setup.rb +40 -0
  35. data/config/routes.rb +14 -0
  36. data/lib/locomotive/ecommerce/plugin.rb +74 -0
  37. data/lib/locomotive/ecommerce/plugin/config.html +111 -0
  38. data/lib/locomotive/ecommerce/plugin/ecommerce_drop.rb +106 -0
  39. data/lib/locomotive/ecommerce/plugin/ecommerce_filters.rb +35 -0
  40. data/lib/locomotive/ecommerce/plugin/ecommerce_tags.rb +31 -0
  41. data/lib/locomotive/ecommerce/plugin/engine.rb +42 -0
  42. data/lib/locomotive/ecommerce/plugin/inventory_interface.rb +15 -0
  43. data/lib/locomotive/ecommerce/plugin/version.rb +5 -0
  44. data/lib/locomotive_ecommerce_plugin.rb +1 -0
  45. metadata +184 -0
@@ -0,0 +1,14 @@
1
+ Locomotive::Ecommerce::Engine.routes.draw do
2
+ resources :cart, :only => [:update]
3
+ resources :checkout, :controller => "purchase",
4
+ :only => [:create, :update]
5
+
6
+ match "add_to_cart/:product_id" => "order#create",
7
+ :via => :post, :as => "add_to_cart"
8
+ match "remove_from_cart/:product_id" => "order#destroy",
9
+ :via => :delete, :as => "remove_from_cart"
10
+ match "push_orders" => "purchase#push",
11
+ :via => :get, :as => "push_orders"
12
+
13
+ mount StripeHelper::Engine => "/"
14
+ end
@@ -0,0 +1,74 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'locomotive_plugins'
4
+ require "locomotive/ecommerce/plugin/engine"
5
+ require 'locomotive/ecommerce/plugin/ecommerce_drop'
6
+ require 'locomotive/ecommerce/plugin/ecommerce_tags'
7
+ require 'locomotive/ecommerce/plugin/ecommerce_filters'
8
+ require 'locomotive/ecommerce/plugin/inventory_interface'
9
+ require 'cells'
10
+ require 'kaminari'
11
+ require 'stripe_helper'
12
+
13
+ module Locomotive
14
+ module Ecommerce
15
+ class PluginHelper
16
+ end
17
+
18
+ class Plugin
19
+ include Locomotive::Plugin
20
+ include ::Locomotive::Ecommerce::InventoryInterface
21
+
22
+ before_page_render :set_config
23
+
24
+ def self.default_plugin_id
25
+ 'ecommerce'
26
+ end
27
+
28
+ def self.rack_app
29
+ Engine
30
+ end
31
+
32
+ def config_template_file
33
+ File.join(File.dirname(__FILE__), 'plugin', 'config.html')
34
+ end
35
+
36
+ def to_liquid
37
+ @drop ||= EcommerceDrop.new(self)
38
+ end
39
+
40
+ def self.liquid_tags
41
+ {
42
+ stripe: StripeTag
43
+ }
44
+ end
45
+
46
+ def self.liquid_filters
47
+ EcommerceFilters
48
+ end
49
+
50
+ def helper
51
+ if !@helper
52
+ @helper = PluginHelper.new
53
+ @helper.instance_eval { extend EcommerceHelper }
54
+ end
55
+ return @helper
56
+ end
57
+
58
+ def path
59
+ rack_app_full_path('/')
60
+ end
61
+
62
+
63
+ private
64
+ def set_config
65
+ mounted_rack_app.config_hash = config
66
+
67
+ ::Stripe.api_key = mounted_rack_app.config_or_default('stripe_secret')
68
+ ::StripeHelper.configure do |config|
69
+ config.public_key = mounted_rack_app.config_or_default('stripe_public')
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,111 @@
1
+ <li>
2
+ <label name="stripe_secret">Stripe Secret Key:</label>
3
+ <input type="text" name="stripe_secret" />
4
+ </li>
5
+ <li>
6
+ <label name="stripe_public">Stripe Public Key:</label>
7
+ <input type="text" name="stripe_public" />
8
+ </li>
9
+ <li>
10
+ <label name="cart_url">Cart URL:</label>
11
+ <input type="text" name="cart_url" />
12
+ </li>
13
+
14
+ <li>
15
+ <label name="checkout_url">Checkout URL:</label>
16
+ <input type="text" name="checkout_url" />
17
+ </li>
18
+
19
+ <li>
20
+ <label name="new_checkout_url">Post Checkout URL:</label>
21
+ <input type="text" name="post_checkout_url" />
22
+ </li>
23
+ <li>
24
+ <label name="purchases_url">Purchases URL:</label>
25
+ <input type="text" name="purchases_url" />
26
+ </li>
27
+ <li>
28
+ <label name="with_quantity">Only in Stock Items:</label>
29
+ <input type="checkbox" name="with_quantity" />
30
+ </li>
31
+ <li>
32
+ <label name="purchases_url">Estimated Tax Rate (in percent):</label>
33
+ <input type="text" name="estimated_tax_rate" />
34
+ <p class="inline-hints">Default: 15</p>
35
+ </li>
36
+ <li>
37
+ <label name="tax_model">Tax Model:</label>
38
+ <select name="tax_model">
39
+ {{#each content_types}}
40
+ <option value="{{ this.slug }}">{{ this.name }}</option>
41
+ {{/each}}
42
+ </select>
43
+ <p class="inline-hints">Slug of the model recording tax rates.</p>
44
+ </li>
45
+ <li>
46
+ <label name="country_slug">Country Code Slug:</label>
47
+ <input type="text" name="country_slug" />
48
+ </li>
49
+ <li>
50
+ <label name="province_slug">Province/State Code Slug:</label>
51
+ <input type="text" name="province_slug" />
52
+ </li>
53
+ <li>
54
+ <label name="precentage_slug">Precentage Slug:</label>
55
+ <input type="text" name="precentage_slug" />
56
+ </li>
57
+ <li>
58
+ <label name="shipping_model">Shipping Model:</label>
59
+ <select name="shipping_model">
60
+ {{#each content_types}}
61
+ <option value="{{ this.slug }}">{{ this.name }}</option>
62
+ {{/each}}
63
+ </select>
64
+ <p class="inline-hints">Slug of the model recording shipping rates.</p>
65
+ </li>
66
+ <li>
67
+ <label name="shipping_name_slug">Name Slug:</label>
68
+ <input type="text" name="shipping_name_slug" />
69
+ <p class="inline-hints">Default: name</p>
70
+ </li>
71
+ <li>
72
+ <label name="shipping_over_slug">Over Price Break Slug:</label>
73
+ <input type="text" name="shipping_over_slug" />
74
+ <p class="inline-hints">Default: over</p>
75
+ </li>
76
+ <li>
77
+ <label name="shipping_under_slug">Under Price Break Slug:</label>
78
+ <input type="text" name="shipping_under_slug" />
79
+ <p class="inline-hints">Default: under</p>
80
+ </li>
81
+ <li>
82
+ <label name="price_break">Price Break</label>
83
+ <input type="text" name="price_break" />
84
+ <p class="inline-hints">Default: 100</p>
85
+ </li>
86
+ <li>
87
+ <label name="edit_extra">Apply extras</label>
88
+ <textarea type="text" style="height=400px" name="edit_extra" />
89
+ <p class="inline-hints">Use Javascript to integrate extra charges to total price.</p>
90
+ </li>
91
+ <li>
92
+ <label name="shop_name">Shop Name</label>
93
+ <input type="text" name="shop_name" />
94
+ </li>
95
+ <li>
96
+ <label name="remote_order">After Purchase Complete JS3</label>
97
+ <textarea style="height=400px" type="text" name="after_purchase_hook" />
98
+ <p class="inline-hints">JS3 that will be run after a purchase has been completer</p>
99
+ </li>
100
+ <li>
101
+ <label name="shop_inventory_update">Shop Inventory Items</label>
102
+ <input type="text" name="shop_inventory_update" />
103
+ </li>
104
+ <li>
105
+ <label name="shop_inventory_items">Shop Inventory Items Class</label>
106
+ <input type="text" name="shop_inventory_items" />
107
+ </li>
108
+ <li>
109
+ <label name="contact">Contact</label>
110
+ <input type="text" name="contact" />
111
+ </li>
@@ -0,0 +1,106 @@
1
+ module Locomotive
2
+ module Ecommerce
3
+ class EcommerceDrop < ::Liquid::Drop
4
+ def initialize(source)
5
+ @source = source
6
+ urls = ['cart_url', 'checkout_url', 'new_checkout_url', 'product_url',
7
+ 'products_url', 'purchases_url']
8
+ urls.each do |name|
9
+ self.class.send(:define_method, name) do
10
+ source.mounted_rack_app.config_or_default(name)
11
+ end
12
+ end
13
+ end
14
+
15
+ def products
16
+ search_filter(source.inventory_items)
17
+ end
18
+
19
+ def show_out_of_stock?
20
+ !!Engine.config_or_default('with_quantity')
21
+ end
22
+
23
+ def cart
24
+ unless @cart
25
+ session = @context.registers[:controller].session
26
+ site = Thread.current[:site]
27
+ user_from_plugin = site.plugin_object_for_id('identity_plugin').js3_context['identity_plugin_users']
28
+ user = user_from_plugin.where(id: session[:user_id]).first
29
+ id = user == nil ? nil : user.id
30
+ @cart = Cart.find_or_create(id, session)
31
+ end
32
+ @cart
33
+ end
34
+
35
+ def purchase
36
+ unless @purchase
37
+ session = @context.registers[:controller].session
38
+ site = Thread.current[:site]
39
+ user_from_plugin = site.plugin_object_for_id('identity_plugin').js3_context['identity_plugin_users']
40
+ user = user_from_plugin.where(id: session[:user_id]).first
41
+ puts "Count in Drop 1: #{Purchase.count}"
42
+ @purchase = cart.purchase || Purchase.new
43
+ cart.purchase = @purchase
44
+ cart.save!
45
+ @purchase.save!
46
+ puts "Count in Drop 2: #{Purchase.count}"
47
+ end
48
+ @purchase
49
+ end
50
+
51
+ def purchases
52
+ session = @context.registers[:controller].session
53
+ site = Thread.current[:site]
54
+ user_from_plugin = site.plugin_object_for_id('identity_plugin').js3_context['identity_plugin_users']
55
+ user = user_from_plugin.where(id: session[:user_id]).first
56
+ Purchase.where(user_id: user.id).all.to_a
57
+ end
58
+
59
+ protected
60
+ attr_reader :source
61
+
62
+ def search_filter(products)
63
+ params = @context['params']
64
+ whitelist = {
65
+ 'sku' => :sku,
66
+ 'product' => :description,
67
+ 'price' => :price,
68
+ 'quantity' => :quantity,
69
+ 'vendor' => :vendor,
70
+ 'group' => :group,
71
+ 'dcs' => :category
72
+ }
73
+
74
+ params.each do |k,v|
75
+ k_split = k.split('_')
76
+ last = k_split.size > 1 ? k_split.delete_at(-1) : nil
77
+ first = k_split.join('_')
78
+ next if !whitelist.key? first
79
+ field = whitelist[first].to_sym
80
+ if last == nil
81
+ if field == :category
82
+ v.split(' ').each do |value|
83
+ regex = /^#{Regexp.escape(value)}.*/i
84
+ products = products.or(category: regex)
85
+ end
86
+ else
87
+ regex = /#{Regexp.escape(v)}/i
88
+ products = products.and(field => regex)
89
+ end
90
+ elsif last == 'min'
91
+ products = products.and(field.gt => v)
92
+ elsif last == 'max'
93
+ products = products.and(field.lt => v)
94
+ elsif last == 'sort'
95
+ if v == 'asc'
96
+ products = products.asc(field)
97
+ elsif v == 'desc'
98
+ products = products.desc(field)
99
+ end
100
+ end
101
+ end
102
+ products
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,35 @@
1
+ module Locomotive
2
+ module Ecommerce
3
+ module EcommerceFilters
4
+
5
+ def cart_update_path(cart)
6
+ stem = @context.registers[:plugin_object].path
7
+ "#{stem}cart/#{cart.id}"
8
+ end
9
+
10
+ def add_to_cart_path(product)
11
+ stem = @context.registers[:plugin_object].path
12
+ "#{stem}add_to_cart/#{product.id}"
13
+ end
14
+
15
+ def remove_from_cart_path(product_sku)
16
+ stem = @context.registers[:plugin_object].path
17
+ "#{stem}remove_from_cart/#{product_sku}"
18
+ end
19
+
20
+ def checkout_path(purchase)
21
+ stem = @context.registers[:plugin_object].path
22
+ "#{stem}checkout"
23
+ end
24
+
25
+ def checkout_update_path(purchase)
26
+ stem = @context.registers[:plugin_object].path
27
+ "#{stem}checkout/#{purchase.id}"
28
+ end
29
+
30
+ def find_purchase(id)
31
+ Purchase.find(id.to_s)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ module Locomotive
2
+ module Ecommerce
3
+ module EcommerceTagHelper
4
+ def render(context)
5
+ @plugin_obj = context.registers[:plugin_object]
6
+ end
7
+ end
8
+
9
+ class StripeTag < ::Liquid::Tag
10
+ include EcommerceTagHelper
11
+ def render(context)
12
+ super
13
+ session = context.registers[:controller].session
14
+ site = Thread.current[:site]
15
+ user_from_plugin = site.plugin_object_for_id('identity_plugin').js3_context['identity_plugin_users']
16
+ user = user_from_plugin.find(session[:user_id])
17
+ # user = IdentityPlugin::User.find(session[:user_id])
18
+ id = user == nil ? nil : user.id
19
+ cart = Cart.find_or_create(id, session)
20
+ @purchase = cart.purchase
21
+ context.registers[:controller].render_cell 'stripe_helper/stripe', :show,
22
+ amount: (@purchase.total.round(2) * 100).to_i,
23
+ desc: Date.today,
24
+ pk: StripeHelper.config.public_key,
25
+ stem: @plugin_obj.path,
26
+ store: Engine.config_or_default('shop_name'),
27
+ token: @purchase.id
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ #require 'omniauth-identity'
2
+
3
+ module Locomotive
4
+ module Ecommerce
5
+ class Engine < ::Rails::Engine
6
+ # would this change to Locomotive::Ecommerce?
7
+ isolate_namespace Ecommerce
8
+
9
+ def self.config_hash=(hash)
10
+ @config_hash = hash
11
+ end
12
+
13
+ def self.config_hash
14
+ @config_hash ||= {}
15
+ end
16
+
17
+ def self.config_or_default(key)
18
+ defaults = {
19
+ 'cart_url' => '/cart',
20
+ 'checkout_url' => '/checkout',
21
+ 'post_checkout_url' => '/complete',
22
+ 'confirm_order_url' => '/confirm',
23
+ 'purchases_url' => '/purchases',
24
+ 'estimated_tax_rate' => '15',
25
+ 'country_slug' => 'country',
26
+ 'province_slug' => 'province',
27
+ 'precentage_slug' => 'precentage',
28
+ 'shipping_name_slug' => 'name',
29
+ 'shipping_over_slug' => 'over',
30
+ 'shipping_under_slug' => 'under',
31
+ 'price_break' => '100',
32
+ 'edit_extra' => 'add extras through JS',
33
+ 'shop_name' => "<insert name>",
34
+ 'shop_inventory' => "inventory_itemsUpdate",
35
+ 'contact' => "fake@email.com"
36
+ }
37
+ hash = defaults.merge(config_hash)
38
+ hash[key]
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,15 @@
1
+ module Locomotive
2
+ module Ecommerce
3
+ module InventoryInterface
4
+ # Inventory
5
+ def inventory_items
6
+ site = Thread.current[:site]
7
+ site.plugin_object_for_id('inventory').js3_context.eval(Engine.config_or_default('shop_inventory_update'))
8
+ end
9
+ def inventory_items_class
10
+ site = Thread.current[:site]
11
+ site.plugin_object_for_id('inventory').js3_context.eval(Engine.config_or_default('shop_inventory_items'))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ module Locomotive
2
+ module Ecommerce
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require 'locomotive/ecommerce/plugin'