radiant-shop-extension 0.9.3 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/README.md +9 -3
  2. data/Rakefile +1 -0
  3. data/VERSION +1 -1
  4. data/app/controllers/admin/shop/customers_controller.rb +35 -126
  5. data/app/controllers/shop/categories_controller.rb +1 -5
  6. data/app/controllers/shop/products_controller.rb +1 -1
  7. data/app/models/form_checkout.rb +198 -112
  8. data/app/models/shop_category.rb +3 -3
  9. data/app/models/shop_customer.rb +3 -12
  10. data/app/models/shop_order.rb +5 -3
  11. data/app/models/shop_payment.rb +0 -1
  12. data/app/models/shop_product.rb +3 -3
  13. data/app/views/admin/shop/customers/edit.html.haml +13 -0
  14. data/app/views/admin/shop/customers/edit/_fields.html.haml +33 -0
  15. data/app/views/admin/shop/customers/edit/_head.html.haml +2 -0
  16. data/app/views/admin/shop/customers/edit/_meta.html.haml +7 -0
  17. data/app/views/admin/shop/customers/edit/_parts.html.haml +4 -0
  18. data/app/views/admin/shop/customers/edit/_popups.html.haml +3 -0
  19. data/app/views/admin/shop/customers/edit/meta/_login.html.haml +5 -0
  20. data/app/views/admin/shop/customers/edit/meta/_password.html.haml +5 -0
  21. data/app/views/admin/shop/customers/edit/meta/_password_confirmation.html.haml +5 -0
  22. data/app/views/admin/shop/customers/edit/parts/_address.html.haml +7 -0
  23. data/app/views/admin/shop/customers/edit/parts/_addresses.html.haml +13 -0
  24. data/app/views/admin/shop/customers/edit/parts/_orders.html.haml +29 -0
  25. data/app/views/admin/shop/customers/index.html.haml +9 -35
  26. data/app/views/admin/shop/customers/index/_bottom.html.haml +4 -0
  27. data/app/views/admin/shop/customers/index/_customer.html.haml +9 -0
  28. data/app/views/admin/shop/customers/new.html.haml +11 -0
  29. data/app/views/admin/shop/customers/remove.html.haml +12 -0
  30. data/app/views/admin/shop/products/new.html.haml +1 -1
  31. data/config/locales/en.yml +37 -29
  32. data/config/routes.rb +2 -0
  33. data/db/migrate/20100927041219_remove_payment_methods.rb +16 -0
  34. data/db/migrate/20100927041624_change_payments_add_gateway.rb +11 -0
  35. data/db/migrate/20100927140446_change_payment_add_card_type_card_number.rb +11 -0
  36. data/db/seed.rb +1 -0
  37. data/db/seeds/forms.rb +179 -0
  38. data/db/{migrate/20100520033059_create_layouts.rb → seeds/layouts.rb} +19 -27
  39. data/db/seeds/snippets.rb +23 -0
  40. data/lib/shop/interface/customers.rb +34 -0
  41. data/lib/shop/tags/address.rb +1 -0
  42. data/lib/shop/tags/card.rb +51 -0
  43. data/lib/shop/tags/helpers.rb +53 -38
  44. data/lib/shop/tags/item.rb +1 -1
  45. data/lib/shop/tags/product.rb +23 -22
  46. data/lib/shop/tags/responses.rb +3 -3
  47. data/lib/tasks/shop_extension_tasks.rake +6 -0
  48. data/public/stylesheets/sass/admin/extensions/shop/index.sass +64 -0
  49. data/radiant-shop-extension.gemspec +37 -6
  50. data/shop_extension.rb +7 -2
  51. data/spec/datasets/forms.rb +112 -118
  52. data/spec/datasets/shop_customers.rb +30 -0
  53. data/spec/datasets/shop_orders.rb +7 -3
  54. data/spec/datasets/shop_products.rb +1 -0
  55. data/spec/lib/shop/tags/card_spec.rb +71 -0
  56. data/spec/lib/shop/tags/helpers_spec.rb +270 -283
  57. data/spec/lib/shop/tags/item_spec.rb +9 -0
  58. data/spec/lib/shop/tags/product_spec.rb +172 -158
  59. data/spec/lib/shop/tags/responses_spec.rb +129 -0
  60. data/spec/models/form_checkout_spec.rb +228 -294
  61. data/spec/models/shop_category_page_spec.rb +2 -2
  62. data/spec/models/shop_order_spec.rb +27 -20
  63. data/spec/models/shop_product_attachment_spec.rb +1 -0
  64. metadata +61 -17
  65. data/app/models/shop_payment_method.rb +0 -5
  66. data/db/migrate/20100903122123_create_forms.rb +0 -44
  67. data/db/migrate/20100908063639_create_snippets.rb +0 -22
@@ -36,9 +36,9 @@ class ShopCategory < ActiveRecord::Base
36
36
  def search(search)
37
37
  unless search.blank?
38
38
  queries = []
39
- queries << 'LOWER(title) LIKE (:term)'
40
- queries << 'LOWER(handle) LIKE (:term)'
41
- queries << 'LOWER(description) LIKE (:term)'
39
+ queries << 'LOWER(shop_categories.name) LIKE (:term)'
40
+ queries << 'LOWER(shop_categories.handle) LIKE (:term)'
41
+ queries << 'LOWER(shop_categories.description) LIKE (:term)'
42
42
 
43
43
  sql = queries.join(" OR ")
44
44
  conditions = [sql, {:term => "%#{search.downcase}%" }]
@@ -1,16 +1,12 @@
1
1
  class ShopCustomer < User
2
-
3
- default_scope where(:all, :conditions => { :access => 'shop' })
2
+ include Scoped::Models::User::Scoped
4
3
 
5
4
  has_many :orders, :class_name => 'ShopOrder'
6
- has_many :addressables, :class_name => 'ShopAddressable', :as => :addresser
7
- has_many :billings, :through => :addressables, :source => :address, :source_type => 'ShopAddressBilling', :uniq => true
8
- has_many :shippings, :through => :addressables, :source => :address, :source_type => 'ShopAddressShipping', :uniq => true
5
+ has_many :billings, :through => :orders
6
+ has_many :shippings, :through => :orders
9
7
 
10
8
  accepts_nested_attributes_for :orders, :allow_destroy => true
11
9
 
12
- before_save :set_access
13
-
14
10
  def first_name
15
11
  self.name.split(' ')[0]
16
12
  end
@@ -19,9 +15,4 @@ class ShopCustomer < User
19
15
  self.name.split(' ')[1]
20
16
  end
21
17
 
22
- private
23
- def set_access
24
- self.access = 'shop'
25
- end
26
-
27
18
  end
@@ -1,6 +1,8 @@
1
1
  class ShopOrder < ActiveRecord::Base
2
2
 
3
- has_many :payments, :class_name => 'ShopPayment', :dependent => :destroy
3
+ default_scope :order => 'shop_orders.updated_at ASC'
4
+
5
+ has_one :payment, :class_name => 'ShopPayment', :dependent => :destroy
4
6
  has_many :line_items, :class_name => 'ShopLineItem', :dependent => :destroy
5
7
 
6
8
  belongs_to :billing, :class_name => 'ShopAddress'
@@ -10,7 +12,6 @@ class ShopOrder < ActiveRecord::Base
10
12
  belongs_to :customer, :class_name => 'ShopCustomer', :foreign_key => :shop_customer_id
11
13
 
12
14
  accepts_nested_attributes_for :line_items, :reject_if => :all_blank
13
- accepts_nested_attributes_for :payments, :reject_if => :all_blank
14
15
  accepts_nested_attributes_for :billing, :reject_if => :all_blank
15
16
  accepts_nested_attributes_for :shipping, :reject_if => :all_blank
16
17
 
@@ -74,7 +75,8 @@ class ShopOrder < ActiveRecord::Base
74
75
  end
75
76
 
76
77
  def paid?
77
- self.status === 'paid'
78
+ return false unless self.payment.present?
79
+ self.payment.amount === self.price and self.status === 'paid'
78
80
  end
79
81
 
80
82
  def shipped?
@@ -1,6 +1,5 @@
1
1
  class ShopPayment < ActiveRecord::Base
2
2
 
3
3
  belongs_to :order, :class_name => 'ShopOrder', :foreign_key => :shop_order_id
4
- belongs_to :method, :class_name => 'ShopPaymentMethod', :foreign_key => :shop_payment_method_id
5
4
 
6
5
  end
@@ -44,9 +44,9 @@ class ShopProduct < ActiveRecord::Base
44
44
  def search(search)
45
45
  unless search.blank?
46
46
  queries = []
47
- queries << 'LOWER(title) LIKE (:term)'
48
- queries << 'LOWER(sku) LIKE (:term)'
49
- queries << 'LOWER(description) LIKE (:term)'
47
+ queries << 'LOWER(shop_products.name) LIKE (:term)'
48
+ queries << 'LOWER(shop_products.sku) LIKE (:term)'
49
+ queries << 'LOWER(shop_products.description) LIKE (:term)'
50
50
 
51
51
  sql = queries.join(" OR ")
52
52
  conditions = [sql, {:term => "%#{search.downcase}%" }]
@@ -0,0 +1,13 @@
1
+ - @page_title = @shop_customer.name + ' - ' + default_page_title
2
+
3
+ - render_region :main do |main|
4
+ - main.header do
5
+ %h1
6
+ = @shop_customer.name
7
+ = render 'admin/shop/customers/edit/head'
8
+ - main.form do
9
+ - form_for :shop_customer, @shop_customer, :url => admin_shop_customer_path(@shop_customer), :html => {:method => :put, :multipart => true, :id => 'edit_shop_customer', 'data-onsubmit_status'=>"Saving Changes&#8230;"} do |f|
10
+ = render :partial => 'admin/shop/customers/edit/fields', :locals => { :f => f }
11
+ - main.popups do
12
+ #popups
13
+ = render 'admin/shop/customers/edit/popups'
@@ -0,0 +1,33 @@
1
+ - render_region :top
2
+
3
+ - render_region :form do |form|
4
+ - form.name do
5
+ %p.title
6
+ %label{:for => 'shop_customer_name'}= t('name')
7
+ = f.text_field :name, :class => 'textbox', :maxlenth => 255
8
+
9
+ - form.email do
10
+ %p.title
11
+ %label{:for => 'shop_customer_email'}= t('email')
12
+ = f.text_field :email, :class => 'textbox', :maxlenth => 255
13
+
14
+ - form.meta do
15
+ = render :partial => '/admin/shop/customers/edit/meta', :locals => { :f => f }
16
+
17
+ - form.parts do
18
+ #tab_control
19
+ #tabs.tabs
20
+ #tab_toolbar
21
+ #pages.pages
22
+ = hidden_field_tag 'page_part_index_field' #important
23
+ = render :partial => '/admin/shop/customers/edit/parts', :locals => { :f => f }
24
+
25
+ - render_region :bottom do |bottom|
26
+ - bottom.buttons do
27
+ %p.buttons{:style=>"clear: left"}
28
+ = save_model_button(@shop_customer)
29
+ = save_model_and_continue_editing_button(@shop_customer)
30
+ = t('or')
31
+ = link_to t('cancel'), admin_shop_customers_path
32
+ - bottom.timestamp do
33
+ = updated_stamp @shop_customer
@@ -0,0 +1,2 @@
1
+ - @buttons.each do |button|
2
+ = render :partial => "admin/shop/customers/edit/buttons/#{button}"
@@ -0,0 +1,7 @@
1
+ .drawer
2
+ .drawer_contents#attributes
3
+ %table.fieldset
4
+ - @meta.each do |meta|
5
+ = render :partial => 'admin/shop/customers/edit/meta/' + meta, :locals => { :f => f }
6
+ .drawer_handle
7
+ %a.toggle{:href=>'#attributes', :rel=>"toggle[attributes]", :class=>"#{(meta_errors? ? 'less' : 'more')}"}= meta_label
@@ -0,0 +1,4 @@
1
+ - @parts.each do |part|
2
+ .page{:id => "customer_page_#{part}", 'data-caption'=>h(part)}
3
+ .part{:id => "customer_part_#{part}"}
4
+ = render :partial => "admin/shop/customers/edit/parts/#{part}", :locals => { :f => f }
@@ -0,0 +1,3 @@
1
+ = @popups.each do |popup|
2
+ .popup{ :id => "#{popup}_popup"}
3
+ = render :partial => "admin/shop/customers/edit/popups/#{popup}"
@@ -0,0 +1,5 @@
1
+ %tr
2
+ %th.label
3
+ = f.label :login, t('login')
4
+ %td.field
5
+ = f.text_field :login
@@ -0,0 +1,5 @@
1
+ %tr
2
+ %th.label
3
+ = f.label :password, t('password')
4
+ %td.field
5
+ = f.password_field :password, :value => ''
@@ -0,0 +1,5 @@
1
+ %tr
2
+ %th.label
3
+ = f.label :password_confirmation, t('password')
4
+ %td.field
5
+ = f.password_field :password_confirmation, :value => ''
@@ -0,0 +1,7 @@
1
+ %span.name= address.name
2
+ %span.unit= address.unit
3
+ %span.street= address.street
4
+ %span.city= address.city
5
+ %span.state= address.state
6
+ %span.country= address.country
7
+ %span.postcode= address.postcode
@@ -0,0 +1,13 @@
1
+ %h3 Billing
2
+
3
+ %ul#billings
4
+ - @shop_customer.billings.each do |billing|
5
+ %li.billing
6
+ = render :partial => '/admin/shop/customers/edit/parts/address', :locals => { :address => billing }
7
+
8
+ %h3 Shipping
9
+
10
+ %ul#shippings
11
+ - @shop_customer.billings.each do |shipping|
12
+ %li.shipping
13
+ = render :partial => '/admin/shop/customers/edit/parts/address', :locals => { :address => shipping }
@@ -0,0 +1,29 @@
1
+ %ul#orders
2
+ - @shop_customer.orders.each do |order|
3
+ %li.order
4
+ %h3
5
+ = number_to_currency(order.price)
6
+ = distance_of_time_in_words Time.now, order.updated_at
7
+ ago
8
+ %h4
9
+ = order.line_items.count
10
+ = order.line_items.count == 1 ? 'item' : 'items'
11
+ = "(#{order.status})"
12
+
13
+ %br
14
+
15
+ %h4 Billing
16
+ %span.billing= render :partial => '/admin/shop/customers/edit/parts/address', :locals => { :address => order.billing }
17
+
18
+ %h4 Shipping
19
+ %span.shipping= render :partial => '/admin/shop/customers/edit/parts/address', :locals => { :address => order.shipping }
20
+
21
+ %h4 Payment
22
+ %span.payment
23
+ - if order.paid?
24
+ = order.payment.card_number
25
+ = order.payment.card_type
26
+ - else
27
+ This order hasn't been paid for yet
28
+
29
+ %hr
@@ -1,36 +1,10 @@
1
- Add Customer
2
- - form_for [:admin, @shop_customer] do |f|
3
- %p
4
- = f.label :name, 'Name:'
5
- = f.text_field :name
6
- %p
7
- = f.label :email, 'Email:'
8
- = f.text_field :email
9
- %p
10
- = f.label :login, 'Login:'
11
- = f.text_field :login
12
- %p
13
- = f.label :password, "Password"
14
- = f.password_field "password", :value => "", :size => 15, :maxlength => 40
15
- %p
16
- = f.label :password_confirmation, "Confirm Password"
17
- = f.password_field "password_confirmation", :value => "", :size => 15, :maxlength => 40
18
- %p
19
- = f.label :reference, 'Reference:'
20
- = f.text_field :reference
21
- %p
22
- = f.label :Organization, 'Organization:'
23
- = f.text_field :organization
24
- %p
25
- = f.submit "Save"
26
-
1
+ - @page_title = t('customers') + ' - ' + default_page_title
27
2
 
28
- - if @shop_customers.empty?
29
- %p There are no customers.
30
- - else
31
- %form
32
- - @shop_customers.each do |customer|
33
- %p
34
- = customer.name
35
- = link_to "Add Order", "", :style => "color: blue;"
36
- = link_to "Delete Customer", "/admin/shop/customers/#{customer.id}", :confirm => "Are you sure?", :method => :delete, :style => "color: blue;"
3
+ .outset
4
+
5
+ #customers_map.map
6
+ %ul#customers
7
+ = render :partial => '/admin/shop/customers/index/customer', :collection => @shop_customers
8
+
9
+ #actions
10
+ = render :partial => '/admin/shop/customers/index/bottom'
@@ -0,0 +1,4 @@
1
+ %ul
2
+ - render_region :bottom do |bottom|
3
+ - bottom.add do
4
+ %li= link_to image('plus') + " " + t("add_customer"), new_admin_shop_customer_path
@@ -0,0 +1,9 @@
1
+ %li.customer.object{:id => "customer_#{customer.id}", :'data-id' => customer.id}
2
+ .attributes
3
+ %span.name.attribute
4
+ - render_region :customer do |region|
5
+ - region.name do
6
+ %span.name.attribute= link_to customer.name, edit_admin_shop_customer_path(customer)
7
+ - region.modify do
8
+ .modify
9
+ %span.remove= link_to t('remove'), remove_admin_shop_customer_path(customer)
@@ -0,0 +1,11 @@
1
+ - render_region :main do |main|
2
+ - main.header do
3
+ %h1
4
+ = @shop_customer.name
5
+ = render 'admin/shop/customers/edit/head'
6
+ - main.form do
7
+ - form_for :shop_customer, :url => admin_shop_customers_path, :html => {:id => 'new_shop_customer', :multipart => true, 'data-onsubmit_status'=>"Creating Customer&#8230;"} do |f|
8
+ = render :partial => 'admin/shop/customers/edit/fields', :locals => { :f => f }
9
+ - main.popups do
10
+ #popups
11
+ = render 'admin/shop/customers/edit/popups'
@@ -0,0 +1,12 @@
1
+ %h1
2
+ = t('remove_customer')
3
+
4
+ %p
5
+ = t('text.remove_customer.warning')
6
+
7
+ - form_for [:admin, @shop_customer.becomes(ShopCustomer)], :html => {:method => :delete, 'data-onsubmit_status'=>"Removing Customer&#8230;"} do
8
+
9
+ %p.buttons
10
+ %input.button{:type=>"submit", :value => t('delete_customer') }/
11
+ = t('or')
12
+ = link_to t('cancel'), admin_shop_customers_path
@@ -4,7 +4,7 @@
4
4
  = t('new_product')
5
5
  = render :partial => 'admin/shop/products/edit/head'
6
6
  - main.edit_form do
7
- - form_for :shop_product, @shop_product, :url => admin_shop_products_path, :html => {:id => 'new_shop_product', :multipart => true, 'data-onsubmit_status'=>"Creating Product&#8230;"} do |f|
7
+ - form_for :shop_product, :url => admin_shop_products_path, :html => {:id => 'new_shop_product', :multipart => true, 'data-onsubmit_status'=>"Creating Product&#8230;"} do |f|
8
8
  = render :partial => 'admin/shop/products/edit/fields', :object => f
9
9
  - main.edit_popups do
10
10
  - #empty
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  en:
3
- shop: "shop"
3
+ shop: "Shop"
4
4
  shop_category: "Category"
5
5
  shop_categories: "Categories"
6
6
  shop_product: "Product"
@@ -15,35 +15,43 @@ en:
15
15
  could_not_update: "Couldn't update"
16
16
  could_not_destroy: "Couldn't delete"
17
17
  could_not_sort: "Couldn't sort"
18
- handle: 'Handle'
19
- title: 'Title'
20
- category: 'Category'
21
- categories: 'Categories'
22
- no_categories: 'No Categories'
23
- add_category: 'Add Category'
24
- new_category: 'New Shop Category'
25
- edit_category: 'Update Shop Category'
26
- remove_category: 'This will delete the category'
27
- delete_category: 'Delete Category'
28
- custom_layout: 'Layout'
29
- custom_product_layout: 'Product Layout'
30
- product: 'Product'
31
- products: 'Products'
32
- no_products: 'No Products'
33
- add_product: 'Add Product'
34
- new_product: 'New Shop Product'
35
- edit_product: 'Update Shop Product'
36
- remove_product: 'This will delete the product'
37
- delete_product: 'Delete Product'
38
- image: 'Image'
39
- images: 'Images'
40
- no_images: 'No Images'
41
- add_image: 'Add Image'
42
- browse_images: 'Browse Images'
43
- caption: 'Caption'
44
- price: 'Price'
45
- sku: 'SKU'
18
+ email: "Email"
19
+ handle: "Handle"
20
+ title: "Title"
21
+ customer: "Customer"
22
+ customers: "Customers"
23
+ add_customer: "Add Customer"
24
+ remove_customer: "This will delete the customer"
25
+ delete_customer: "Delete Customer"
26
+ category: "Category"
27
+ categories: "Categories"
28
+ no_categories: "No Categories"
29
+ add_category: "Add Category"
30
+ new_category: "New Shop Category"
31
+ edit_category: "Update Shop Category"
32
+ remove_category: "This will delete the category"
33
+ delete_category: "Delete Category"
34
+ custom_layout: "Layout"
35
+ custom_product_layout: "Product Layout"
36
+ product: "Product"
37
+ products: "Products"
38
+ no_products: "No Products"
39
+ add_product: "Add Product"
40
+ new_product: "New Shop Product"
41
+ edit_product: "Update Shop Product"
42
+ remove_product: "This will delete the product"
43
+ delete_product: "Delete Product"
44
+ image: "Image"
45
+ images: "Images"
46
+ no_images: "No Images"
47
+ add_image: "Add Image"
48
+ browse_images: "Browse Images"
49
+ caption: "Caption"
50
+ price: "Price"
51
+ sku: "SKU"
46
52
  text:
53
+ remove_customer:
54
+ warning: "Deleting a customer is irreversible and will also delete their orders and addresses, make sure you're sure."
47
55
  remove_product:
48
56
  warning: "Deleting a product is irreversible, make sure you're sure."
49
57
  remove_category:
data/config/routes.rb CHANGED
@@ -3,6 +3,8 @@ ActionController::Routing::Routes.draw do |map|
3
3
  map.namespace :admin do |admin|
4
4
  admin.namespace :shop, :member => { :remove => :get } do |shop|
5
5
 
6
+ shop.resources :customers
7
+
6
8
  shop.resources :categories, :collection => { :sort => :put }, :member => { :products => :get } do |category|
7
9
  category.resources :products, :only => :new
8
10
  end
@@ -0,0 +1,16 @@
1
+ class RemovePaymentMethods < ActiveRecord::Migration
2
+ def self.up
3
+ drop_table :shop_payment_methods
4
+ remove_index :shop_payments, :shop_payment_method_id
5
+ remove_column :shop_payments, :shop_payment_method_id
6
+ end
7
+
8
+ def self.down
9
+ add_column :shop_payments, :shop_pamyent_method_id, :integer
10
+ add_index :shop_payments, :shop_payment_method_id
11
+
12
+ create_table :shop_payment_methods do |t|
13
+ t.string :name
14
+ end
15
+ end
16
+ end