shoppe 0.0.15 → 0.0.16

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.
Files changed (199) hide show
  1. data/README.rdoc +1 -0
  2. data/Rakefile +21 -1
  3. data/app/assets/javascripts/shoppe/application.coffee +5 -0
  4. data/app/assets/stylesheets/shoppe/application.scss +16 -3
  5. data/app/assets/stylesheets/shoppe/elements.scss +8 -0
  6. data/app/assets/stylesheets/shoppe/printable.scss +67 -0
  7. data/app/controllers/shoppe/application_controller.rb +1 -10
  8. data/app/controllers/shoppe/orders_controller.rb +4 -0
  9. data/app/controllers/shoppe/sessions_controller.rb +1 -0
  10. data/app/controllers/shoppe/settings_controller.rb +12 -0
  11. data/app/controllers/shoppe/users_controller.rb +2 -2
  12. data/app/controllers/shoppe/variants_controller.rb +1 -1
  13. data/app/helpers/shoppe/application_helper.rb +63 -8
  14. data/app/mailers/shoppe/order_mailer.rb +5 -7
  15. data/app/mailers/shoppe/user_mailer.rb +2 -2
  16. data/app/models/shoppe/country.rb +17 -1
  17. data/app/models/shoppe/delivery_service.rb +15 -0
  18. data/app/models/shoppe/delivery_service_price.rb +17 -0
  19. data/app/models/shoppe/order.rb +82 -9
  20. data/app/models/shoppe/order_item.rb +18 -0
  21. data/app/models/shoppe/product.rb +26 -1
  22. data/app/models/shoppe/product/product_attributes.rb +1 -1
  23. data/app/models/shoppe/product/variants.rb +3 -3
  24. data/app/models/shoppe/product_attribute.rb +15 -0
  25. data/app/models/shoppe/product_category.rb +12 -0
  26. data/app/models/shoppe/setting.rb +59 -0
  27. data/app/models/shoppe/stock_level_adjustment.rb +15 -0
  28. data/app/models/shoppe/tax_rate.rb +13 -1
  29. data/app/models/shoppe/user.rb +13 -0
  30. data/app/views/layouts/shoppe/application.html.haml +2 -1
  31. data/app/views/layouts/shoppe/printable.html.haml +11 -0
  32. data/app/views/shoppe/delivery_service_prices/index.html.haml +1 -1
  33. data/app/views/shoppe/order_mailer/accepted.text.erb +2 -2
  34. data/app/views/shoppe/order_mailer/received.text.erb +2 -2
  35. data/app/views/shoppe/order_mailer/rejected.text.erb +2 -2
  36. data/app/views/shoppe/order_mailer/shipped.text.erb +2 -2
  37. data/app/views/shoppe/orders/despatch_note.html.haml +45 -0
  38. data/app/views/shoppe/orders/index.html.haml +2 -2
  39. data/app/views/shoppe/orders/show.html.haml +21 -11
  40. data/app/views/shoppe/settings/edit.html.haml +19 -0
  41. data/app/views/shoppe/user_mailer/new_password.text.erb +1 -1
  42. data/app/views/shoppe/variants/form.html.haml +4 -0
  43. data/config/locales/en.yml +34 -0
  44. data/config/routes.rb +5 -0
  45. data/db/migrate/20130926094549_create_shoppe_initial_schema.rb +92 -33
  46. data/db/seeds.rb +1 -1
  47. data/lib/shoppe.rb +13 -35
  48. data/lib/shoppe/engine.rb +6 -6
  49. data/lib/shoppe/settings.rb +28 -0
  50. data/lib/shoppe/settings_loader.rb +16 -0
  51. data/lib/shoppe/setup_generator.rb +0 -4
  52. data/lib/shoppe/version.rb +1 -1
  53. data/test/{dummy → app}/README.rdoc +0 -0
  54. data/test/{dummy → app}/Rakefile +0 -0
  55. data/test/{dummy → app}/app/assets/javascripts/application.js +0 -0
  56. data/test/{dummy → app}/app/assets/stylesheets/application.css +0 -0
  57. data/test/{dummy → app}/app/controllers/application_controller.rb +0 -0
  58. data/test/{dummy → app}/app/helpers/application_helper.rb +0 -0
  59. data/test/{dummy → app}/app/views/layouts/application.html.erb +0 -0
  60. data/test/{dummy → app}/bin/bundle +0 -0
  61. data/test/{dummy → app}/bin/rails +0 -0
  62. data/test/{dummy → app}/bin/rake +0 -0
  63. data/test/{dummy → app}/config.ru +0 -0
  64. data/test/{dummy → app}/config/application.rb +0 -0
  65. data/test/{dummy → app}/config/boot.rb +0 -0
  66. data/test/app/config/database.example.yml +30 -0
  67. data/test/{dummy → app}/config/database.yml +9 -5
  68. data/test/{dummy → app}/config/environment.rb +0 -0
  69. data/test/{dummy → app}/config/environments/development.rb +0 -0
  70. data/test/{dummy → app}/config/environments/production.rb +0 -0
  71. data/test/{dummy → app}/config/environments/test.rb +0 -0
  72. data/test/{dummy → app}/config/initializers/backtrace_silencers.rb +0 -0
  73. data/test/{dummy → app}/config/initializers/filter_parameter_logging.rb +0 -0
  74. data/test/{dummy → app}/config/initializers/inflections.rb +0 -0
  75. data/test/{dummy → app}/config/initializers/mime_types.rb +0 -0
  76. data/test/{dummy → app}/config/initializers/secret_token.rb +0 -0
  77. data/test/app/config/initializers/session_store.rb +3 -0
  78. data/test/{dummy → app}/config/initializers/wrap_parameters.rb +0 -0
  79. data/test/{dummy → app}/config/locales/en.yml +0 -0
  80. data/test/{dummy → app}/config/routes.rb +0 -0
  81. data/{config/shoppe.example.yml → test/app/config/shoppe.yml} +0 -0
  82. data/test/{dummy → app}/db/development.sqlite3 +0 -0
  83. data/test/{dummy → app}/db/migrate/20131017165217_create_nifty_attachments_table.rb +0 -0
  84. data/test/{dummy → app}/db/migrate/20131017165222_create_nifty_key_value_store_table.rb +0 -0
  85. data/test/{dummy → app}/db/schema.rb +31 -16
  86. data/test/{dummy → app}/db/test.sqlite3 +0 -0
  87. data/test/app/log/development.log +8093 -0
  88. data/test/{dummy → app}/log/test.log +0 -0
  89. data/test/{dummy → app}/public/404.html +0 -0
  90. data/test/{dummy → app}/public/422.html +0 -0
  91. data/test/{dummy → app}/public/500.html +0 -0
  92. data/test/{dummy → app}/public/favicon.ico +0 -0
  93. data/test/app/tmp/cache/assets/development/sass/7c98994848dbb534749f971b176724aa382339bb/dialog.scssc +0 -0
  94. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/application.scssc +0 -0
  95. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/dialog.scssc +0 -0
  96. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/elements.scssc +0 -0
  97. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/reset.scssc +0 -0
  98. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/sub.scssc +0 -0
  99. data/test/app/tmp/cache/assets/development/sass/edac894564dae62b78e653a08d1c41f10ade93f9/variables.scssc +0 -0
  100. data/test/app/tmp/cache/assets/development/sprockets/06d540cec125e08e63a898c35e8235d6 +0 -0
  101. data/test/app/tmp/cache/assets/development/sprockets/0a6bca3e510625f255083bd154cc470b +0 -0
  102. data/test/app/tmp/cache/assets/development/sprockets/0d8942b2279b6bc7c68b3db3e2e4c342 +0 -0
  103. data/test/app/tmp/cache/assets/development/sprockets/122a65fdcbb923c3c1cd95549ef52f43 +0 -0
  104. data/test/app/tmp/cache/assets/development/sprockets/140840b7aefa4bf5beda2c32e20374a6 +0 -0
  105. data/test/app/tmp/cache/assets/development/sprockets/160ddfa6141944c4a03757fe91643137 +0 -0
  106. data/test/app/tmp/cache/assets/development/sprockets/1bb0d399b6b81fc3b47ff794b066873f +0 -0
  107. data/test/app/tmp/cache/assets/development/sprockets/1e1679158bd397a720be46fa3a5876a3 +0 -0
  108. data/test/app/tmp/cache/assets/development/sprockets/2a75ba35f8e751887ba89a914363fefd +0 -0
  109. data/test/app/tmp/cache/assets/development/sprockets/2cc6ef740b5691af5ee246c0dbc68f14 +0 -0
  110. data/test/app/tmp/cache/assets/development/sprockets/2f80004fb2e2ce07283a83ac15cf920a +0 -0
  111. data/test/app/tmp/cache/assets/development/sprockets/322295abdd8625fcce4da08f9565cc63 +0 -0
  112. data/test/app/tmp/cache/assets/development/sprockets/421b79f445cd87f3532a5c445877cbec +0 -0
  113. data/test/app/tmp/cache/assets/development/sprockets/4528fe4a109cad1ff031659cd9eeae17 +0 -0
  114. data/test/app/tmp/cache/assets/development/sprockets/45a9c7dfe9986570daa4c972277375ec +0 -0
  115. data/test/app/tmp/cache/assets/development/sprockets/48b2cd7153bbc442eaa84c3e24e963e0 +0 -0
  116. data/test/app/tmp/cache/assets/development/sprockets/4c3fef5a3e293ed6b6df3d869f54e1d1 +0 -0
  117. data/test/app/tmp/cache/assets/development/sprockets/4c8cb5cfd87990ebddbaa5b5fd594be5 +0 -0
  118. data/test/app/tmp/cache/assets/development/sprockets/4cefa37a52d669d3ca7e6aa1e1aaf435 +0 -0
  119. data/test/app/tmp/cache/assets/development/sprockets/4ea4f5c13aaeda9a7d39684ab72fa710 +0 -0
  120. data/test/app/tmp/cache/assets/development/sprockets/4ecd1cb66cb36718daadcfba0aa42c1e +0 -0
  121. data/test/app/tmp/cache/assets/development/sprockets/4ed3cbd180c275b98627eaeea4c9c838 +0 -0
  122. data/test/app/tmp/cache/assets/development/sprockets/519aa2b3c3ab8fd8f065c56507111878 +0 -0
  123. data/test/app/tmp/cache/assets/development/sprockets/51d409a48872319ac6a731aa880e6368 +0 -0
  124. data/test/app/tmp/cache/assets/development/sprockets/55bae604bcb5ccf7d9e0ed0fd61953b6 +0 -0
  125. data/test/app/tmp/cache/assets/development/sprockets/5805d2c402f412642d86ec03a7ec4a3d +0 -0
  126. data/test/app/tmp/cache/assets/development/sprockets/5cd772b44cdeae4d3b37b62193e946eb +0 -0
  127. data/test/app/tmp/cache/assets/development/sprockets/5f32b259cbcc52156d2fe21c185d9390 +0 -0
  128. data/test/app/tmp/cache/assets/development/sprockets/656ea3403f27a33b86d5bf9e8a0c0e46 +0 -0
  129. data/test/app/tmp/cache/assets/development/sprockets/679705affe2ad274da1ad48cb5137c21 +0 -0
  130. data/test/app/tmp/cache/assets/development/sprockets/69a687de4cbb95365bf8aa2037d63726 +0 -0
  131. data/test/app/tmp/cache/assets/development/sprockets/69d5224a79e874431294e8adf04e7d65 +0 -0
  132. data/test/app/tmp/cache/assets/development/sprockets/6bc5a76ff13bc4daebb7e164a4b64196 +0 -0
  133. data/test/app/tmp/cache/assets/development/sprockets/6c1a5456c2e5d87285dd1910762fe01e +0 -0
  134. data/test/app/tmp/cache/assets/development/sprockets/6d52ff2c9298014f2d648eb9e04a61a6 +0 -0
  135. data/test/app/tmp/cache/assets/development/sprockets/7938636d16e11b754d4dd046b89863c4 +0 -0
  136. data/test/app/tmp/cache/assets/development/sprockets/7ce7981501e05438faa017eb2e197379 +0 -0
  137. data/test/app/tmp/cache/assets/development/sprockets/7e232a7b4ac10fe1350e2b9b05ab0b02 +0 -0
  138. data/test/app/tmp/cache/assets/development/sprockets/81d7800826e89041f377af8570b8324f +0 -0
  139. data/test/app/tmp/cache/assets/development/sprockets/81f524fed55fe63e95c1aeccb5d83571 +0 -0
  140. data/test/app/tmp/cache/assets/development/sprockets/85984636ee801f63af86b35d7697d4c5 +0 -0
  141. data/test/app/tmp/cache/assets/development/sprockets/88de2cf8ce5990c5fa59f7c9f4599a65 +0 -0
  142. data/test/app/tmp/cache/assets/development/sprockets/8932a78ffe18ad2e3bb7ceb90ac4b933 +0 -0
  143. data/test/app/tmp/cache/assets/development/sprockets/8d6fd863923e78438318b02bf83be1c4 +0 -0
  144. data/test/app/tmp/cache/assets/development/sprockets/8f43db1e57a90ffbae3be00a895d5a09 +0 -0
  145. data/test/app/tmp/cache/assets/development/sprockets/91e11940ab63a407af03d21720ac2951 +0 -0
  146. data/test/app/tmp/cache/assets/development/sprockets/938abfdc262a8ab42e768545640bfb2a +0 -0
  147. data/test/app/tmp/cache/assets/development/sprockets/9e760b9565b110e433b7e42f827cb5f8 +0 -0
  148. data/test/app/tmp/cache/assets/development/sprockets/9e8fbfd56e8ef705ba94bb03b5b3696e +0 -0
  149. data/test/app/tmp/cache/assets/development/sprockets/9ebbf73fb48cdf8bc07a8bfdd6d14328 +0 -0
  150. data/test/app/tmp/cache/assets/development/sprockets/9f240d481b0818a6da0b1a1aaaac2b54 +0 -0
  151. data/test/app/tmp/cache/assets/development/sprockets/a2b956b30a80f996b5aeb1b2f226775c +0 -0
  152. data/test/app/tmp/cache/assets/development/sprockets/a5b5ed9849e8019160b73aa554132b37 +0 -0
  153. data/test/app/tmp/cache/assets/development/sprockets/a692ba7ed6cff183bb840c2622233c87 +0 -0
  154. data/test/app/tmp/cache/assets/development/sprockets/a951f4ceb83ae691f002b4f6183bc1ed +0 -0
  155. data/test/app/tmp/cache/assets/development/sprockets/accc4dc17ef18d0b510917a005340da5 +0 -0
  156. data/test/app/tmp/cache/assets/development/sprockets/b2db166e9974feb35358e7fcce87cb39 +0 -0
  157. data/test/app/tmp/cache/assets/development/sprockets/b519a4f6c5b5a0d9236bdca14e0eb00d +0 -0
  158. data/test/app/tmp/cache/assets/development/sprockets/b5cbeb3def40b118469fff2d80c1b596 +0 -0
  159. data/test/app/tmp/cache/assets/development/sprockets/b6f65271a0e77b349529ce9148dd2782 +0 -0
  160. data/test/app/tmp/cache/assets/development/sprockets/b9ad7ea18b7e55c3626a15d1dae142ed +0 -0
  161. data/test/app/tmp/cache/assets/development/sprockets/bc384ea2fdcc667aa4282209caba921f +0 -0
  162. data/test/app/tmp/cache/assets/development/sprockets/bcf06bf434bb3d3a5769036d6e24b301 +0 -0
  163. data/test/app/tmp/cache/assets/development/sprockets/bd83357635155d3457747e92e47da0ed +0 -0
  164. data/test/app/tmp/cache/assets/development/sprockets/c39634555e4eba3595350eeea648ddf4 +0 -0
  165. data/test/app/tmp/cache/assets/development/sprockets/c3ef336ca8f7e64969d8bfdcf837ad10 +0 -0
  166. data/test/app/tmp/cache/assets/development/sprockets/c55037904a95162828e5d0b087677878 +0 -0
  167. data/test/app/tmp/cache/assets/development/sprockets/c733f1a2fe9d05a3a634ff64a394f64b +0 -0
  168. data/test/app/tmp/cache/assets/development/sprockets/c83a337688a52890ba93372fea6ec932 +0 -0
  169. data/test/app/tmp/cache/assets/development/sprockets/ca92d0dbc43c066af9b31f2bc26d038d +0 -0
  170. data/test/app/tmp/cache/assets/development/sprockets/cae2fc80bfbc81ec7b6c11a72be18c98 +0 -0
  171. data/test/app/tmp/cache/assets/development/sprockets/cd665363677ffcef0dde972284e8d942 +0 -0
  172. data/test/app/tmp/cache/assets/development/sprockets/d5154a1eda9cfbfe54e091d6ead1ac5f +0 -0
  173. data/test/app/tmp/cache/assets/development/sprockets/daa7fa7a610bc5951cc3c4403f290eb6 +0 -0
  174. data/test/app/tmp/cache/assets/development/sprockets/dabc0e94bc1e37007351ac756dd2dd6a +0 -0
  175. data/test/app/tmp/cache/assets/development/sprockets/edf3c55a27678996371bffe56298925b +0 -0
  176. data/test/app/tmp/cache/assets/development/sprockets/f0f04c3b2b0091fa3ca4a1edacc23a1c +0 -0
  177. data/test/app/tmp/cache/assets/development/sprockets/f8610737fbfdcb85db95ae7c6a70514e +0 -0
  178. data/test/app/tmp/restart.txt +0 -0
  179. data/test/shoppe_test.rb +0 -5
  180. data/test/test_helper.rb +1 -1
  181. metadata +298 -98
  182. data/app/helpers/shoppe/shoppe_helper.rb +0 -30
  183. data/db/migrate/20131012123829_create_shoppe_product_attributes.rb +0 -11
  184. data/db/migrate/20131012163301_add_public_boolean_to_product_attributes.rb +0 -5
  185. data/db/migrate/20131013123937_add_cost_prices_to_various_objects.rb +0 -8
  186. data/db/migrate/20131013131658_add_stock_control_boolean_to_products.rb +0 -5
  187. data/db/migrate/20131017144430_create_shoppe_stock_level_adjustments.rb +0 -18
  188. data/db/migrate/20131017180920_create_shoppe_countries.rb +0 -16
  189. data/db/migrate/20131017183211_create_shoppe_tax_rates.rb +0 -26
  190. data/db/migrate/20131020204719_add_countries_to_tax_rates_and_delivery_prices.rb +0 -6
  191. data/db/migrate/20131021135208_add_notes_to_orders.rb +0 -5
  192. data/db/migrate/20131022090919_refactor_order_items_to_allow_any_product.rb +0 -6
  193. data/db/migrate/20131022092904_rename_product_title_to_name.rb +0 -5
  194. data/db/migrate/20131022093538_stock_level_adjustments_should_be_polymorphic.rb +0 -6
  195. data/db/migrate/20131022135331_add_parent_id_to_products.rb +0 -5
  196. data/db/migrate/20131022145653_cost_price_should_be_default_to_zero.rb +0 -9
  197. data/test/dummy/config/initializers/session_store.rb +0 -3
  198. data/test/dummy/config/shoppe.yml +0 -7
  199. data/test/dummy/log/development.log +0 -1162
@@ -1,3 +1,20 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_delivery_service_prices
4
+ #
5
+ # id :integer not null, primary key
6
+ # delivery_service_id :integer
7
+ # code :string(255)
8
+ # price :decimal(8, 2)
9
+ # cost_price :decimal(8, 2)
10
+ # tax_rate_id :integer
11
+ # min_weight :decimal(8, 2)
12
+ # max_weight :decimal(8, 2)
13
+ # created_at :datetime
14
+ # updated_at :datetime
15
+ # country_ids :text
16
+ #
17
+
1
18
  module Shoppe
2
19
  class DeliveryServicePrice < ActiveRecord::Base
3
20
 
@@ -1,3 +1,50 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_orders
4
+ #
5
+ # id :integer not null, primary key
6
+ # token :string(255)
7
+ # first_name :string(255)
8
+ # last_name :string(255)
9
+ # company :string(255)
10
+ # billing_address1 :string(255)
11
+ # billing_address2 :string(255)
12
+ # billing_address3 :string(255)
13
+ # billing_address4 :string(255)
14
+ # billing_postcode :string(255)
15
+ # billing_country_id :integer
16
+ # email_address :string(255)
17
+ # phone_number :string(255)
18
+ # status :string(255)
19
+ # received_at :datetime
20
+ # accepted_at :datetime
21
+ # shipped_at :datetime
22
+ # created_at :datetime
23
+ # updated_at :datetime
24
+ # delivery_service_id :integer
25
+ # delivery_price :decimal(8, 2)
26
+ # delivery_cost_price :decimal(8, 2)
27
+ # delivery_tax_rate :decimal(8, 2)
28
+ # delivery_tax_amount :decimal(8, 2)
29
+ # paid_at :datetime
30
+ # accepted_by :integer
31
+ # shipped_by :integer
32
+ # consignment_number :string(255)
33
+ # rejected_at :datetime
34
+ # rejected_by :integer
35
+ # ip_address :string(255)
36
+ # payment_reference :string(255)
37
+ # payment_method :string(255)
38
+ # notes :text
39
+ # separate_delivery_address :boolean default(FALSE)
40
+ # delivery_address1 :string(255)
41
+ # delivery_address2 :string(255)
42
+ # delivery_address3 :string(255)
43
+ # delivery_address4 :string(255)
44
+ # deilvery_postcode :string(255)
45
+ # delivery_country_id :integer
46
+ #
47
+
1
48
  module Shoppe
2
49
  class Order < ActiveRecord::Base
3
50
 
@@ -17,7 +64,8 @@ module Shoppe
17
64
 
18
65
  # Relationships
19
66
  belongs_to :delivery_service, :class_name => 'Shoppe::DeliveryService'
20
- belongs_to :country, :class_name => 'Shoppe::Country'
67
+ belongs_to :billing_country, :class_name => 'Shoppe::Country', :foreign_key => 'billing_country_id'
68
+ belongs_to :delivery_country, :class_name => 'Shoppe::Country', :foreign_key => 'delivery_country_id'
21
69
  belongs_to :accepter, :class_name => 'Shoppe::User', :foreign_key => 'accepted_by'
22
70
  belongs_to :rejecter, :class_name => 'Shoppe::User', :foreign_key => 'rejected_by'
23
71
  belongs_to :shipper, :class_name => 'Shoppe::User', :foreign_key => 'shipped_by'
@@ -30,14 +78,23 @@ module Shoppe
30
78
  with_options :if => Proc.new { |o| !o.building? } do |order|
31
79
  order.validates :first_name, :presence => true
32
80
  order.validates :last_name, :presence => true
33
- order.validates :address1, :presence => true
34
- order.validates :address3, :presence => true
35
- order.validates :address4, :presence => true
36
- order.validates :postcode, :presence => true
37
- order.validates :country, :presence => true
81
+ order.validates :billing_address1, :presence => true
82
+ order.validates :billing_address3, :presence => true
83
+ order.validates :billing_address4, :presence => true
84
+ order.validates :billing_postcode, :presence => true
85
+ order.validates :billing_country, :presence => true
38
86
  order.validates :email_address, :format => {:with => /\A\b[A-Z0-9\.\_\%\-\+]+@(?:[A-Z0-9\-]+\.)+[A-Z]{2,6}\b\z/i}
39
87
  order.validates :phone_number, :format => {:with => /\A[\d\ \-x\(\)]{7,}\z/}
40
88
  end
89
+ with_options :if => :separate_delivery_address? do |order|
90
+ order.validates :delivery_name, :presence => true
91
+ order.validates :delivery_address1, :presence => true
92
+ order.validates :delivery_address3, :presence => true
93
+ order.validates :delivery_address4, :presence => true
94
+ order.validates :delivery_postcode, :presence => true
95
+ order.validates :delivery_country, :presence => true
96
+ end
97
+
41
98
  validate do
42
99
  unless available_delivery_services.include?(self.delivery_service)
43
100
  errors.add :delivery_service_id, "is not suitable for this order"
@@ -54,6 +111,12 @@ module Shoppe
54
111
  self.status = 'building' if self.status.blank?
55
112
  self.token = SecureRandom.uuid if self.token.blank?
56
113
  end
114
+
115
+ [:delivery_name, :delivery_address1, :delivery_address2, :delivery_address3, :delivery_address4, :delivery_postcode, :delivery_country].each do |f|
116
+ define_method(f) do
117
+ separate_delivery_address? ? super() : send(f.to_s.gsub('delivery_', 'billing_'))
118
+ end
119
+ end
57
120
 
58
121
  # Is this order still being built by the user?
59
122
  def building?
@@ -99,7 +162,17 @@ module Shoppe
99
162
 
100
163
  # The name of the customer
101
164
  def customer_name
102
- company.blank? ? "#{first_name} #{last_name}" : "#{company} (#{first_name} #{last_name})"
165
+ company.blank? ? full_name : "#{company} (#{full_name})"
166
+ end
167
+
168
+ # The name for billing purposes
169
+ def billing_name
170
+ company.blank? ? full_name : "#{full_name} (#{company})"
171
+ end
172
+
173
+ # The full anme of the customer
174
+ def full_name
175
+ "#{first_name} #{last_name}"
103
176
  end
104
177
 
105
178
  # Is this order empty? (i.e. doesn't have any items associated with it)
@@ -161,7 +234,7 @@ module Shoppe
161
234
  def delivery_service_prices
162
235
  @delivery_service_prices ||= begin
163
236
  prices = Shoppe::DeliveryServicePrice.joins(:delivery_service).where(:shoppe_delivery_services => {:active => true}).order("`default` desc, price asc").for_weight(total_weight)
164
- prices = prices.select { |p| p.countries.empty? || p.country?(self.country) }
237
+ prices = prices.select { |p| p.countries.empty? || p.country?(self.billing_country) }
165
238
  prices
166
239
  end
167
240
  end
@@ -343,7 +416,7 @@ module Shoppe
343
416
 
344
417
  # Specify which attributes can be searched
345
418
  def self.ransackable_attributes(auth_object = nil)
346
- ["id", "postcode", "address1", "address2", "address3", "address4", "first_name", "last_name", "company", "email_address", "phone_number", "consignment_number", "status", "received_at"] + _ransackers.keys
419
+ ["id", "billing_postcode", "billing_address1", "billing_address2", "billing_address3", "billing_address4", "first_name", "last_name", "company", "email_address", "phone_number", "consignment_number", "status", "received_at"] + _ransackers.keys
347
420
  end
348
421
 
349
422
  # Specify which associations can be searched
@@ -1,3 +1,21 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_order_items
4
+ #
5
+ # id :integer not null, primary key
6
+ # order_id :integer
7
+ # ordered_item_id :integer
8
+ # ordered_item_type :string(255)
9
+ # quantity :integer default(1)
10
+ # unit_price :decimal(8, 2)
11
+ # unit_cost_price :decimal(8, 2)
12
+ # tax_amount :decimal(8, 2)
13
+ # tax_rate :decimal(8, 2)
14
+ # weight :decimal(8, 3) default(0.0)
15
+ # created_at :datetime
16
+ # updated_at :datetime
17
+ #
18
+
1
19
  module Shoppe
2
20
  class OrderItem < ActiveRecord::Base
3
21
 
@@ -1,3 +1,28 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_products
4
+ #
5
+ # id :integer not null, primary key
6
+ # parent_id :integer
7
+ # product_category_id :integer
8
+ # name :string(255)
9
+ # sku :string(255)
10
+ # permalink :string(255)
11
+ # description :text
12
+ # short_description :text
13
+ # active :boolean default(TRUE)
14
+ # weight :decimal(8, 3) default(0.0)
15
+ # price :decimal(8, 2) default(0.0)
16
+ # cost_price :decimal(8, 2) default(0.0)
17
+ # tax_rate_id :integer
18
+ # created_at :datetime
19
+ # updated_at :datetime
20
+ # featured :boolean default(FALSE)
21
+ # in_the_box :text
22
+ # stock_control :boolean default(TRUE)
23
+ # default :boolean default(FALSE)
24
+ #
25
+
1
26
  module Shoppe
2
27
  class Product < ActiveRecord::Base
3
28
 
@@ -38,7 +63,7 @@ module Shoppe
38
63
  # Scopes
39
64
  scope :active, -> { where(:active => true) }
40
65
  scope :featured, -> {where(:featured => true)}
41
- scope :ordered, -> {order('name asc')}
66
+ scope :ordered, -> {order('`default` desc, name asc')}
42
67
 
43
68
  # Return the name of the product
44
69
  def full_name
@@ -1,5 +1,5 @@
1
1
  module Shoppe
2
- class Product
2
+ class Product < ActiveRecord::Base
3
3
 
4
4
  # Relationships
5
5
  has_many :product_attributes, -> { order(:position) }, :class_name => 'Shoppe::ProductAttribute'
@@ -1,8 +1,8 @@
1
1
  module Shoppe
2
- class Product
2
+ class Product < ActiveRecord::Base
3
3
 
4
4
  # Relationships
5
- has_many :variants, :class_name => 'Shoppe::Product', :foreign_key => 'parent_id', :dependent => :destroy
5
+ has_many :variants, -> { order("`default` desc, name asc")}, :class_name => 'Shoppe::Product', :foreign_key => 'parent_id', :dependent => :destroy
6
6
  belongs_to :parent, :class_name => 'Shoppe::Product', :foreign_key => 'parent_id'
7
7
 
8
8
  # Validations
@@ -19,7 +19,7 @@ module Shoppe
19
19
 
20
20
  def default_variant
21
21
  return nil if self.parent
22
- @default_variant ||= self.variants.first
22
+ @default_variant ||= self.variants.select { |v| v.default? }.first
23
23
  end
24
24
 
25
25
  end
@@ -1,3 +1,18 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_product_attributes
4
+ #
5
+ # id :integer not null, primary key
6
+ # product_id :integer
7
+ # key :string(255)
8
+ # value :string(255)
9
+ # position :integer default(1)
10
+ # searchable :boolean default(TRUE)
11
+ # created_at :datetime
12
+ # updated_at :datetime
13
+ # public :boolean default(TRUE)
14
+ #
15
+
1
16
  module Shoppe
2
17
  class ProductAttribute < ActiveRecord::Base
3
18
 
@@ -1,3 +1,15 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_product_categories
4
+ #
5
+ # id :integer not null, primary key
6
+ # name :string(255)
7
+ # permalink :string(255)
8
+ # description :text
9
+ # created_at :datetime
10
+ # updated_at :datetime
11
+ #
12
+
1
13
  module Shoppe
2
14
  class ProductCategory < ActiveRecord::Base
3
15
 
@@ -0,0 +1,59 @@
1
+ require 'ostruct'
2
+
3
+ module Shoppe
4
+ class Setting < ActiveRecord::Base
5
+
6
+ validates :key, :presence => true, :uniqueness => true
7
+ validates :value, :presence => true
8
+ validates :value_type, :presence => true
9
+
10
+ before_validation do
11
+ self.value_type = I18n.t("shoppe.settings.types")[self.key.to_sym].try(:capitalize) || self.value.class.to_s
12
+ self.value = encoded_value
13
+ end
14
+
15
+ # The encoded value for saving in the backend (as a string)
16
+ def encoded_value
17
+ case value_type
18
+ when 'Array', 'Hash' then value.to_json
19
+ when 'Boolean' then value.to_s == 'true' ? 'true' : 'false'
20
+ else value.to_s
21
+ end
22
+ end
23
+
24
+ # The decoded value for the setting attribute (in it's native type)
25
+ def decoded_value
26
+ case value_type
27
+ when 'Fixnum' then value.to_i
28
+ when 'Float' then value.to_f
29
+ when 'Array', 'Hash' then JSON.parse(value)
30
+ when 'Boolean' then value == 'true' ? true : false
31
+ else value.to_s
32
+ end
33
+ end
34
+
35
+ # A full hash of all settings available in the current scope
36
+ def self.to_hash
37
+ all.inject({}) do |h, setting|
38
+ h[setting.key.to_s] = setting.decoded_value
39
+ h
40
+ end
41
+ end
42
+
43
+ # Update settings from a given hash and persist them. Accepts a
44
+ # hash of keys (which should be strings).
45
+ def self.update_from_hash(hash)
46
+ existing_settings = self.all.to_a
47
+ hash.each do |key, value|
48
+ existing = existing_settings.select { |s| s.key.to_s == key.to_s }.first
49
+ if existing
50
+ value.blank? ? existing.destroy! : existing.update!(:value => value)
51
+ else
52
+ value.blank? ? nil : self.create!(:key => key, :value => value)
53
+ end
54
+ end
55
+ hash
56
+ end
57
+
58
+ end
59
+ end
@@ -1,3 +1,18 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_stock_level_adjustments
4
+ #
5
+ # id :integer not null, primary key
6
+ # item_id :integer
7
+ # item_type :string(255)
8
+ # description :string(255)
9
+ # adjustment :integer default(0)
10
+ # parent_type :string(255)
11
+ # parent_id :integer
12
+ # created_at :datetime
13
+ # updated_at :datetime
14
+ #
15
+
1
16
  module Shoppe
2
17
  class StockLevelAdjustment < ActiveRecord::Base
3
18
 
@@ -1,3 +1,15 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_tax_rates
4
+ #
5
+ # id :integer not null, primary key
6
+ # name :string(255)
7
+ # rate :decimal(8, 2)
8
+ # created_at :datetime
9
+ # updated_at :datetime
10
+ # country_ids :text
11
+ #
12
+
1
13
  module Shoppe
2
14
  class TaxRate < ActiveRecord::Base
3
15
 
@@ -23,7 +35,7 @@ module Shoppe
23
35
  end
24
36
 
25
37
  def rate_for(order)
26
- if countries.empty? || order.country.nil? || country?(order.country)
38
+ if countries.empty? || order.billing_country.nil? || country?(order.billing_country)
27
39
  self.rate
28
40
  else
29
41
  0.0
@@ -1,3 +1,16 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: shoppe_users
4
+ #
5
+ # id :integer not null, primary key
6
+ # first_name :string(255)
7
+ # last_name :string(255)
8
+ # email_address :string(255)
9
+ # password_digest :string(255)
10
+ # created_at :datetime
11
+ # updated_at :datetime
12
+ #
13
+
1
14
  module Shoppe
2
15
  class User < ActiveRecord::Base
3
16
 
@@ -21,6 +21,7 @@
21
21
  %li= link_to "Delivery Services", [:delivery_services], :class => @active_nav == :delivery_services ? 'active' : ''
22
22
  %li= link_to "Tax Rates", :tax_rates, :class => @active_nav == :tax_rates ? 'active' : ''
23
23
  %li= link_to "Users", [:users], :class => @active_nav == :users ? 'active' : ''
24
+ %li= link_to "Settings", :settings, :class => @active_nav == :settings ? 'active' : ''
24
25
  %li= link_to "Logout", [:logout], :method => :delete
25
26
 
26
27
  %header.main
@@ -32,5 +33,5 @@
32
33
  = yield
33
34
 
34
35
  %footer
35
- %p.store= link_to "Goto Storefront", '/'
36
+ %p.store= link_to "&larr; Goto #{Shoppe.settings.store_name}".html_safe, '/'
36
37
 
@@ -0,0 +1,11 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title= @page_title
5
+ = stylesheet_link_tag 'shoppe/printable', :media => :all
6
+ :javascript
7
+ window.print();
8
+ %body
9
+ #content
10
+ = yield
11
+
@@ -17,6 +17,6 @@
17
17
  - for price in @delivery_service_prices
18
18
  %tr
19
19
  %td= link_to number_to_currency(price.price), [:edit, @delivery_service, price]
20
- %td #{price.min_weight}kg &rarr; #{price.max_weight}kg
20
+ %td #{number_to_weight price.min_weight} &rarr; #{number_to_weight price.max_weight}
21
21
  %td= price.code
22
22
 
@@ -8,5 +8,5 @@ We will e-mail you again when we ship your order from our warehouse.
8
8
 
9
9
  Many thanks,
10
10
 
11
- <%=Shoppe.config[:store_name]%>
12
- <%=Shoppe.config[:email_address]%>
11
+ <%=Shoppe.settings.store_name%>
12
+ <%=Shoppe.settings.email_address%>