camaleon_ecommerce 1.1 → 1.2

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/plugins/ecommerce/admin_product.js.coffee +83 -0
  3. data/app/assets/javascripts/plugins/ecommerce/cart.js +3 -0
  4. data/app/controllers/plugins/ecommerce/admin/coupons_controller.rb +6 -12
  5. data/app/controllers/plugins/ecommerce/admin/orders_controller.rb +2 -8
  6. data/app/controllers/plugins/ecommerce/admin/payment_methods_controller.rb +7 -12
  7. data/app/controllers/plugins/ecommerce/admin/prices_controller.rb +0 -8
  8. data/app/controllers/plugins/ecommerce/admin/settings_controller.rb +0 -8
  9. data/app/controllers/plugins/ecommerce/admin/shipping_methods_controller.rb +6 -14
  10. data/app/controllers/plugins/ecommerce/admin/tax_rates_controller.rb +6 -12
  11. data/app/controllers/plugins/ecommerce/admin_controller.rb +27 -8
  12. data/app/controllers/plugins/ecommerce/front/checkout_controller.rb +42 -75
  13. data/app/controllers/plugins/ecommerce/front/orders_controller.rb +2 -10
  14. data/app/controllers/plugins/ecommerce/front_controller.rb +0 -8
  15. data/app/decorators/plugins/ecommerce/coupon_decorator.rb +0 -8
  16. data/app/decorators/plugins/ecommerce/product_decorator.rb +86 -35
  17. data/app/decorators/plugins/ecommerce/product_item_decorator.rb +27 -3
  18. data/app/decorators/plugins/ecommerce/product_variation_decorator.rb +18 -0
  19. data/app/helpers/plugins/ecommerce/ecommerce_email_helper.rb +11 -13
  20. data/app/helpers/plugins/ecommerce/ecommerce_functions_helper.rb +25 -11
  21. data/app/helpers/plugins/ecommerce/ecommerce_helper.rb +22 -27
  22. data/app/helpers/plugins/ecommerce/ecommerce_payment_helper.rb +1 -56
  23. data/app/models/plugins/ecommerce/attribute.rb +9 -0
  24. data/app/models/plugins/ecommerce/cart.rb +46 -28
  25. data/app/models/plugins/ecommerce/coupon.rb +0 -8
  26. data/app/models/plugins/ecommerce/legacy_cart.rb +50 -0
  27. data/app/models/plugins/ecommerce/legacy_order.rb +48 -0
  28. data/app/models/plugins/ecommerce/order.rb +0 -8
  29. data/app/models/plugins/ecommerce/order_detail.rb +0 -9
  30. data/app/models/plugins/ecommerce/payment_method.rb +0 -8
  31. data/app/models/plugins/ecommerce/product_item.rb +3 -10
  32. data/app/models/plugins/ecommerce/product_variation.rb +9 -0
  33. data/app/models/plugins/ecommerce/shipping_method.rb +0 -8
  34. data/app/models/plugins/ecommerce/tax_rate.rb +0 -8
  35. data/app/services/plugins/ecommerce/cart_service.rb +149 -0
  36. data/app/services/plugins/ecommerce/order_service.rb +26 -0
  37. data/app/services/plugins/ecommerce/product_item_service.rb +29 -0
  38. data/app/services/plugins/ecommerce/product_service.rb +17 -0
  39. data/app/services/plugins/ecommerce/site_service.rb +21 -0
  40. data/app/services/plugins/ecommerce/user_cart_service.rb +12 -0
  41. data/app/services/plugins/ecommerce/user_product_service.rb +29 -0
  42. data/app/services/plugins/ecommerce/util_service.rb +5 -0
  43. data/app/views/plugins/ecommerce/admin/orders/form.html.erb +28 -16
  44. data/app/views/plugins/ecommerce/admin/orders/index.html.erb +7 -1
  45. data/app/views/plugins/ecommerce/admin/payment_methods/form.html.erb +11 -1
  46. data/app/views/plugins/ecommerce/admin/product_attributes.html.erb +95 -0
  47. data/app/views/plugins/ecommerce/admin/products/_variations.html.erb +72 -0
  48. data/app/views/plugins/ecommerce/front/checkout/cart_index.html.erb +5 -5
  49. data/app/views/plugins/ecommerce/front/orders/show.html.erb +96 -89
  50. data/app/views/plugins/ecommerce/partials/_cart_widget.html.erb +3 -3
  51. data/app/views/plugins/ecommerce/partials/checkout/_details.html.erb +1 -1
  52. data/app/views/plugins/ecommerce/partials/checkout/_payments.html.erb +6 -1
  53. data/app/views/plugins/ecommerce/partials/checkout/_products_detail.html.erb +1 -1
  54. data/app/views/plugins/ecommerce/partials/checkout/_user_info.html.erb +26 -22
  55. data/app/views/post_types/commerce/single.html.erb +28 -12
  56. data/config/camaleon_plugin.json +4 -12
  57. data/config/custom_models.rb +10 -0
  58. data/config/locales/en.yml +3 -0
  59. data/config/locales/es.yml +112 -54
  60. data/config/routes.rb +2 -0
  61. data/db/migrate/20160527184747_add_new_cart_structure.rb +7 -4
  62. data/db/migrate/20160620200501_add_product_attributes_structure.rb +21 -0
  63. data/db/migrate/20160825174848_set_cama_post_decorator_class.rb +13 -0
  64. data/db/migrate/20160825232739_migrate_order_data.rb +87 -0
  65. data/lib/ecommerce/version.rb +1 -1
  66. metadata +22 -7
  67. data/app/assets/javascripts/plugins/ecommerce/admin.js +0 -0
  68. data/app/assets/javascripts/plugins/ecommerce/fix_form.js +0 -7
  69. data/config/currency_en.json +0 -154
  70. data/config/currency_es.json +0 -154
@@ -1,61 +1,6 @@
1
1
  module Plugins::Ecommerce::EcommercePaymentHelper
2
- include Plugins::Ecommerce::EcommerceHelper
3
-
4
- def payment_pay_by_credit_card_authorize_net(order, payment_method)
5
- billing_address = order.get_meta("billing_address")
6
- details = order.get_meta("details")
7
- amount = commerce_to_cents(order.total_amount)
8
- payment_params = {
9
- :order_id => order.slug,
10
- :currency => current_site.currency_code,
11
- :email => order.user.email,
12
- :billing_address => {:name => "#{order.user.fullname}",
13
- :address1 => billing_address[:address1],
14
- :address2 => billing_address[:address2],
15
- :city => billing_address[:city],
16
- :state => billing_address[:state],
17
- :country => billing_address[:country],
18
- :zip => billing_address[:zip]
19
- },
20
- :description => 'Buy Products',
21
- :ip => request.remote_ip
22
- }
23
-
24
- authorize_net_options = {
25
- :login => payment_method.options[:authorize_net_login_id],
26
- :password => payment_method.options[:authorize_net_transaction_key]
27
- }
28
-
29
- ActiveMerchant::Billing::Base.mode = payment_method.options[:authorize_net_sandbox].to_s.to_bool ? :test : :production
30
-
31
- credit_card = ActiveMerchant::Billing::CreditCard.new(
32
- :first_name => params[:firstName],
33
- :last_name => params[:lastName],
34
- :number => params[:cardNumber],
35
- :month => params[:expMonth],
36
- :year => "20#{params[:expYear]}",
37
- :verification_value => params[:cvCode]
38
- )
39
- if credit_card.validate.empty?
40
- gateway = ActiveMerchant::Billing::AuthorizeNetGateway.new(authorize_net_options)
41
- response = gateway.purchase(amount, credit_card, payment_params)
42
- if response.success?
43
- order.set_meta('pay_authorize_net', payment_params)
44
- return {}
45
- else
46
- return {error: response.message}
47
- end
48
- else
49
- return {error: credit_card.validate.map{|k, v| "#{k}: #{v.join(', ')}"}.join('<br>')}
50
- end
51
- end
52
-
53
2
  def commerce_to_cents(money)
54
- (money*100).round
55
- end
56
-
57
- def commerce_current_currency
58
- current_site.get_meta("_setting_ecommerce", {})[:current_unit] || 'USD'
3
+ Plugins::Ecommerce::UtilService.ecommerce_money_to_cents(money)
59
4
  end
60
5
 
61
6
  end
@@ -0,0 +1,9 @@
1
+ class Plugins::Ecommerce::Attribute < ActiveRecord::Base
2
+ self.table_name='plugins_ecommerce_attributes'
3
+ belongs_to :site
4
+ has_many :values, class_name: 'Plugins::Ecommerce::Attribute', foreign_key: :parent_id, dependent: :destroy
5
+ belongs_to :product_attribute, class_name: 'Plugins::Ecommerce::Attribute', foreign_key: :parent_id
6
+ scope :only_group, ->{ where(parent_id: nil) }
7
+ scope :only_value, ->{ where.not(parent_id: nil) }
8
+ default_scope ->{ order(position: :ASC) }
9
+ end
@@ -1,11 +1,3 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::Cart < ActiveRecord::Base
10
2
  self.table_name = 'plugins_ecommerce_orders'
11
3
  default_scope { where(kind: 'cart') }
@@ -16,25 +8,23 @@ class Plugins::Ecommerce::Cart < ActiveRecord::Base
16
8
 
17
9
  belongs_to :site, :class_name => "CamaleonCms::Site", foreign_key: :site_id
18
10
  belongs_to :user, :class_name => "CamaleonCms::User", foreign_key: :user_id
11
+ scope :active_cart, ->{ where("#{Plugins::Ecommerce::Cart.table_name}.updated_at >= ?", 24.hours.ago) }
12
+
19
13
  after_create :generate_slug
20
14
 
21
- def add_product(product, qty = 1)
22
- pi = product_items.where(product_id: product.id).first
15
+ def add_product(product, qty = 1, variation_id = nil)
16
+ pi = product_items.where(product_id: product.id, variation_id: variation_id).first
23
17
  if pi.present?
24
18
  pi.update_column(:qty, qty)
25
19
  else
26
- pi = product_items.create(product_id: product.id, qty: qty)
20
+ pi = product_items.create(product_id: product.id, qty: qty, variation_id: variation_id)
27
21
  end
28
22
  pi
29
23
  end
30
24
 
31
- def remove_product(product_id)
32
- product_items.where(product_id: product_id).destroy_all
33
- end
34
-
35
25
  # return the product titles in array format
36
26
  def products_title
37
- products.decorate.each{|p| p.the_title }.join(', ')
27
+ product_items.map{|i| p=i.product.decorate; p.the_variation_title(i.variation_id) }.join(', ')
38
28
  end
39
29
 
40
30
  def items_total
@@ -43,16 +33,15 @@ class Plugins::Ecommerce::Cart < ActiveRecord::Base
43
33
 
44
34
  # price of all products (no include taxes)
45
35
  def sub_total
46
- # product_items.map{|item| product = item.product.decorate; (product.price + product.tax) * item.qty }.inject{|sum,x| sum + x } || 0
47
- product_items.map{|item| product = item.product.decorate; (product.price) * item.qty }.inject{|sum,x| sum + x } || 0
36
+ product_items.map{|item| product = item.product.decorate; (product.price(item.variation_id)) * item.qty }.inject{|sum,x| sum + x } || 0
48
37
  end
49
38
 
50
39
  def tax_total
51
- product_items.map{|item| product = item.product.decorate; (product.tax) * item.qty }.inject{|sum,x| sum + x } || 0
40
+ product_items.map{|item| product = item.product.decorate; (product.tax(item.variation_id)) * item.qty }.inject{|sum,x| sum + x } || 0
52
41
  end
53
42
 
54
43
  def weight_total
55
- product_items.map{|item| product = item.product.decorate; (product.weight) * item.qty }.inject{|sum,x| sum + x } || 0
44
+ product_items.map{|item| product = item.product.decorate; (product.weight(item.variation_id)) * item.qty }.inject{|sum,x| sum + x } || 0
56
45
  end
57
46
 
58
47
  # verify an return {error: (error code), discount: amount of discount} coupon for current cart
@@ -72,8 +61,10 @@ class Plugins::Ecommerce::Cart < ActiveRecord::Base
72
61
  res[:error] = 'required_minimum_price'
73
62
  else
74
63
  case opts[:discount_type]
75
- when 'free_ship'
64
+ when 'free'
76
65
  res[:discount] = price || sub_total
66
+ when 'free_ship'
67
+ res[:discount] = total_shipping
77
68
  when 'percent'
78
69
  res[:discount] = sub_total * opts[:amount].to_f / 100
79
70
  when 'money'
@@ -86,8 +77,17 @@ class Plugins::Ecommerce::Cart < ActiveRecord::Base
86
77
  res
87
78
  end
88
79
 
80
+ def prepare_to_pay
81
+ self.class.transaction do
82
+ self.update_columns(
83
+ status: 'qtys_taken',
84
+ )
85
+ self.product_items.decorate.each{|p_item| p_item.decrement_qty! }
86
+ end
87
+ end
88
+
89
89
  # convert into order current cart
90
- def make_order!
90
+ def convert_to_order
91
91
  self.update_columns(kind: 'order', created_at: Time.current)
92
92
  site.orders.find(self.id)
93
93
  end
@@ -137,23 +137,41 @@ class Plugins::Ecommerce::Cart < ActiveRecord::Base
137
137
  total_amount <= 0
138
138
  end
139
139
 
140
- # return order object
141
- def make_paid!(status = 'paid')
140
+ def update_amounts
142
141
  product_items.decorate.each do |item|
143
142
  p = item.product.decorate
144
- item.update_columns(cache_the_price: item.the_price, cache_the_title: p.the_title, cache_the_tax: p.the_tax, cache_the_sub_total: item.the_sub_total)
143
+ item.update_columns(
144
+ cache_the_price: p.the_price(item.variation_id),
145
+ cache_the_title: p.the_variation_title(item.variation_id),
146
+ cache_the_tax: p.the_tax(item.variation_id),
147
+ cache_the_sub_total: item.the_sub_total,
148
+ )
145
149
  end
146
150
 
147
151
  if self.coupon.present?
148
152
  res_coupon = self.discount_for(self.coupon, total_to_pay_without_discounts)
149
153
  unless res_coupon[:error].present?
150
- update_columns(the_coupon_amount: res_coupon[:coupon].decorate.the_amount, coupon_amount: res_coupon[:discount])
154
+ update_columns(the_coupon_amount: res_coupon[:coupon].decorate.the_amount)
151
155
  res_coupon[:coupon].mark_as_used(user)
152
156
  end
153
157
  end
154
158
  c = self.decorate
155
- self.update_columns(status: status, paid_at: Time.current, amount: total_amount, cache_the_total: c.the_price, cache_the_sub_total: c.the_sub_total, cache_the_tax: c.the_tax_total, cache_the_weight: c.the_weight_total, cache_the_discounts: c.the_total_discounts, cache_the_shipping: c.the_total_shipping)
156
- make_order!
159
+ self.update_columns(
160
+ amount: total_amount,
161
+ cache_the_total: c.the_price,
162
+ cache_the_sub_total: c.the_sub_total,
163
+ cache_the_tax: c.the_tax_total,
164
+ cache_the_weight: c.the_weight_total,
165
+ cache_the_discounts: c.the_total_discounts,
166
+ cache_the_shipping: c.the_total_shipping,
167
+ )
168
+ end
169
+
170
+ def mark_paid(status = 'paid')
171
+ self.update_columns(
172
+ status: status,
173
+ paid_at: Time.current,
174
+ )
157
175
  end
158
176
 
159
177
 
@@ -1,11 +1,3 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::Coupon < CamaleonCms::TermTaxonomy
10
2
  default_scope { where(taxonomy: :ecommerce_coupon) }
11
3
  belongs_to :site, :class_name => "CamaleonCms::Site", foreign_key: :parent_id
@@ -0,0 +1,50 @@
1
+ class Plugins::Ecommerce::LegacyCart < CamaleonCms::TermTaxonomy
2
+ default_scope { where(taxonomy: :ecommerce_cart) }
3
+ has_many :products, foreign_key: :objectid, through: :term_relationships, :source => :objects
4
+ belongs_to :site, :class_name => "CamaleonCms::Site", foreign_key: :parent_id
5
+
6
+ def add_product(object)
7
+ post_id = defined?(object.id) ? object.id : object.to_i
8
+ term_relationships.where(objectid: post_id).first_or_create if post_id > 0
9
+ end
10
+
11
+ # update or set product quantity
12
+ # return true if it is possible to add the quantity
13
+ # return false if quantity is not enough
14
+ def set_product_qty(product, qty)
15
+ _options = self.get_option("product_#{product.id}")
16
+ if qty.to_f <= product.the_qty_real.to_f
17
+ _options['qty'] = qty
18
+ self.set_option("product_#{product.id}", _options)
19
+ true
20
+ else
21
+ false
22
+ end
23
+ end
24
+
25
+ def remove_product(object)
26
+ post_id = defined?(object.id) ? object.id : object.to_i
27
+ term_relationships.where(objectid: post_id).destroy_all if post_id > 0
28
+ end
29
+
30
+ def the_items_count
31
+ options.map{|k, p| p[:qty].to_i}.inject{|sum,x| sum + x } || 0 rescue 0
32
+ end
33
+
34
+ def the_amount_total
35
+ options.map{|k, p| (p[:price].to_f + p[:tax])* p[:qty].to_f}.inject{|sum,x| sum + x } || 0 rescue 0
36
+ end
37
+
38
+ # return the price of current cart ($10)
39
+ def the_price
40
+ "#{self.site.decorate.current_unit}#{sprintf('%.2f', the_amount_total)}"
41
+ end
42
+
43
+ # set user in filter
44
+ def self.set_user(user)
45
+ user_id = defined?(user.id) ? user.id : user.to_i
46
+ self.where(user_id: user_id)
47
+ end
48
+
49
+
50
+ end
@@ -0,0 +1,48 @@
1
+ class Plugins::Ecommerce::LegacyOrder < CamaleonCms::TermTaxonomy
2
+ default_scope { where(taxonomy: :ecommerce_order) }
3
+ has_one :details, class_name: "Plugins::Ecommerce::OrderDetail", foreign_key: :order_id, dependent: :destroy
4
+ has_many :products, foreign_key: :objectid, through: :term_relationships, :source => :objects
5
+ belongs_to :customer, class_name: "CamaleonCms::User", foreign_key: :user_id
6
+
7
+ def add_product(object)
8
+ post_id = defined?(object.id) ? object.id : object.to_i
9
+ term_relationships.where(objectid: post_id).first_or_create if post_id > 0
10
+ end
11
+ def remove_product(object)
12
+ post_id = defined?(object.id) ? object.id : object.to_i
13
+ term_relationships.where(objectid: post_id).destroy_all if post_id > 0
14
+ end
15
+
16
+ def payment_method
17
+ Plugins::Ecommerce::PaymentMethod.find_by_id get_meta("payment")[:payment_id]
18
+ end
19
+
20
+ def payment
21
+ payment = get_meta("payment")
22
+ get_meta("pay_#{payment[:type]}".to_sym)
23
+ end
24
+
25
+ def shipping_method
26
+ Plugins::Ecommerce::ShippingMethod.find_by_id get_meta("payment", {})[:shipping_method]
27
+ end
28
+
29
+ def canceled?
30
+ status == 'canceled'
31
+ end
32
+ def unpaid?
33
+ status == 'unpaid'
34
+ end
35
+
36
+ def paid?
37
+ payment.present?
38
+ end
39
+
40
+
41
+ # set user in filter
42
+ def self.set_user(user)
43
+ user_id = defined?(user.id) ? user.id : user.to_i
44
+ self.where(user_id: user_id)
45
+ end
46
+
47
+
48
+ end
@@ -1,11 +1,3 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::Order < Plugins::Ecommerce::Cart
10
2
  self.table_name = 'plugins_ecommerce_orders'
11
3
  has_many :metas, ->{ where(object_class: 'Plugins::Ecommerce::Cart')}, :class_name => "CamaleonCms::Meta", foreign_key: :objectid, dependent: :delete_all
@@ -1,13 +1,4 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::OrderDetail < ActiveRecord::Base
10
2
  self.table_name = "plugins_order_details"
11
- attr_accessible :order_id, :customer, :email, :phone, :status, :received_at, :accepted_at, :shipped_at, :closed_at
12
3
  belongs_to :order, class_name: "Plugins::Ecommerce::Order", foreign_key: :order_id
13
4
  end
@@ -1,11 +1,3 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::PaymentMethod < CamaleonCms::TermTaxonomy
10
2
  default_scope { where(taxonomy: :ecommerce_payment_method) }
11
3
  belongs_to :site, :class_name => "CamaleonCms::Site", foreign_key: :parent_id
@@ -1,20 +1,13 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::ProductItem < ActiveRecord::Base
10
2
  include CamaleonCms::Metas
11
3
  self.table_name = 'plugins_ecommerce_products'
12
- belongs_to :cart, class_name: 'Plugins::Ecommerce::Cart', foreign_key: :order_id
4
+ belongs_to :cart, class_name: 'Plugins::Ecommerce::Cart', foreign_key: :order_id, touch: true
13
5
  belongs_to :order, class_name: 'Plugins::Ecommerce::Order'
14
6
  belongs_to :product, foreign_key: :product_id, class_name: 'CamaleonCms::Post'
7
+ belongs_to :product_variation, class_name: 'Plugins::Ecommerce::ProductVariation', foreign_key: :variation_id
15
8
 
16
9
  def sub_total
17
10
  p = self.product.decorate
18
- (p.price + p.tax) * self.qty
11
+ (p.price(self.variation_id) + p.tax(self.variation_id)) * self.qty
19
12
  end
20
13
  end
@@ -0,0 +1,9 @@
1
+ class Plugins::Ecommerce::ProductVariation < ActiveRecord::Base
2
+ self.table_name='plugins_ecommerce_product_variations'
3
+ belongs_to :product, class_name: "CamaleonCms::Post"
4
+
5
+ # return all attribute values assigned to this product
6
+ def attribute_values
7
+ Plugins::Ecommerce::Attribute.only_value.where(id: self.attribute_ids.to_s.split(','))
8
+ end
9
+ end
@@ -1,11 +1,3 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::ShippingMethod < CamaleonCms::TermTaxonomy
10
2
  default_scope { where(taxonomy: :ecommerce_shipping_method) }
11
3
  belongs_to :site, :class_name => "CamaleonCms::Site", foreign_key: :parent_id
@@ -1,11 +1,3 @@
1
- =begin
2
- Camaleon CMS is a content management system
3
- Copyright (C) 2015 by Owen Peredo Diaz
4
- Email: owenperedo@gmail.com
5
- This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
6
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
- See the GNU Affero General Public License (GPLv3) for more details.
8
- =end
9
1
  class Plugins::Ecommerce::TaxRate < CamaleonCms::TermTaxonomy
10
2
  default_scope { where(taxonomy: :ecommerce_tax_rate) }
11
3
  belongs_to :site, :class_name => "CamaleonCms::Site", foreign_key: :parent_id
@@ -0,0 +1,149 @@
1
+ class Plugins::Ecommerce::CartService
2
+ def initialize(site, cart)
3
+ @site = site
4
+ @cart = cart
5
+ end
6
+
7
+ attr_reader :site, :cart
8
+
9
+ def pay_with_authorize_net(options={})
10
+ payment_method = options[:payment_method] || site_service.payment_method('authorize_net')
11
+ billing_address = cart.get_meta("billing_address")
12
+ details = cart.get_meta("details")
13
+ amount = Plugins::Ecommerce::UtilService.ecommerce_money_to_cents(cart.total_amount)
14
+ payment_params = {
15
+ order_id: cart.slug,
16
+ currency: site.currency_code,
17
+ email: cart.user.email,
18
+ billing_address: {name: "#{cart.user.fullname}",
19
+ address1: billing_address[:address1],
20
+ address2: billing_address[:address2],
21
+ city: billing_address[:city],
22
+ state: billing_address[:state],
23
+ country: billing_address[:country],
24
+ zip: billing_address[:zip]
25
+ },
26
+ description: 'Buy Products',
27
+ ip: options[:ip]
28
+ }
29
+
30
+ if options[:ip]
31
+ payment_params[:ip] = options[:ip]
32
+ end
33
+
34
+ authorize_net_options = {
35
+ login: payment_method.options[:authorize_net_login_id],
36
+ password: payment_method.options[:authorize_net_transaction_key]
37
+ }
38
+
39
+ ActiveMerchant::Billing::Base.mode = payment_method.options[:authorize_net_sandbox].to_s.to_bool ? :test : :production
40
+
41
+ credit_card = ActiveMerchant::Billing::CreditCard.new(
42
+ first_name: options[:first_name],
43
+ last_name: options[:last_name],
44
+ number: options[:number],
45
+ month: options[:exp_month],
46
+ year: "20#{options[:exp_year]}",
47
+ verification_value: options[:cvc]
48
+ )
49
+ if credit_card.validate.empty?
50
+ gateway = ActiveMerchant::Billing::AuthorizeNetGateway.new(authorize_net_options)
51
+ response = gateway.purchase(amount, credit_card, payment_params)
52
+ if response.success?
53
+ cart.set_meta('pay_authorize_net', payment_params)
54
+ return {}
55
+ else
56
+ return {error: response.message}
57
+ end
58
+ else
59
+ return {error: credit_card.validate.map{|k, v| "#{k}: #{v.join(', ')}"}.join('<br>')}
60
+ end
61
+ end
62
+
63
+ def pay_with_paypal(options={})
64
+ payment_method = options[:payment_method] || site_service.payment_method('paypal')
65
+ billing_address = cart.get_meta("billing_address")
66
+ ActiveMerchant::Billing::Base.mode = payment_method.options[:paypal_sandbox].to_s.to_bool ? :test : :production
67
+ paypal_options = {
68
+ login: payment_method.options[:paypal_login],
69
+ password: payment_method.options[:paypal_password],
70
+ signature: payment_method.options[:paypal_signature]
71
+ }
72
+ gateway = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
73
+ amount_in_cents = Plugins::Ecommerce::UtilService.ecommerce_money_to_cents(cart.total_amount)
74
+ gateway_request = {
75
+ brand_name: site.name,
76
+ items: [{
77
+ number: cart.slug,
78
+ name: "Buy Products from #{site.the_title}: #{cart.products_title}",
79
+ amount: amount_in_cents,
80
+ }],
81
+ order_id: cart.slug,
82
+ currency: site.currency_code,
83
+ email: cart.user.email,
84
+ billing_address: {name: "#{billing_address[:first_name]} #{billing_address[:last_name]}",
85
+ address1: billing_address[:address1],
86
+ address2: billing_address[:address2],
87
+ city: billing_address[:city],
88
+ state: billing_address[:state],
89
+ country: billing_address[:country],
90
+ zip: billing_address[:zip]
91
+ },
92
+ description: "Buy Products from #{site.the_title}: #{cart.total_amount}",
93
+ ip: options[:ip],
94
+ return_url: options[:return_url],
95
+ cancel_return_url: options[:cancel_return_url]
96
+ }
97
+
98
+ if options[:ip]
99
+ gateway_request[:ip] = options[:ip]
100
+ end
101
+
102
+ response = gateway.setup_purchase(amount_in_cents, gateway_request)
103
+ # TODO handle errors
104
+ {redirect_url: gateway.redirect_url_for(response.token)}
105
+ end
106
+
107
+ def pay_with_stripe(options)
108
+ require 'stripe'
109
+ payment_method = options[:payment_method] || site_service.payment_method('stripe')
110
+ Stripe.api_key = payment_method.options[:stripe_id]
111
+ customer = Stripe::Customer.create(
112
+ email: options[:email], source: options[:stripe_token])
113
+ amount_in_cents = Plugins::Ecommerce::UtilService.ecommerce_money_to_cents(cart.total_amount)
114
+ begin
115
+ charge = Stripe::Charge.create(
116
+ customer: customer.id,
117
+ amount: amount_in_cents,
118
+ description: "Payment Products: #{cart.products_title}",
119
+ currency: site_service.currency,
120
+ )
121
+ payment_data = {
122
+ email: options[:email],
123
+ customer: customer.id,
124
+ charge: charge.id,
125
+ }
126
+ cart.set_meta("payment_data", payment_data)
127
+ {}
128
+ rescue Stripe::CardError => e
129
+ {error: e.message, payment_error: true}
130
+ rescue => e
131
+ {error: e.message}
132
+ end
133
+ end
134
+
135
+ def convert_to_order(status = 'paid')
136
+ Plugins::Ecommerce::Cart.transaction do
137
+ cart.prepare_to_pay
138
+ cart.update_amounts
139
+ cart.mark_paid(status)
140
+ cart.convert_to_order
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ def site_service
147
+ @site_service ||= Plugins::Ecommerce::SiteService.new(site)
148
+ end
149
+ end