Class: Plugins::Ecommerce::Cart

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
CamaleonCms::Metas
Defined in:
app/models/plugins/ecommerce/cart.rb

Direct Known Subclasses

Order

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.set_user(user) ⇒ Object

set user in filter (filter carts by user_id or cookie_id) cookie_id is used for public users who are buying without login



124
125
126
# File 'app/models/plugins/ecommerce/cart.rb', line 124

def self.set_user(user)
  defined?(user.id) ? self.where(user_id: user.id) : self.where(visitor_key: user)
end

Instance Method Details

#add_product(product, qty = 1, variation_id = nil) ⇒ Object



25
26
27
28
29
30
31
32
33
# File 'app/models/plugins/ecommerce/cart.rb', line 25

def add_product(product, qty = 1, variation_id = nil)
  pi = product_items.where(product_id: product.id, variation_id: variation_id).first
  if pi.present?
    pi.update_column(:qty, qty)
  else
    pi = product_items.create(product_id: product.id, qty: qty, variation_id: variation_id)
  end
  pi
end

#change_user(user) ⇒ Object

move current cart from public user into existent user



129
130
131
# File 'app/models/plugins/ecommerce/cart.rb', line 129

def change_user(user)
  update_columns(user_id: user.id, visitor_key: nil)
end

#discount_for(coupon_code, price = nil) ⇒ Object

verify an return (error code), discount: amount of discount coupon for current cart price: the total price including shipping price (used for free discount type)



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'app/models/plugins/ecommerce/cart.rb', line 54

def discount_for(coupon_code, price = nil)
  coupon = site.coupons.find_by_slug(coupon_code)
  res = {error: '', discount: 0, coupon: coupon}
  if coupon.present?
    opts = coupon.options
    if coupon.expired?
      res[:error] = 'coupon_expired'
    elsif !coupon.active?
      res[:error] = 'inactive_coupon'
    elsif coupon.used_times_exceeded?
      res[:error] = 'times_exceeded'
    elsif !coupon.valid_min_price?(sub_total)
      res[:error] = 'required_minimum_price'
    else
      case opts[:discount_type]
        when 'free_ship', 'free'
          res[:discount] = total_shipping
        when 'percent'
          res[:discount] = sub_total * opts[:amount].to_f / 100
        when 'money'
          res[:discount] = opts[:amount].to_f
      end
    end
  else
    res[:error] = 'coupon_not_found'
  end
  res
end

#free_cart?Boolean

check if the price of the cart is 0, including prices for products, discounts, shipping

Returns:

  • (Boolean)


134
135
136
# File 'app/models/plugins/ecommerce/cart.rb', line 134

def free_cart?
  total_amount <= 0
end

#items_totalObject



35
36
37
# File 'app/models/plugins/ecommerce/cart.rb', line 35

def items_total
  product_items.map{|item| item.qty }.inject{|sum,x| sum + x } || 0
end

#payment_methodObject

status: bank_pending => pending of verification for bank transfer orders

paid => paid by some method
canceled => canceled order
shipped => shipped status


21
22
23
# File 'app/models/plugins/ecommerce/cart.rb', line 21

def payment_method
  @_cama_cache_payment_method ||= Plugins::Ecommerce::PaymentMethod.find_by_id(get_meta('payment_method_id', self.payment_method_id))
end

#paypal_gatewayObject

return the gateway for paypal transactions



169
170
171
172
173
174
175
176
177
# File 'app/models/plugins/ecommerce/cart.rb', line 169

def paypal_gateway
  ActiveMerchant::Billing::Base.mode = payment_method.options[:paypal_sandbox].to_s.to_bool ? :test : :production
  paypal_options = {
    login: payment_method.options[:paypal_login],
    password: payment_method.options[:paypal_password],
    signature: payment_method.options[:paypal_signature]
  }
  ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end

#prepare_to_payObject



83
84
85
86
87
88
89
90
# File 'app/models/plugins/ecommerce/cart.rb', line 83

def prepare_to_pay
  self.class.transaction do
    self.update_columns(
      status: 'qtys_taken',
    )
    self.product_items.decorate.each{|p_item| p_item.decrement_qty! }
  end
end

#sub_totalObject

price of all products (no include taxes)



40
41
42
# File 'app/models/plugins/ecommerce/cart.rb', line 40

def sub_total
  product_items.map{|item| product = item.product.decorate; (product.price(item.variation_id)) * item.qty }.inject{|sum,x| sum + x } || 0
end

#tax_totalObject



44
45
46
# File 'app/models/plugins/ecommerce/cart.rb', line 44

def tax_total
  product_items.map{|item| product = item.product.decorate; (product.tax(item.variation_id)) * item.qty }.inject{|sum,x| sum + x } || 0
end

#total_amountObject

include all costs and discounts



99
100
101
102
103
104
105
106
# File 'app/models/plugins/ecommerce/cart.rb', line 99

def total_amount
  payment_amount = partial_total
  if self.coupon.present?
    res_coupon = self.discount_for(self.coupon, payment_amount)
    payment_amount = payment_amount - res_coupon[:discount] unless res_coupon[:error].present?
  end
  payment_amount < 0 ? 0 : payment_amount
end

#total_discountsObject

return total of discounts



109
110
111
112
113
114
115
# File 'app/models/plugins/ecommerce/cart.rb', line 109

def total_discounts
  if self.coupon.present?
    self.discount_for(self.coupon, partial_total)[:discount] || 0
  else
    0
  end
end

#total_shippingObject

return the total price of shipping



118
119
120
# File 'app/models/plugins/ecommerce/cart.rb', line 118

def total_shipping
  shipping_method.present? ? shipping_method.get_price_from_weight(weight_total) : 0
end

#total_to_pay_without_discountsObject Also known as: partial_total

return the total price without coupon price



93
94
95
# File 'app/models/plugins/ecommerce/cart.rb', line 93

def total_to_pay_without_discounts
  sub_total + tax_total + total_shipping
end

#update_amountsObject



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'app/models/plugins/ecommerce/cart.rb', line 138

def update_amounts
  product_items.decorate.each do |item|
    p = item.product.decorate
    item.update_columns(
      cache_the_price: p.the_price(item.variation_id),
      cache_the_title: p.the_variation_title(item.variation_id),
      cache_the_tax: p.the_tax(item.variation_id),
      cache_the_sub_total: item.the_sub_total,
    )
  end

  if self.coupon.present?
    res_coupon = self.discount_for(self.coupon, total_to_pay_without_discounts)
    unless res_coupon[:error].present?
      update_columns(the_coupon_amount: res_coupon[:coupon].decorate.the_amount)
      res_coupon[:coupon].mark_as_used(user)
    end
  end
  c = self.decorate
  self.update_columns(
    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,
  )
end

#weight_totalObject



48
49
50
# File 'app/models/plugins/ecommerce/cart.rb', line 48

def weight_total
  product_items.map{|item| product = item.product.decorate; (product.weight(item.variation_id)) * item.qty }.inject{|sum,x| sum + x } || 0
end