nimbleshop_core 0.0.1.rc1

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 (359) hide show
  1. data/README.md +13 -0
  2. data/Rakefile +15 -0
  3. data/app/assets/images/engines/nimbleshop_authorizedotnet/american_express.png +0 -0
  4. data/app/assets/images/engines/nimbleshop_authorizedotnet/authorize_net_big.png +0 -0
  5. data/app/assets/images/engines/nimbleshop_authorizedotnet/authorizedotnet_big.png +0 -0
  6. data/app/assets/images/engines/nimbleshop_authorizedotnet/discover.png +0 -0
  7. data/app/assets/images/engines/nimbleshop_authorizedotnet/mastercard.png +0 -0
  8. data/app/assets/images/engines/nimbleshop_authorizedotnet/visa.png +0 -0
  9. data/app/assets/images/engines/nimbleshop_cod/cod_small.png +0 -0
  10. data/app/assets/images/engines/nimbleshop_paypalwp/paypal_big.png +0 -0
  11. data/app/assets/images/engines/nimbleshop_paypalwp/paypal_small.png +0 -0
  12. data/app/assets/images/engines/nimbleshop_splitable/splitable.png +0 -0
  13. data/app/assets/images/engines/nimbleshop_splitable/splitable_big.png +0 -0
  14. data/app/assets/images/engines/nimbleshop_splitable/splitable_small.png +0 -0
  15. data/app/assets/javascripts/admin/products/edit.js.coffee +19 -0
  16. data/app/assets/javascripts/admin/shipping_methods/edit.js.coffee +6 -0
  17. data/app/assets/javascripts/admin.js +25 -0
  18. data/app/assets/javascripts/fadeout_success.js.coffee +2 -0
  19. data/app/assets/javascripts/payment_method.js.coffee +19 -0
  20. data/app/assets/javascripts/product-group-condition.js.coffee +33 -0
  21. data/app/assets/javascripts/remove_deletion_of_product_pictures.js.coffee +5 -0
  22. data/app/assets/javascripts/shipit.js.coffee +10 -0
  23. data/app/assets/javascripts/twitter_bootstrap.js.coffee +4 -0
  24. data/app/assets/stylesheets/admin.css +9 -0
  25. data/app/assets/stylesheets/admin_bootstrap_and_overrides.css.less +38 -0
  26. data/app/assets/stylesheets/admin_custom.css +104 -0
  27. data/app/assets/twitter/bootstrap/glyphicons-halflings-white.png +0 -0
  28. data/app/assets/twitter/bootstrap/glyphicons-halflings.png +0 -0
  29. data/app/controllers/admin/custom_fields_controller.rb +56 -0
  30. data/app/controllers/admin/link_groups_controller.rb +76 -0
  31. data/app/controllers/admin/main_controller.rb +9 -0
  32. data/app/controllers/admin/navigations_controller.rb +49 -0
  33. data/app/controllers/admin/orders_controller.rb +47 -0
  34. data/app/controllers/admin/payment_methods_controller.rb +26 -0
  35. data/app/controllers/admin/product_groups_controller.rb +70 -0
  36. data/app/controllers/admin/products_controller.rb +71 -0
  37. data/app/controllers/admin/shipments_controller.rb +19 -0
  38. data/app/controllers/admin/shipping_methods_controller.rb +93 -0
  39. data/app/controllers/admin/shipping_zones_controller.rb +62 -0
  40. data/app/controllers/admin/shops_controller.rb +33 -0
  41. data/app/controllers/admin_controller.rb +38 -0
  42. data/app/helpers/admin_helper.rb +83 -0
  43. data/app/helpers/nimbleshop_helper.rb +43 -0
  44. data/app/helpers/payment_method_helper.rb +52 -0
  45. data/app/mailers/admin_mailer.rb +22 -0
  46. data/app/mailers/mailer.rb +31 -0
  47. data/app/models/address.rb +69 -0
  48. data/app/models/country_shipping_zone.rb +36 -0
  49. data/app/models/creditcard.rb +95 -0
  50. data/app/models/custom_field.rb +8 -0
  51. data/app/models/custom_field_answer/field.rb +101 -0
  52. data/app/models/custom_field_answer.rb +17 -0
  53. data/app/models/line_item.rb +48 -0
  54. data/app/models/link.rb +3 -0
  55. data/app/models/link_group.rb +8 -0
  56. data/app/models/navigation.rb +7 -0
  57. data/app/models/order.rb +158 -0
  58. data/app/models/payment_method.rb +20 -0
  59. data/app/models/payment_transaction.rb +11 -0
  60. data/app/models/picture.rb +30 -0
  61. data/app/models/product.rb +76 -0
  62. data/app/models/product_group.rb +65 -0
  63. data/app/models/product_group_condition.rb +8 -0
  64. data/app/models/regional_shipping_zone.rb +25 -0
  65. data/app/models/shipment.rb +19 -0
  66. data/app/models/shipment_carrier.rb +3 -0
  67. data/app/models/shipping_cost_calculator.rb +9 -0
  68. data/app/models/shipping_method.rb +103 -0
  69. data/app/models/shipping_zone.rb +9 -0
  70. data/app/models/shop.rb +26 -0
  71. data/app/models/tax_calculator.rb +18 -0
  72. data/app/observers/order_observer.rb +53 -0
  73. data/app/uploaders/picture_uploader.rb +65 -0
  74. data/app/views/admin/custom_fields/_form.html.erb +45 -0
  75. data/app/views/admin/custom_fields/edit.html.erb +7 -0
  76. data/app/views/admin/custom_fields/index.html.erb +31 -0
  77. data/app/views/admin/custom_fields/new.html.erb +7 -0
  78. data/app/views/admin/link_groups/_form.html.erb +31 -0
  79. data/app/views/admin/link_groups/_link_group.html.erb +50 -0
  80. data/app/views/admin/link_groups/_link_group_title.html.erb +5 -0
  81. data/app/views/admin/link_groups/edit.html.erb +8 -0
  82. data/app/views/admin/link_groups/index.html.erb +29 -0
  83. data/app/views/admin/link_groups/new.html.erb +9 -0
  84. data/app/views/admin/mailer/new_order_notification.text.erb +31 -0
  85. data/app/views/admin/main/index.html.erb +5 -0
  86. data/app/views/admin/navigations/new.html.erb +29 -0
  87. data/app/views/admin/orders/_line_item.html.erb +11 -0
  88. data/app/views/admin/orders/_line_items.html.erb +39 -0
  89. data/app/views/admin/orders/_payment_info.html.erb +20 -0
  90. data/app/views/admin/orders/_shipping_info.html.erb +40 -0
  91. data/app/views/admin/orders/index.html.erb +33 -0
  92. data/app/views/admin/orders/show.html.erb +40 -0
  93. data/app/views/admin/payment_methods/index.html.erb +6 -0
  94. data/app/views/admin/product_groups/_condition.html.mustache +20 -0
  95. data/app/views/admin/product_groups/_form.html.erb +72 -0
  96. data/app/views/admin/product_groups/edit.html.erb +7 -0
  97. data/app/views/admin/product_groups/index.html.erb +30 -0
  98. data/app/views/admin/product_groups/new.html.erb +7 -0
  99. data/app/views/admin/product_groups/show.html.erb +9 -0
  100. data/app/views/admin/products/_custom_field_answer.html.erb +9 -0
  101. data/app/views/admin/products/_form.html.erb +69 -0
  102. data/app/views/admin/products/_handle_pictures.html.erb +32 -0
  103. data/app/views/admin/products/_pictures.html.erb +33 -0
  104. data/app/views/admin/products/edit.html.erb +26 -0
  105. data/app/views/admin/products/index.html.erb +34 -0
  106. data/app/views/admin/products/new.html.erb +9 -0
  107. data/app/views/admin/shipping_methods/_form.html.erb +58 -0
  108. data/app/views/admin/shipping_methods/_shipping_method.html.erb +31 -0
  109. data/app/views/admin/shipping_methods/edit.html.erb +18 -0
  110. data/app/views/admin/shipping_methods/new.html.erb +7 -0
  111. data/app/views/admin/shipping_zones/_form.html.erb +31 -0
  112. data/app/views/admin/shipping_zones/_shipping_method.html.erb +13 -0
  113. data/app/views/admin/shipping_zones/_shipping_zone.html.erb +47 -0
  114. data/app/views/admin/shipping_zones/edit.html.erb +8 -0
  115. data/app/views/admin/shipping_zones/index.html.erb +16 -0
  116. data/app/views/admin/shipping_zones/new.html.erb +8 -0
  117. data/app/views/admin/shops/edit.html.erb +119 -0
  118. data/app/views/layouts/_admin_footer.html.erb +23 -0
  119. data/app/views/layouts/_admin_sidebar.html.erb +0 -0
  120. data/app/views/layouts/_container.html.erb +33 -0
  121. data/app/views/layouts/_top_nav_bar.html.erb +30 -0
  122. data/app/views/layouts/admin.html.erb +35 -0
  123. data/app/views/layouts/payment_method.html.erb +12 -0
  124. data/app/views/mailer/order_notification_to_buyer.text.erb +31 -0
  125. data/app/views/mailer/shipment_notification_to_buyer.text.erb +34 -0
  126. data/config/initializers/001_settings_application.rb +10 -0
  127. data/config/initializers/002_load_core_extensions.rb +8 -0
  128. data/config/initializers/field_with_error.rb +2 -0
  129. data/config/initializers/strip_and_nullify.rb +13 -0
  130. data/config/initializers/time_formats.rb +1 -0
  131. data/config/locales/en.yml +61 -0
  132. data/config/routes.rb +56 -0
  133. data/db/development.sqlite3 +0 -0
  134. data/db/migrate/20111022144421_create_product_groups.rb +12 -0
  135. data/db/migrate/20111022144426_create_products.rb +16 -0
  136. data/db/migrate/20111022144653_create_orders.rb +21 -0
  137. data/db/migrate/20111022144725_create_line_items.rb +15 -0
  138. data/db/migrate/20111022234951_create_shops.rb +20 -0
  139. data/db/migrate/20111026193227_create_link_groups.rb +12 -0
  140. data/db/migrate/20111026193435_create_navigations.rb +10 -0
  141. data/db/migrate/20111031135810_create_links.rb +10 -0
  142. data/db/migrate/20111106193938_create_custom_fields.rb +10 -0
  143. data/db/migrate/20111106195112_create_custom_field_answers.rb +14 -0
  144. data/db/migrate/20111106201548_create_product_group_conditions.rb +12 -0
  145. data/db/migrate/20111107035350_create_creditcard_transactions.rb +15 -0
  146. data/db/migrate/20111109190754_create_addresses.rb +24 -0
  147. data/db/migrate/20111125173344_create_pictures.rb +16 -0
  148. data/db/migrate/20111201024408_create_shipping_methods.rb +16 -0
  149. data/db/migrate/20111202143154_create_shipping_zones.rb +17 -0
  150. data/db/migrate/20111203034020_create_payment_methods.rb +14 -0
  151. data/db/migrate/20111221190000_create_preferences.rb +14 -0
  152. data/db/migrate/20120105234047_create_shipments.rb +11 -0
  153. data/db/migrate/20120105234553_create_shipment_carriers.rb +11 -0
  154. data/db/migrate/20120606165355_create_delayed_jobs.rb +22 -0
  155. data/db/production.sqlite3 +0 -0
  156. data/db/schema.rb +265 -0
  157. data/db/seeds.rb +1 -0
  158. data/db/test.sqlite3 +0 -0
  159. data/lib/assets/javascripts/loading_state_for_buttons.js.coffee +3 -0
  160. data/lib/assets/javascripts/show_help_on_hover.js.coffee +2 -0
  161. data/lib/assets/javascripts/utils/autoresize.js.coffee +3 -0
  162. data/lib/assets/javascripts/utils/focus.js.coffee +3 -0
  163. data/lib/assets/javascripts/utils/formatNumber.js.coffee +25 -0
  164. data/lib/assets/javascripts/utils/formatPrice.js.coffee +24 -0
  165. data/lib/generators/nimbleshop/app/app_generator.rb +84 -0
  166. data/lib/generators/nimbleshop/app/templates/config/application.yml +61 -0
  167. data/lib/generators/nimbleshop/app/templates/config/initializers/airbrake.rb +3 -0
  168. data/lib/generators/nimbleshop/app/templates/config/initializers/cache_images.rb +4 -0
  169. data/lib/generators/nimbleshop/app/templates/config/initializers/carrierwave.rb +36 -0
  170. data/lib/generators/nimbleshop/app/templates/config/initializers/delayed_job.rb +15 -0
  171. data/lib/generators/nimbleshop/app/templates/config/initializers/setup_email.rb +24 -0
  172. data/lib/nimbleshop/core_ext/activerecord_base.rb +18 -0
  173. data/lib/nimbleshop/core_ext/filelessio.rb +4 -0
  174. data/lib/nimbleshop/core_ext/force_ssl.rb +26 -0
  175. data/lib/nimbleshop/core_ext/mustache_templater_handler.rb +10 -0
  176. data/lib/nimbleshop/engine.rb +23 -0
  177. data/lib/nimbleshop/permalink/builder.rb +46 -0
  178. data/lib/nimbleshop/processor/base.rb +51 -0
  179. data/lib/nimbleshop/processor.rb +3 -0
  180. data/lib/nimbleshop/product_group_search/base_field.rb +19 -0
  181. data/lib/nimbleshop/product_group_search/core_field_strategy.rb +31 -0
  182. data/lib/nimbleshop/product_group_search/custom_field_strategy.rb +39 -0
  183. data/lib/nimbleshop/product_group_search/date_field.rb +16 -0
  184. data/lib/nimbleshop/product_group_search/extension.rb +46 -0
  185. data/lib/nimbleshop/product_group_search/number_field.rb +17 -0
  186. data/lib/nimbleshop/product_group_search/text_field.rb +33 -0
  187. data/lib/nimbleshop/product_group_search.rb +74 -0
  188. data/lib/nimbleshop/sampledata/data.rb +246 -0
  189. data/lib/nimbleshop/sampledata/pictures/product1/pic1.jpg +0 -0
  190. data/lib/nimbleshop/sampledata/pictures/product2/pic1.jpg +0 -0
  191. data/lib/nimbleshop/sampledata/pictures/product2/pic2.jpg +0 -0
  192. data/lib/nimbleshop/sampledata/pictures/product3/pic1.jpg +0 -0
  193. data/lib/nimbleshop/sampledata/pictures/product3/pic2.jpg +0 -0
  194. data/lib/nimbleshop/sampledata/pictures/product3/pic3.jpg +0 -0
  195. data/lib/nimbleshop/sampledata/pictures/product3/pic4.jpg +0 -0
  196. data/lib/nimbleshop/sampledata/pictures/product3/pic5.jpg +0 -0
  197. data/lib/nimbleshop/sampledata/pictures/product4/pic1.jpg +0 -0
  198. data/lib/nimbleshop/sampledata/pictures/product4/pic2.jpg +0 -0
  199. data/lib/nimbleshop/sampledata/pictures/product5/pic1.jpg +0 -0
  200. data/lib/nimbleshop/sampledata/pictures/product5/pic2.jpg +0 -0
  201. data/lib/nimbleshop/sampledata/pictures/product6/pic1.jpg +0 -0
  202. data/lib/nimbleshop/sampledata/pictures/product6/pic10.jpg +0 -0
  203. data/lib/nimbleshop/sampledata/pictures/product6/pic11.jpg +0 -0
  204. data/lib/nimbleshop/sampledata/pictures/product6/pic12.jpg +0 -0
  205. data/lib/nimbleshop/sampledata/pictures/product6/pic13.jpg +0 -0
  206. data/lib/nimbleshop/sampledata/pictures/product6/pic14.jpg +0 -0
  207. data/lib/nimbleshop/sampledata/pictures/product6/pic15.jpg +0 -0
  208. data/lib/nimbleshop/sampledata/pictures/product6/pic16.jpg +0 -0
  209. data/lib/nimbleshop/sampledata/pictures/product6/pic17.jpg +0 -0
  210. data/lib/nimbleshop/sampledata/pictures/product6/pic2.jpg +0 -0
  211. data/lib/nimbleshop/sampledata/pictures/product6/pic3.jpg +0 -0
  212. data/lib/nimbleshop/sampledata/pictures/product6/pic4.jpg +0 -0
  213. data/lib/nimbleshop/sampledata/pictures/product6/pic5.jpg +0 -0
  214. data/lib/nimbleshop/sampledata/pictures/product6/pic6.jpg +0 -0
  215. data/lib/nimbleshop/sampledata/pictures/product6/pic7.jpg +0 -0
  216. data/lib/nimbleshop/sampledata/pictures/product6/pic8.jpg +0 -0
  217. data/lib/nimbleshop/sampledata/pictures/product6/pic9.jpg +0 -0
  218. data/lib/nimbleshop/sampledata/pictures/product7/pic1.jpg +0 -0
  219. data/lib/nimbleshop/sampledata/pictures/product7/pic2.jpg +0 -0
  220. data/lib/nimbleshop/sampledata/pictures/product7/pic3.jpg +0 -0
  221. data/lib/nimbleshop/sampledata/pictures/product8/pic1.jpg +0 -0
  222. data/lib/nimbleshop/sampledata/pictures/product8/pic2.jpg +0 -0
  223. data/lib/nimbleshop/sampledata/pictures/product8/pic3.jpg +0 -0
  224. data/lib/nimbleshop/sampledata/pictures/product8/pic4.jpg +0 -0
  225. data/lib/nimbleshop/sampledata/pictures/product8/pic5.jpg +0 -0
  226. data/lib/nimbleshop/sampledata/pictures/product8/pic6.jpg +0 -0
  227. data/lib/nimbleshop/sampledata/pictures/product8/pic7.jpg +0 -0
  228. data/lib/nimbleshop/sampledata/pictures/product8/pic8.jpg +0 -0
  229. data/lib/nimbleshop/sampledata/pictures/product9/pic1.jpg +0 -0
  230. data/lib/nimbleshop/sampledata/pictures/product9/pic2.jpg +0 -0
  231. data/lib/nimbleshop/util.rb +60 -0
  232. data/lib/nimbleshop/version.rb +18 -0
  233. data/lib/nimbleshop_core.rb +23 -0
  234. data/lib/tasks/localhost2public.rake +8 -0
  235. data/lib/tasks/setup.rake +26 -0
  236. data/test/factories/address_factory.rb +31 -0
  237. data/test/factories/creditcard_factory.rb +30 -0
  238. data/test/factories/custom_field_answer_factory.rb +6 -0
  239. data/test/factories/custom_field_factory.rb +21 -0
  240. data/test/factories/line_item_factory.rb +7 -0
  241. data/test/factories/link_factory.rb +6 -0
  242. data/test/factories/link_group_factory.rb +5 -0
  243. data/test/factories/navigation_factory.rb +6 -0
  244. data/test/factories/order_factory.rb +49 -0
  245. data/test/factories/payment_method_factory.rb +6 -0
  246. data/test/factories/payment_transaction_factory.rb +42 -0
  247. data/test/factories/picture_factory.rb +11 -0
  248. data/test/factories/product_group_condition_factory.rb +40 -0
  249. data/test/factories/product_group_factory.rb +5 -0
  250. data/test/factories/products_factory.rb +11 -0
  251. data/test/factories/shipment_carrier_factory.rb +6 -0
  252. data/test/factories/shipment_factory.rb +6 -0
  253. data/test/factories/shipping_method_factory.rb +15 -0
  254. data/test/factories/shipping_zone_factory.rb +5 -0
  255. data/test/factories/shop_factory.rb +8 -0
  256. data/test/fixtures/files/avatar.png +0 -0
  257. data/test/fixtures/link_groups.yml +13 -0
  258. data/test/fixtures/payment_methods.yml +39 -0
  259. data/test/fixtures/shops.yml +15 -0
  260. data/test/helpers/admin_helper_test.rb +37 -0
  261. data/test/helpers/nimbleshop_helper_test.rb +17 -0
  262. data/test/integration/admin/link_groups_acceptance_test.rb +39 -0
  263. data/test/integration/admin/orders_acceptance_test.rb +63 -0
  264. data/test/integration/admin/payment_methods_acceptance_test.rb +13 -0
  265. data/test/integration/admin/product_groups_acceptance_test.rb +89 -0
  266. data/test/integration/admin/products_acceptance_test.rb +105 -0
  267. data/test/integration/admin/shipping_methods_acceptance_test.rb +63 -0
  268. data/test/integration/admin/shipping_zones_acceptance_test.rb +16 -0
  269. data/test/integration/admin/shops_acceptance_test.rb +44 -0
  270. data/test/integration/checkout/cart_acceptance_test.rb +113 -0
  271. data/test/integration/checkout/payment_confirmation_acceptance_test.rb +24 -0
  272. data/test/integration/checkout/paypal_acceptance_test.rb +34 -0
  273. data/test/integration/checkout/shipping_address_acceptance_test.rb +91 -0
  274. data/test/integration/checkout/shipping_method_acceptance_test.rb +51 -0
  275. data/test/integration/homepage_acceptance_test.rb +24 -0
  276. data/test/integration/products_acceptance_test.rb +12 -0
  277. data/test/integration/static_pages_acceptance_test.rb +13 -0
  278. data/test/mailers/mailer_test.rb +25 -0
  279. data/test/rails_app/Gemfile +27 -0
  280. data/test/rails_app/Gemfile.lock +218 -0
  281. data/test/rails_app/Rakefile +10 -0
  282. data/test/rails_app/app/controllers/application_controller.rb +6 -0
  283. data/test/rails_app/app/helpers/application_helper.rb +3 -0
  284. data/test/rails_app/app/views/layouts/application.html.erb +10 -0
  285. data/test/rails_app/config/application.rb +25 -0
  286. data/test/rails_app/config/application.yml +61 -0
  287. data/test/rails_app/config/boot.rb +5 -0
  288. data/test/rails_app/config/database.yml +18 -0
  289. data/test/rails_app/config/environment.rb +5 -0
  290. data/test/rails_app/config/environments/development.rb +18 -0
  291. data/test/rails_app/config/environments/production.rb +33 -0
  292. data/test/rails_app/config/environments/test.rb +33 -0
  293. data/test/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  294. data/test/rails_app/config/initializers/inflections.rb +2 -0
  295. data/test/rails_app/config/initializers/secret_token.rb +2 -0
  296. data/test/rails_app/config/routes.rb +10 -0
  297. data/test/rails_app/config.ru +4 -0
  298. data/test/rails_app/db/development.sqlite3 +0 -0
  299. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +74 -0
  300. data/test/rails_app/db/schema.rb +52 -0
  301. data/test/rails_app/log/development.log +94 -0
  302. data/test/rails_app/log/test.log +0 -0
  303. data/test/rails_app/public/404.html +26 -0
  304. data/test/rails_app/public/422.html +26 -0
  305. data/test/rails_app/public/500.html +26 -0
  306. data/test/rails_app/public/favicon.ico +0 -0
  307. data/test/rails_app/script/rails +10 -0
  308. data/test/support/address_test_helper.rb +24 -0
  309. data/test/support/checkout_test_helper.rb +40 -0
  310. data/test/support/dbify_sql_helper.rb +12 -0
  311. data/test/support/images/cookware.jpg +0 -0
  312. data/test/support/must_be_like.rb +24 -0
  313. data/test/support/shipping_method_test_helper.rb +5 -0
  314. data/test/support/wait_for_ajax.rb +4 -0
  315. data/test/test_helper.rb +65 -0
  316. data/test/unit/address_test.rb +33 -0
  317. data/test/unit/country_shipping_zone_test.rb +17 -0
  318. data/test/unit/creditcard_test.rb +33 -0
  319. data/test/unit/custom_field_answer/field_test.rb +93 -0
  320. data/test/unit/order_test.rb +70 -0
  321. data/test/unit/payment_method/authorizedotnet_test.rb +21 -0
  322. data/test/unit/payment_method/paypalwp_test.rb +17 -0
  323. data/test/unit/payment_method/splitable_test.rb +18 -0
  324. data/test/unit/picture_test.rb +24 -0
  325. data/test/unit/processor/authorize_net_test.rb +236 -0
  326. data/test/unit/processor/paypal_test.rb +40 -0
  327. data/test/unit/processor/splitable_test.rb +123 -0
  328. data/test/unit/product_group_condition_test.rb +188 -0
  329. data/test/unit/product_group_test.rb +109 -0
  330. data/test/unit/product_test.rb +60 -0
  331. data/test/unit/shipping_cost_calculator_test.rb +19 -0
  332. data/test/unit/shipping_method_test.rb +197 -0
  333. data/test/unit/shop_test.rb +11 -0
  334. data/test/unit/tax_calculator_test.rb +13 -0
  335. data/test/vcr_cassettes/authorize_net/authorize-failure.yml +38 -0
  336. data/test/vcr_cassettes/authorize_net/authorize-success.yml +38 -0
  337. data/test/vcr_cassettes/authorize_net/capture-failure.yml +38 -0
  338. data/test/vcr_cassettes/authorize_net/capture-success.yml +38 -0
  339. data/test/vcr_cassettes/authorize_net/purchase-failure.yml +38 -0
  340. data/test/vcr_cassettes/authorize_net/purchase-success.yml +38 -0
  341. data/test/vcr_cassettes/authorize_net/refund-failure.yml +38 -0
  342. data/test/vcr_cassettes/authorize_net/refund-success.yml +38 -0
  343. data/test/vcr_cassettes/authorize_net/void-authorize.yml +38 -0
  344. data/test/vcr_cassettes/authorize_net/void-failure.yml +38 -0
  345. data/test/vcr_cassettes/authorize_net/void-success.yml +38 -0
  346. data/test/vcr_cassettes/splitable/split-create-failure.yml +48 -0
  347. data/test/vcr_cassettes/splitable/split-create-success.yml +50 -0
  348. data/test/vcr_cassettes/splitable/split-draft-create-failure.yml +50 -0
  349. data/test/vcr_cassettes/splitable/split-draft-create-success.yml +50 -0
  350. data/vendor/assets/javascripts/accounting.js +406 -0
  351. data/vendor/assets/javascripts/autoresize.js +275 -0
  352. data/vendor/assets/javascripts/jquery-1.7.1.js +9267 -0
  353. data/vendor/assets/javascripts/jquery-form.js +980 -0
  354. data/vendor/assets/javascripts/jquery-json.js +193 -0
  355. data/vendor/assets/javascripts/jquery-ui-1.8.16.js +11768 -0
  356. data/vendor/assets/javascripts/jquery-ujs.js +374 -0
  357. data/vendor/assets/javascripts/mustache.js +436 -0
  358. data/vendor/assets/javascripts/nested_form.js +51 -0
  359. metadata +740 -0
@@ -0,0 +1,70 @@
1
+ class Admin::ProductGroupsController < AdminController
2
+
3
+ before_filter :load_product_group, only: [:edit, :update, :destroy]
4
+
5
+ respond_to :html
6
+
7
+ def index
8
+ @product_groups = ProductGroup.order('name asc')
9
+ respond_with @product_groups
10
+ end
11
+
12
+ def new
13
+ @product_group = ProductGroup.new
14
+ @product_group.product_group_conditions.build
15
+ respond_with @product_group
16
+ end
17
+
18
+ def create
19
+ respond_to do |format|
20
+ format.html do
21
+
22
+ @product_group = ProductGroup.new(post_params[:product_group])
23
+ if @product_group.save
24
+ redirect_to admin_product_groups_path, notice: t(:successfully_updated)
25
+ else
26
+ render action: 'new'
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+
33
+ def edit
34
+ @custom_fields = CustomField.order('name asc')
35
+ respond_with @product_group
36
+ end
37
+
38
+ def update
39
+ respond_to do |format|
40
+ format.html do
41
+
42
+ if @product_group.update_attributes(post_params[:product_group])
43
+ redirect_to admin_product_groups_path, notice: t(:successfully_updated)
44
+ else
45
+ render action: 'edit'
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
52
+ def destroy
53
+ if @product_group.destroy
54
+ redirect_to admin_product_groups_path, notice: t(:successfully_deleted)
55
+ else
56
+ respond_with @product_group
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def post_params
63
+ params.permit(product_group: [:name, :product_group_conditions_attributes])
64
+ end
65
+
66
+ def load_product_group
67
+ @product_group = ProductGroup.find_by_permalink!(params[:id])
68
+ end
69
+
70
+ end
@@ -0,0 +1,71 @@
1
+ class Admin::ProductsController < AdminController
2
+
3
+ before_filter :load_product!, only: [:edit, :update, :destroy ]
4
+
5
+ respond_to :html
6
+
7
+ def index
8
+ @products = Product.order(:id)
9
+ respond_with @products
10
+ end
11
+
12
+ def new
13
+ @products = Product.order(:id)
14
+ @product = Product.new
15
+ @product.pictures.build
16
+ @product.find_or_build_all_answers
17
+ respond_with @product
18
+ end
19
+
20
+ def edit
21
+ @product_groups = ProductGroup.contains_product(@product)
22
+ @product.find_or_build_all_answers
23
+ respond_with @products
24
+ end
25
+
26
+ def create
27
+ respond_to do |format|
28
+ format.html do
29
+
30
+ @product = Product.new(post_params[:product])
31
+ if @product.save
32
+ redirect_to edit_admin_product_path(@product), notice: t(:successfully_added)
33
+ else
34
+ render action: 'new'
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+
41
+ def update
42
+ respond_to do |format|
43
+ format.html do
44
+
45
+ @product_groups = ProductGroup.contains_product(@product)
46
+ if @product.update_attributes(post_params[:product])
47
+ redirect_to edit_admin_product_path(@product), notice: t(:successfully_updated)
48
+ else
49
+ respond_with @product
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+
56
+ def destroy
57
+ @product.destroy
58
+ redirect_to admin_products_url, notice: t(:successfully_deleted)
59
+ end
60
+
61
+ private
62
+
63
+ def post_params
64
+ params.permit(product: [:pictures_attributes, :name, :status, :description, :price, :new, :pictures_order, :custom_field_answers_attributes] )
65
+ end
66
+
67
+ def load_product!
68
+ @product = Product.find_by_permalink!(params[:id])
69
+ end
70
+
71
+ end
@@ -0,0 +1,19 @@
1
+ class Admin::ShipmentsController < AdminController
2
+
3
+ def create
4
+ @order = Order.find_by_number!(params[:order_id])
5
+ @shipment = @order.shipments.build(params[:shipment])
6
+
7
+ respond_to do |format|
8
+ format.html do
9
+
10
+ if @shipment.save
11
+ @order.shipped
12
+ redirect_to admin_order_path(@order)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,93 @@
1
+ class Admin::ShippingMethodsController < AdminController
2
+
3
+ before_filter :load_shipping_zone
4
+ before_filter :load_shipping_method, except: [:new, :create, :enable]
5
+
6
+ respond_to :html
7
+
8
+ def update_offset
9
+ @shipping_method.update_offset(params[:offset])
10
+ render json: { html: render_shipping_method(@shipping_method) }
11
+ end
12
+
13
+ def disable
14
+ @shipping_method.disable!
15
+ render json: { html: render_shipping_method(@shipping_method) }
16
+ end
17
+
18
+ def enable
19
+ @shipping_method = ShippingMethod.where(shipping_zone_id: @shipping_zone.id, id: params[:id]).first
20
+
21
+ @shipping_method.enable!
22
+ render json: { html: render_shipping_method(@shipping_method) }
23
+ end
24
+
25
+ def new
26
+ @shipping_method = @shipping_zone.shipping_methods.build
27
+ respond_with @shipping_method
28
+ end
29
+
30
+ def edit
31
+ respond_with @shipping_method
32
+ end
33
+
34
+ def create
35
+ respond_to do |format|
36
+ format.html do
37
+
38
+ @shipping_method = @shipping_zone.shipping_methods.build(params[:shipping_method])
39
+ if @shipping_method.save
40
+ redirect_to admin_shipping_zones_path, notice: t(:successfully_created)
41
+ else
42
+ render action: :new
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+
49
+ def update
50
+ respond_to do |format|
51
+ format.html do
52
+
53
+ @shipping_method = @shipping_zone.shipping_methods.find(params[:id])
54
+
55
+ if @shipping_method.update_attributes(params[:shipping_method])
56
+ redirect_to [:edit, :admin, @shipping_zone, @shipping_method], notice: t(:successfully_updated)
57
+ else
58
+ render action: :new
59
+ end
60
+
61
+ end
62
+ end
63
+ end
64
+
65
+ def destroy
66
+ if @shipping_method.update_attributes(active: false)
67
+ redirect_to admin_shipping_zones_path, notice: t(:successfully_deleted)
68
+ else
69
+ redirect_to admin_shipping_zones_path, error: t(:could_not_delete)
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def load_shipping_method
76
+ @shipping_method = @shipping_zone.shipping_methods.find_by_id!(params[:id])
77
+ end
78
+
79
+ def load_shipping_zone
80
+ @shipping_zone = ShippingZone.find_by_permalink!(shipping_zone_param)
81
+ end
82
+
83
+ def shipping_zone_param
84
+ params[:country_shipping_zone_id] ||
85
+ params[:regional_shipping_zone_id] ||
86
+ params[:shipping_zone_id]
87
+ end
88
+
89
+ def render_shipping_method(shipping_method)
90
+ render_to_string(partial: 'admin/shipping_methods/shipping_method', locals: { shipping_method: shipping_method })
91
+ end
92
+
93
+ end
@@ -0,0 +1,62 @@
1
+ class Admin::ShippingZonesController < AdminController
2
+
3
+ before_filter :load_shipping_zone, only: [:edit, :update, :destroy]
4
+
5
+ respond_to :html
6
+
7
+ def index
8
+ @shipping_zones = CountryShippingZone.order('name asc')
9
+ respond_with @shipping_zones
10
+ end
11
+
12
+ def new
13
+ @shipping_zone = ShippingZone.new
14
+ respond_with @shipping_zone
15
+ end
16
+
17
+ def edit
18
+ respond_with @shipping_zone
19
+ end
20
+
21
+ def update
22
+ if @shipping_zone.update_attributes(post_params[:shipping_zone])
23
+ redirect_to admin_shipping_zones_path, notice: t(:successfully_updated)
24
+ else
25
+ respond_with @shipping_zone
26
+ end
27
+ end
28
+
29
+ def create
30
+ @shipping_zone = CountryShippingZone.new(post_params[:shipping_zone])
31
+ if @shipping_zone.save
32
+ redirect_to admin_shipping_zones_path, notice: t(:successfully_created)
33
+ else
34
+ respond_with @shipping_zone
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ respond_to do |format|
40
+ format.html do
41
+
42
+ if @shipping_zone.destroy
43
+ redirect_to admin_shipping_zones_path, notice: t(:successfully_deleted)
44
+ else
45
+ redirect_to admin_shipping_zones_path, error: t(:could_not_delete)
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def post_params
55
+ params.permit(shipping_zone: [ :name, :country_code, :state_code, :country_shipping_zone_id])
56
+ end
57
+
58
+ def load_shipping_zone
59
+ @shipping_zone = ShippingZone.find_by_permalink!(params[:id])
60
+ end
61
+
62
+ end
@@ -0,0 +1,33 @@
1
+ class Admin::ShopsController < AdminController
2
+
3
+ respond_to :html
4
+
5
+ def edit
6
+ respond_with(:admin, current_shop)
7
+ end
8
+
9
+ def update
10
+ if current_shop.update_attributes(post_params[:shop])
11
+ redirect_to edit_admin_shop_path, notice: 'Shop was successfully updated'
12
+ else
13
+ respond_with(:admin, current_shop)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def post_params
20
+ params.permit(shop: [ :name,
21
+ :theme,
22
+ :author_name,
23
+ :description,
24
+ :time_zone,
25
+ :from_email,
26
+ :default_creditcard_action,
27
+ :twitter_handle,
28
+ :facebook_url,
29
+ :google_analytics_tracking_id,
30
+ :tax_percentage])
31
+ end
32
+
33
+ end
@@ -0,0 +1,38 @@
1
+ class AdminController < ::ApplicationController
2
+
3
+ layout 'admin'
4
+
5
+ before_filter :set_timezone
6
+ before_filter :restricted_access
7
+
8
+ helper_method :current_shop
9
+
10
+ private
11
+
12
+ def set_timezone
13
+ Time.zone = current_shop.time_zone
14
+ end
15
+
16
+ def restricted_access
17
+ return unless Nimbleshop.config.ask_admin_to_login
18
+
19
+ authenticate_or_request_with_http_basic('staging') { |username, password|
20
+ username == Nimbleshop.config.admin_email && password == Nimbleshop.config.admin_password
21
+ }
22
+ end
23
+
24
+ def delayed_job_admin_authentication
25
+ return true if Rails.env.development? || Rails.env.test?
26
+ end
27
+
28
+ def no_page_title
29
+ @do_not_use_page_title = true
30
+ end
31
+
32
+ def current_shop
33
+ @shop ||= Shop.first
34
+ raise "The database base is empty. Please run bundle exec rake setup first." unless @shop
35
+ @shop
36
+ end
37
+
38
+ end
@@ -0,0 +1,83 @@
1
+ module AdminHelper
2
+
3
+ ROUTE_MAP = {
4
+ admin_products_path: 'admin/products',
5
+ admin_custom_fields_path: 'admin/custom_fields',
6
+ admin_product_groups_path: 'admin/product_groups',
7
+ admin_link_groups_path: [ 'admin/link_groups', 'admin/navigations' ],
8
+ admin_payment_methods_path: 'admin/payment_methods',
9
+ admin_shipping_zones_path: [ 'admin/shipping_zones', 'admin/shipping_methods' ],
10
+ edit_admin_shop_path: 'admin/shops',
11
+ admin_orders_path: 'admin/orders'
12
+ }
13
+
14
+ def admin_topbar_active?(path, current_controller)
15
+ Array.wrap(ROUTE_MAP[path.to_sym]).include?(current_controller)
16
+ end
17
+
18
+ def admin_topbar(label, path, identifier)
19
+
20
+ html_options = {}
21
+
22
+ if admin_topbar_active?(identifier, params[:controller])
23
+ html_options['class'] = 'active'
24
+ end
25
+
26
+ content_tag(:li, link_to(label, path), html_options)
27
+ end
28
+
29
+ def display_payment_status(order)
30
+ css_klass = order.payment_status == 'purchased' ? 'label-success' : 'label-info'
31
+ %Q{<span class="label #{css_klass}"> #{order.payment_status.titleize.upcase} </span>}.html_safe
32
+ end
33
+
34
+ def display_shipping_status(order)
35
+ css_klass = case order.shipping_status
36
+ when 'shipped'
37
+ 'label-success'
38
+ when 'nothing_to_ship'
39
+ 'label-info'
40
+ when 'shipping_pending'
41
+ 'label-important'
42
+ end
43
+ %Q{<span class="label #{css_klass}"> #{order.shipping_status.titleize.upcase} </span>}.html_safe
44
+ end
45
+
46
+ def creditcard_logo_for(creditcard)
47
+ image_tag "#{creditcard.cardtype}.png"
48
+ end
49
+
50
+ def shipping_method_condition_in_english(shipping_method)
51
+ if shipping_method.maximum_order_amount
52
+ s = number_to_currency(shipping_method.minimum_order_amount)
53
+ s << " - "
54
+ s << number_to_currency(shipping_method.maximum_order_amount)
55
+ else
56
+ number_to_currency(shipping_method.minimum_order_amount) + ' minimum'
57
+ end
58
+ end
59
+
60
+ def gravatar_for(email, options = {})
61
+ return if email.blank?
62
+ options = { alt: 'avatar', class: 'avatar', size: 50 }.merge! options
63
+ id = Digest::MD5::hexdigest(email.strip.downcase)
64
+ url = 'http://www.gravatar.com/avatar/' + id + '.jpg?d=mm&s=' + options[:size].to_s
65
+ options.delete :size
66
+ image_tag url, options
67
+ end
68
+
69
+ def shipment_info(shipment)
70
+ if shipment.tracking_number.present?
71
+ link_to shipment.name + ' #' + shipment.tracking_number, shipment.tracking_url
72
+ else
73
+ shipment.name
74
+ end
75
+ end
76
+
77
+ def delete_icon
78
+ %Q{
79
+ <i class='icon-remove icon-black'></i>
80
+ }.html_safe
81
+ end
82
+
83
+ end
@@ -0,0 +1,43 @@
1
+ module NimbleshopHelper
2
+
3
+ def body_id
4
+ "#{params[:controller]}-#{params[:action]}".parameterize
5
+ end
6
+
7
+ def display_address(address)
8
+ return if address.nil?
9
+ address.full_address_array.map { |i| html_escape(i) }.join('<br />').html_safe
10
+ end
11
+
12
+ def display_page_title
13
+ if @page_title
14
+ @page_title.html_safe + "&mdash;".html_safe + html_escape(current_shop.name)
15
+ else
16
+ Shop.first.name
17
+ end
18
+ end
19
+
20
+ def page_title(title)
21
+ @page_title = title
22
+ end
23
+
24
+ def parent_layout(layout)
25
+ @view_flow.set(:layout,output_buffer)
26
+ self.output_buffer = render(file: "layouts/#{layout}")
27
+ end
28
+
29
+ def body_class
30
+ %|#{controller.controller_name} #{controller.controller_name}-#{controller.action_name}|
31
+ end
32
+
33
+ def grouped_options_for_country_state_codes
34
+ Carmen::Country.all.reduce({}) do |h, country|
35
+ h[country.alpha_2_code] = country.subregions.map do |r|
36
+ [r.name, r.code]
37
+ end
38
+ h
39
+ end
40
+ end
41
+
42
+
43
+ end
@@ -0,0 +1,52 @@
1
+ module PaymentMethodHelper
2
+
3
+ def next_payment_processing_action(order)
4
+ if pm = order.payment_method
5
+ call_engineized_method(pm, :next_payment_processing_action, order)
6
+ end
7
+ end
8
+
9
+ def order_show_extra_info(order)
10
+ if pm = order.payment_method
11
+ call_engineized_method(pm, :order_show_extra_info, order)
12
+ end
13
+ end
14
+
15
+ def available_payment_options_icons
16
+ PaymentMethod.order('id desc').map do |pm|
17
+ call_engineized_method(pm, :available_payment_options_icons)
18
+ end.compact.flatten
19
+ end
20
+
21
+ def icon_for_order_payment(order)
22
+ if pm = order.payment_method
23
+ call_engineized_method(pm, :icon_for_order_payment, order)
24
+ end
25
+ end
26
+
27
+ def payment_info_for_buyer(order)
28
+ if pm = order.payment_method
29
+ call_engineized_method(pm, :payment_info_for_buyer, order)
30
+ end
31
+ end
32
+
33
+ def nimbleshop_crud_form(payment_method)
34
+ call_engineized_method(payment_method, :crud_form)
35
+ end
36
+
37
+ def engineized_name(payment_method, method_name)
38
+ "nimbleshop_#{payment_method.demodulized_underscore}_#{method_name}".intern
39
+ end
40
+
41
+ def call_engineized_method(payment_method, method_name, *args)
42
+ method_name_in_engine = engineized_name(payment_method, method_name)
43
+ if self.respond_to?(method_name_in_engine)
44
+ if args.any?
45
+ self.send(method_name_in_engine, *args)
46
+ else
47
+ self.send(method_name_in_engine)
48
+ end
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,22 @@
1
+ class AdminMailer < ActionMailer::Base
2
+
3
+ include ApplicationHelper
4
+
5
+ default from: lambda { Shop.first.from_email }
6
+
7
+ default_url_options[:host] = Nimbleshop.config.host_for_email
8
+ default_url_options[:protocol] = 'http'
9
+
10
+ def new_order_notification(order_number)
11
+ @order = Order.find_by_number!(order_number)
12
+ @shop = Shop.first
13
+ @payment_date = @order.purchased_at
14
+
15
+ mail_options = { to: @order.email, subject: "Order ##{order_number} was recently placed" }
16
+
17
+ mail(mail_options) do |format|
18
+ format.text { render "admin/mailer/new_order_notification" }
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,31 @@
1
+ class Mailer < ActionMailer::Base
2
+
3
+ helper :application
4
+
5
+ layout 'email'
6
+
7
+ default from: lambda { Shop.first.from_email }
8
+ default_url_options[:host] = Nimbleshop.config.host_for_email
9
+ default_url_options[:protocol] = 'http'
10
+
11
+ def order_notification_to_buyer(order_number)
12
+ subject = "Order confirmation for order ##{order_number}"
13
+ @order = Order.find_by_number!(order_number)
14
+
15
+ @shop = Shop.first
16
+ @payment_date = @order.created_at.to_s(:long) || @order.purchased_at.to_s(:long)
17
+
18
+ mail_options = {to: @order.email, subject: subject}
19
+ mail(mail_options)
20
+ end
21
+
22
+ def shipment_notification_to_buyer(order_number)
23
+ subject = "Items for order ##{order_number} have been shipped"
24
+ @order = Order.find_by_number!(order_number)
25
+ @shipment = @order.shipments.first
26
+
27
+ mail_options = {to: @order.email, subject: subject}
28
+ mail(mail_options)
29
+ end
30
+
31
+ end
@@ -0,0 +1,69 @@
1
+ class Address < ActiveRecord::Base
2
+
3
+ validates_presence_of :first_name, :last_name, :address1, :zipcode, :country_code, :city
4
+
5
+ CREDIT_CARD_ATTRIBUTES = %w(address1 address2 zipcode first_name last_name)
6
+
7
+ belongs_to :order
8
+
9
+ validate :validate_and_set_country_name, :validate_and_set_state_name
10
+
11
+ def full_address_array
12
+ [name, address1, address2, city_state_zip, country_name].compact
13
+ end
14
+
15
+ def name
16
+ [first_name, last_name].compact.join(' ')
17
+ end
18
+
19
+ def address_lines(join_chars = ', ')
20
+ [address1, address2].delete_if { |add| add.blank? }.join(join_chars)
21
+ end
22
+
23
+ def city_state_name
24
+ [city, state_name].join(', ')
25
+ end
26
+
27
+ def city_state_zip
28
+ [city_state_name, zipcode].join(' ')
29
+ end
30
+
31
+ def to_credit_card_attributes
32
+ attributes.slice(*CREDIT_CARD_ATTRIBUTES).merge('state' => state_name)
33
+ end
34
+
35
+ private
36
+
37
+ def validate_and_set_country_name
38
+ if country = Carmen::Country.coded(country_code)
39
+ self.country_name = country.name
40
+ else
41
+ errors.add(:country_code, "#{country_code} is not a valid country code")
42
+ end
43
+ end
44
+
45
+ def validate_and_set_state_name
46
+ country = Carmen::Country.coded(country_code)
47
+ return unless country
48
+
49
+ if country.subregions?
50
+ if state_code.blank?
51
+ errors.add(:state_code, "is required")
52
+ elsif state = country.subregions.coded(state_code)
53
+ self.state_name = state.name
54
+ else
55
+ errors.add(:state_code, "#{state_code} is not a valid state")
56
+ end
57
+ else
58
+ if state_name.blank?
59
+ errors.add(:state_name, "#{state_name} is required")
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ class BillingAddress < Address
66
+ end
67
+
68
+ class ShippingAddress < Address
69
+ end