shoppe 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/shoppe/application.coffee +4 -0
  3. data/app/assets/stylesheets/shoppe/application.scss +3 -3
  4. data/app/controllers/shoppe/addresses_controller.rb +47 -0
  5. data/app/controllers/shoppe/customers_controller.rb +55 -0
  6. data/app/controllers/shoppe/orders_controller.rb +29 -0
  7. data/app/controllers/shoppe/product_category_localisations_controller.rb +58 -0
  8. data/app/controllers/shoppe/product_localisations_controller.rb +58 -0
  9. data/app/controllers/shoppe/products_controller.rb +1 -1
  10. data/app/models/shoppe/address.rb +44 -0
  11. data/app/models/shoppe/customer.rb +41 -0
  12. data/app/models/shoppe/order.rb +7 -0
  13. data/app/models/shoppe/product.rb +6 -3
  14. data/app/models/shoppe/product/variants.rb +1 -1
  15. data/app/models/shoppe/product_category.rb +3 -3
  16. data/app/views/shoppe/addresses/_form.html.haml +33 -0
  17. data/app/views/shoppe/addresses/edit.html.haml +5 -0
  18. data/app/views/shoppe/addresses/new.html.haml +5 -0
  19. data/app/views/shoppe/customers/_addresses.html.haml +20 -0
  20. data/app/views/shoppe/customers/_form.html.haml +30 -0
  21. data/app/views/shoppe/customers/_search_form.html.haml +13 -0
  22. data/app/views/shoppe/customers/edit.html.haml +5 -0
  23. data/app/views/shoppe/customers/index.html.haml +32 -0
  24. data/app/views/shoppe/customers/new.html.haml +5 -0
  25. data/app/views/shoppe/customers/show.html.haml +53 -0
  26. data/app/views/shoppe/orders/_form.html.haml +3 -0
  27. data/app/views/shoppe/product_categories/_form.html.haml +1 -2
  28. data/app/views/shoppe/product_categories/edit.html.haml +3 -1
  29. data/app/views/shoppe/product_categories/index.html.haml +7 -0
  30. data/app/views/shoppe/product_category_localisations/form.html.haml +29 -0
  31. data/app/views/shoppe/product_category_localisations/index.html.haml +26 -0
  32. data/app/views/shoppe/product_localisations/form.html.haml +32 -0
  33. data/app/views/shoppe/product_localisations/index.html.haml +26 -0
  34. data/app/views/shoppe/products/edit.html.haml +1 -0
  35. data/app/views/shoppe/variants/form.html.haml +3 -1
  36. data/config/locales/en.yml +82 -1
  37. data/config/routes.rb +10 -1
  38. data/db/migrate/20141013192427_create_shoppe_customers.rb +14 -0
  39. data/db/migrate/20141027215005_create_shoppe_addresses.rb +17 -0
  40. data/db/migrate/20150315215633_add_customer_to_shoppe_orders.rb +5 -0
  41. data/db/migrate/20150513171350_create_shoppe_product_category_translation_table.rb +17 -0
  42. data/db/migrate/20150519173350_create_shoppe_product_translation_table.rb +18 -0
  43. data/db/schema.rb +42 -1
  44. data/lib/shoppe.rb +1 -0
  45. data/lib/shoppe/default_navigation.rb +1 -0
  46. data/lib/shoppe/version.rb +1 -1
  47. metadata +41 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa73eb9e87ef1d27482822773c0ca8d61f7baea1
4
- data.tar.gz: e94359654bfb0ad01f39eaf0ac0638e14c2bac4e
3
+ metadata.gz: bf9a0256bc9ea841945749f08d51e47c307c574d
4
+ data.tar.gz: 538c996c91a1a34081fbfe945b7afa450fed2443
5
5
  SHA512:
6
- metadata.gz: abffb88a987ab3a8aa34e0ff5da824f89cec0fc7905a1a250cc01b80e95b24eb4735b1fe27aa218845efb03002ab16b540b380734955f5b909f781f4b6c69655
7
- data.tar.gz: 9b830ff1d41ff811b183b0aabd62be74b625ccedea233d1034ccb52f0ae2f459e04afe247b9965bd581e301bb29cd788d728c4252c82ddf43b20b7d6242a6c97
6
+ metadata.gz: e75007e5bccf210a4954380863cadd7061396f758dd59ecfc7a28dd368068f56521c64ab2a501febf51eca1b5530122c7599f2590a740a5547903e78104056b6
7
+ data.tar.gz: 7f896f5bf90086972c0119d604ad1390262d6ef7d21ee8c382da5a8c7025d3eb72c1745cf9aa69f0db73908bad0fa38b09ddc426e08eb8e570521c8e5623dab9
@@ -13,6 +13,10 @@ $ ->
13
13
  # When clicking the order search button, toggle the form
14
14
  $('a[rel=searchOrders]').on 'click', ->
15
15
  $('div.orderSearch').toggle()
16
+
17
+ # When clicking the customer search button, toggle the form
18
+ $('a[rel=searchCustomers]').on 'click', ->
19
+ $('div.customerSearch').toggle()
16
20
 
17
21
  # Add a new attribute to a table
18
22
  $('a[data-behavior=addAttributeToAttributesTable]').on 'click', ->
@@ -321,9 +321,9 @@ header.main {
321
321
  }
322
322
 
323
323
  //
324
- // order summary page
324
+ // order & customer summary pages
325
325
  //
326
- #order {
326
+ #order, #customer {
327
327
  .details {
328
328
  overflow:hidden;
329
329
  .left {
@@ -433,7 +433,7 @@ header.main {
433
433
  //
434
434
  // order search
435
435
  //
436
- div.orderSearch {
436
+ div.orderSearch, div.customerSearch {
437
437
  overflow:hidden;
438
438
  display:none;
439
439
  dl.left, dl.right {
@@ -0,0 +1,47 @@
1
+ module Shoppe
2
+ class AddressesController < Shoppe::ApplicationController
3
+
4
+ before_filter { @active_nav = :customers }
5
+ before_filter { params[:customer_id] && @customer = Shoppe::Customer.find(params[:customer_id])}
6
+ before_filter { params[:id] && @address = @customer.addresses.find(params[:id])}
7
+
8
+ def new
9
+ @address = Shoppe::Address.new
10
+ end
11
+
12
+ def edit
13
+ end
14
+
15
+ def create
16
+ @address = @customer.addresses.build(safe_params)
17
+ if @customer.addresses.count == 0
18
+ @address.default = true
19
+ end
20
+ if @customer.save
21
+ redirect_to @customer, :flash => {:notice => "Address has been created successfully"}
22
+ else
23
+ render action: "new"
24
+ end
25
+ end
26
+
27
+ def update
28
+ if @address.update(safe_params)
29
+ redirect_to @customer, :flash => {:notice => "Address has been updated successfully"}
30
+ else
31
+ render action: "edit"
32
+ end
33
+ end
34
+
35
+ def destroy
36
+ @address.destroy
37
+ redirect_to @customer, :flash => {:notice => "Address has been deleted successfully"}
38
+ end
39
+
40
+ private
41
+
42
+ def safe_params
43
+ params[:address].permit(:address_type, :address1, :address2, :address3, :address4, :postcode, :country_id)
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,55 @@
1
+ module Shoppe
2
+ class CustomersController < Shoppe::ApplicationController
3
+
4
+ before_filter { @active_nav = :customers }
5
+ before_filter { params[:id] && @customer = Shoppe::Customer.find(params[:id])}
6
+
7
+ def index
8
+ @query = Shoppe::Customer.ordered.page(params[:page]).search(params[:q])
9
+ @customers = @query.result
10
+ end
11
+
12
+ def new
13
+ @customer = Shoppe::Customer.new
14
+ end
15
+
16
+ def show
17
+ @addresses = @customer.addresses.ordered.load
18
+ @orders = @customer.orders.ordered.load
19
+ end
20
+
21
+ def create
22
+ @customer = Shoppe::Customer.new(safe_params)
23
+ if @customer.save
24
+ redirect_to @customer, :flash => {:notice => "Customer has been created successfully"}
25
+ else
26
+ render :action => "new"
27
+ end
28
+ end
29
+
30
+ def update
31
+ if @customer.update(safe_params)
32
+ redirect_to @customer, :flash => {:notice => "Customer has been updated successfully"}
33
+ else
34
+ render :action => "edit"
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ @customer.destroy
40
+ redirect_to customers_path, :flash => {:notice => "Customer has been deleted successfully"}
41
+ end
42
+
43
+ def search
44
+ index
45
+ render :action => "index"
46
+ end
47
+
48
+ private
49
+
50
+ def safe_params
51
+ params[:customer].permit(:first_name, :last_name, :company, :email, :phone, :mobile)
52
+ end
53
+
54
+ end
55
+ end
@@ -18,6 +18,34 @@ module Shoppe
18
18
  Shoppe::Order.transaction do
19
19
  @order = Shoppe::Order.new(safe_params)
20
20
  @order.status = 'confirming'
21
+
22
+ if safe_params[:customer_id]
23
+ @customer = Shoppe::Customer.find safe_params[:customer_id]
24
+ @order.first_name = @customer.first_name
25
+ @order.last_name = @customer.last_name
26
+ @order.company = @customer.company
27
+ @order.email_address = @customer.email
28
+ @order.phone_number = @customer.phone
29
+ if @customer.addresses.billing.present?
30
+ billing = @customer.addresses.billing.first
31
+ @order.billing_address1 = billing.address1
32
+ @order.billing_address2 = billing.address2
33
+ @order.billing_address3 = billing.address3
34
+ @order.billing_address4 = billing.address4
35
+ @order.billing_postcode = billing.postcode
36
+ @order.billing_country_id = billing.country_id
37
+ end
38
+ if @customer.addresses.delivery.present?
39
+ delivery = @customer.addresses.delivery.first
40
+ @order.delivery_address1 = delivery.address1
41
+ @order.delivery_address2 = delivery.address2
42
+ @order.delivery_address3 = delivery.address3
43
+ @order.delivery_address4 = delivery.address4
44
+ @order.delivery_postcode = delivery.postcode
45
+ @order.delivery_country_id = delivery.country_id
46
+ end
47
+ end
48
+
21
49
  if !request.xhr? && @order.save
22
50
  @order.confirm!
23
51
  redirect_to @order, :notice => t('shoppe.orders.create_notice')
@@ -76,6 +104,7 @@ module Shoppe
76
104
 
77
105
  def safe_params
78
106
  params[:order].permit(
107
+ :customer_id,
79
108
  :first_name, :last_name, :company,
80
109
  :billing_address1, :billing_address2, :billing_address3, :billing_address4, :billing_postcode, :billing_country_id,
81
110
  :separate_delivery_address,
@@ -0,0 +1,58 @@
1
+ require "globalize"
2
+
3
+ module Shoppe
4
+ class ProductCategoryLocalisationsController < ApplicationController
5
+
6
+ before_filter { @active_nav = :product_categories }
7
+ before_filter { @product_category = Shoppe::ProductCategory.find(params[:product_category_id]) }
8
+ before_filter { params[:id] && @localisation = @product_category.translations.find(params[:id]) }
9
+
10
+ def index
11
+ @localisations = @product_category.translations
12
+ end
13
+
14
+ def new
15
+ @localisation = @product_category.translations.new
16
+ render :action => "form"
17
+ end
18
+
19
+ def create
20
+ if I18n.available_locales.include? safe_params[:locale].to_sym
21
+ I18n.locale = safe_params[:locale].to_sym
22
+
23
+ if @product_category.update(safe_params)
24
+ I18n.locale = I18n.default_locale
25
+ redirect_to [@product_category, :localisations], :flash => { :notice => t("shoppe.localisations.localisation_created") }
26
+ else
27
+ render :action => "edit"
28
+ end
29
+ else
30
+ redirect_to [@product_category, :localisations]
31
+ end
32
+ end
33
+
34
+ def edit
35
+ render :action => "form"
36
+ end
37
+
38
+ def update
39
+ if @localisation.update(safe_params)
40
+ redirect_to [@product_category, :localisations], :notice => t('shoppe.localisations.localisation_updated')
41
+ else
42
+ render :action => "form"
43
+ end
44
+ end
45
+
46
+ def destroy
47
+ @localisation.destroy
48
+ redirect_to [@product_category, :localisations], :notice => t('shoppe.localisations.localisation_destroyed')
49
+ end
50
+
51
+ private
52
+
53
+ def safe_params
54
+ params[:product_category_translation].permit(:name, :locale, :permalink, :description)
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,58 @@
1
+ require "globalize"
2
+
3
+ module Shoppe
4
+ class ProductLocalisationsController < ApplicationController
5
+
6
+ before_filter { @active_nav = :products }
7
+ before_filter { @product = Shoppe::Product.find(params[:product_id]) }
8
+ before_filter { params[:id] && @localisation = @product.translations.find(params[:id]) }
9
+
10
+ def index
11
+ @localisations = @product.translations
12
+ end
13
+
14
+ def new
15
+ @localisation = @product.translations.new
16
+ render :action => "form"
17
+ end
18
+
19
+ def create
20
+ if I18n.available_locales.include? safe_params[:locale].to_sym
21
+ I18n.locale = safe_params[:locale].to_sym
22
+
23
+ if @product.update(safe_params)
24
+ I18n.locale = I18n.default_locale
25
+ redirect_to [@product, :localisations], :flash => { :notice => t("shoppe.localisations.localisation_created") }
26
+ else
27
+ render :action => "form"
28
+ end
29
+ else
30
+ redirect_to [@product, :localisations]
31
+ end
32
+ end
33
+
34
+ def edit
35
+ render :action => "form"
36
+ end
37
+
38
+ def update
39
+ if @localisation.update(safe_params)
40
+ redirect_to [@product, :localisations], :notice => t('shoppe.localisations.localisation_updated')
41
+ else
42
+ render :action => "form"
43
+ end
44
+ end
45
+
46
+ def destroy
47
+ @localisation.destroy
48
+ redirect_to [@product, :localisations], :notice => t('shoppe.localisations.localisation_destroyed')
49
+ end
50
+
51
+ private
52
+
53
+ def safe_params
54
+ params[:product_translation].permit(:name, :locale, :permalink, :description, :short_description)
55
+ end
56
+
57
+ end
58
+ end
@@ -5,7 +5,7 @@ module Shoppe
5
5
  before_filter { params[:id] && @product = Shoppe::Product.root.find(params[:id]) }
6
6
 
7
7
  def index
8
- @products = Shoppe::Product.root.includes(:stock_level_adjustments, :default_image, :product_categories, :variants).order(:name).group_by(&:product_category).sort_by { |cat,pro| cat.name }
8
+ @products = Shoppe::Product.root.includes(:translations, :stock_level_adjustments, :default_image, :product_categories, :variants).order(:name).group_by(&:product_category).sort_by { |cat,pro| cat.name }
9
9
  end
10
10
 
11
11
  def new
@@ -0,0 +1,44 @@
1
+ module Shoppe
2
+ class Address < ActiveRecord::Base
3
+
4
+ # An array of all the available types for an address
5
+ TYPES = ["billing", "delivery"]
6
+
7
+ # Set the table name
8
+ self.table_name = "shoppe_addresses"
9
+
10
+ # The customer which this address should be linked to
11
+ #
12
+ # @return [Shoppe::Customer]
13
+ belongs_to :customer, :class_name => "Shoppe::Customer"
14
+
15
+ # The order which this address should be linked to
16
+ #
17
+ # @return [Shoppe::Order]
18
+ belongs_to :order, :class_name => "Shoppe::Order"
19
+
20
+ # The country which this address should be linked to
21
+ #
22
+ # @return [Shoppe::Country]
23
+ belongs_to :country, :class_name => "Shoppe::Country"
24
+
25
+ # Validations
26
+ validates :address_type, :presence => true, :inclusion => {:in => TYPES}
27
+ validates :address1, :presence => true
28
+ validates :address3, :presence => true
29
+ validates :address4, :presence => true
30
+ validates :postcode, :presence => true
31
+ validates :country, :presence => true
32
+
33
+ # All addresses ordered by their id asending
34
+ scope :ordered, -> { order(:id => :desc)}
35
+ scope :default, -> { where(default: true)}
36
+ scope :billing, -> { where(address_type: "billing")}
37
+ scope :delivery, -> { where(address_type: "delivery")}
38
+
39
+ def full_address
40
+ [address1, address2, address3, address4, postcode, country.try(:name)].join(", ")
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+ module Shoppe
2
+ class Customer < ActiveRecord::Base
3
+
4
+ self.table_name = "shoppe_customers"
5
+
6
+ has_many :addresses, :dependent => :restrict_with_exception, :class_name => "Shoppe::Address"
7
+
8
+ has_many :orders, :dependent => :restrict_with_exception, :class_name => "Shoppe::Order"
9
+
10
+ # Validations
11
+ validates :email, :presence => true, :uniqueness => true, :format => {:with => /\A\b[A-Z0-9\.\_\%\-\+]+@(?:[A-Z0-9\-]+\.)+[A-Z]{2,6}\b\z/i}
12
+ validates :phone, :presence => true, :format => {:with => /\A[\d\ \-x\(\)]{7,}\z/}
13
+
14
+ # All customers ordered by their ID desending
15
+ scope :ordered, -> { order(:id => :desc)}
16
+
17
+ # The name of the customer in the format of "Company (First Last)" or if they don't have
18
+ # company specified, just "First Last".
19
+ #
20
+ # @return [String]
21
+ def name
22
+ company.blank? ? full_name : "#{company} (#{full_name})"
23
+ end
24
+
25
+ # The full name of the customer created by concatinting the first & last name
26
+ #
27
+ # @return [String]
28
+ def full_name
29
+ "#{first_name} #{last_name}"
30
+ end
31
+
32
+ def self.ransackable_attributes(auth_object = nil)
33
+ ["id", "first_name", "last_name", "company", "email", "phone", "mobile"] + _ransackers.keys
34
+ end
35
+
36
+ def self.ransackable_associations(auth_object = nil)
37
+ []
38
+ end
39
+
40
+ end
41
+ end
@@ -19,6 +19,10 @@ module Shoppe
19
19
  # All products which are part of this order (accessed through the items)
20
20
  has_many :products, :through => :order_items, :class_name => 'Shoppe::Product', :source => :ordered_item, :source_type => 'Shoppe::Product'
21
21
 
22
+ # The order can belong to a customer
23
+ belongs_to :customer, :class_name => 'Shoppe::Customer'
24
+ has_many :addresses, :through => :customers, :class_name => "Shoppe::Address"
25
+
22
26
  # Validations
23
27
  validates :token, :presence => true
24
28
  with_options :if => Proc.new { |o| !o.building? } do |order|
@@ -29,6 +33,9 @@ module Shoppe
29
33
  # Set some defaults
30
34
  before_validation { self.token = SecureRandom.uuid if self.token.blank? }
31
35
 
36
+ # Some methods for setting the billing & delivery addresses
37
+ attr_accessor :save_addresses, :billing_address_id, :delivery_address_id
38
+
32
39
  # The order number
33
40
  #
34
41
  # @return [String] - the order number padded with at least 5 zeros
@@ -1,4 +1,5 @@
1
- require 'roo'
1
+ require "roo"
2
+ require "globalize"
2
3
 
3
4
  module Shoppe
4
5
  class Product < ActiveRecord::Base
@@ -58,8 +59,9 @@ module Shoppe
58
59
  # All featured products
59
60
  scope :featured, -> {where(:featured => true)}
60
61
 
61
- # All products ordered with default items first followed by name ascending
62
- scope :ordered, -> {order(:default => :desc, :name => :asc)}
62
+ # Localisations
63
+ translates :name, :permalink, :description, :short_description
64
+ scope :ordered, -> { includes(:translations).order(:name) }
63
65
 
64
66
  # Return the name of the product
65
67
  #
@@ -81,6 +83,7 @@ module Shoppe
81
83
  #
82
84
  # @return [BigDecimal]
83
85
  def price
86
+ # self.default_variant ? self.default_variant.price : read_attribute(:price)
84
87
  self.default_variant ? self.default_variant.price : read_attribute(:price)
85
88
  end
86
89