shoppe 1.0.7 → 1.0.8
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.
- 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
|
|