shoppe 1.0.7 → 1.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/shoppe/application.coffee +4 -0
- data/app/assets/stylesheets/shoppe/application.scss +3 -3
- data/app/controllers/shoppe/addresses_controller.rb +47 -0
- data/app/controllers/shoppe/customers_controller.rb +55 -0
- data/app/controllers/shoppe/orders_controller.rb +29 -0
- data/app/controllers/shoppe/product_category_localisations_controller.rb +58 -0
- data/app/controllers/shoppe/product_localisations_controller.rb +58 -0
- data/app/controllers/shoppe/products_controller.rb +1 -1
- data/app/models/shoppe/address.rb +44 -0
- data/app/models/shoppe/customer.rb +41 -0
- data/app/models/shoppe/order.rb +7 -0
- data/app/models/shoppe/product.rb +6 -3
- data/app/models/shoppe/product/variants.rb +1 -1
- data/app/models/shoppe/product_category.rb +3 -3
- data/app/views/shoppe/addresses/_form.html.haml +33 -0
- data/app/views/shoppe/addresses/edit.html.haml +5 -0
- data/app/views/shoppe/addresses/new.html.haml +5 -0
- data/app/views/shoppe/customers/_addresses.html.haml +20 -0
- data/app/views/shoppe/customers/_form.html.haml +30 -0
- data/app/views/shoppe/customers/_search_form.html.haml +13 -0
- data/app/views/shoppe/customers/edit.html.haml +5 -0
- data/app/views/shoppe/customers/index.html.haml +32 -0
- data/app/views/shoppe/customers/new.html.haml +5 -0
- data/app/views/shoppe/customers/show.html.haml +53 -0
- data/app/views/shoppe/orders/_form.html.haml +3 -0
- data/app/views/shoppe/product_categories/_form.html.haml +1 -2
- data/app/views/shoppe/product_categories/edit.html.haml +3 -1
- data/app/views/shoppe/product_categories/index.html.haml +7 -0
- data/app/views/shoppe/product_category_localisations/form.html.haml +29 -0
- data/app/views/shoppe/product_category_localisations/index.html.haml +26 -0
- data/app/views/shoppe/product_localisations/form.html.haml +32 -0
- data/app/views/shoppe/product_localisations/index.html.haml +26 -0
- data/app/views/shoppe/products/edit.html.haml +1 -0
- data/app/views/shoppe/variants/form.html.haml +3 -1
- data/config/locales/en.yml +82 -1
- data/config/routes.rb +10 -1
- data/db/migrate/20141013192427_create_shoppe_customers.rb +14 -0
- data/db/migrate/20141027215005_create_shoppe_addresses.rb +17 -0
- data/db/migrate/20150315215633_add_customer_to_shoppe_orders.rb +5 -0
- data/db/migrate/20150513171350_create_shoppe_product_category_translation_table.rb +17 -0
- data/db/migrate/20150519173350_create_shoppe_product_translation_table.rb +18 -0
- data/db/schema.rb +42 -1
- data/lib/shoppe.rb +1 -0
- data/lib/shoppe/default_navigation.rb +1 -0
- data/lib/shoppe/version.rb +1 -1
- metadata +41 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf9a0256bc9ea841945749f08d51e47c307c574d
|
4
|
+
data.tar.gz: 538c996c91a1a34081fbfe945b7afa450fed2443
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
data/app/models/shoppe/order.rb
CHANGED
@@ -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
|
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
|
-
#
|
62
|
-
|
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
|
|