nimbleshop_core 0.0.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
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,36 @@
1
+ class CountryShippingZone < ShippingZone
2
+
3
+ has_many :regional_shipping_zones, dependent: :destroy
4
+
5
+ validates :country_code, presence: true
6
+ validate :code_validity
7
+
8
+ before_save :set_name, if: :country_code_changed?
9
+ after_create :create_regions
10
+
11
+ def country
12
+ Carmen::Country.coded(country_code)
13
+ end
14
+
15
+ def self.all_country_codes
16
+ CountryShippingZone.pluck(:country_code)
17
+ end
18
+
19
+ private
20
+
21
+ def code_validity
22
+ unless country
23
+ errors.add(:country_code, "is invalid")
24
+ end
25
+ end
26
+
27
+ def create_regions
28
+ country.subregions.each do | region |
29
+ regional_shipping_zones.create({ state_code: region.code, country_code: country_code })
30
+ end
31
+ end
32
+
33
+ def set_name
34
+ self.name = country.name
35
+ end
36
+ end
@@ -0,0 +1,95 @@
1
+ class Creditcard
2
+ extend ActiveModel::Naming
3
+ include ActiveModel::Conversion
4
+ include ActiveModel::Validations
5
+ extend ActiveModel::Callbacks
6
+ include ActiveModel::Validations::Callbacks
7
+
8
+ attr_accessor :cvv, :expires_on, :number, :first_name, :last_name, :address1, :address2,
9
+ :cardtype, :month, :year, :state, :zipcode
10
+
11
+ alias :verification_value :cvv # ActiveMerchant needs this
12
+
13
+ delegate :display_number, to: :active_merchant_creditcard
14
+
15
+ before_validation :strip_non_numeric_values, if: :number
16
+
17
+ validates_presence_of :last_name, :first_name
18
+
19
+ validates_presence_of :number, message: "^Please enter credit card number"
20
+ validates_numericality_of :number, message: "^Please check the credit card number you entered"
21
+ validates_presence_of :cvv, message: "^Please enter CVV"
22
+
23
+ validate :validation_of_cardtype, if: lambda { |r| r.errors.empty? }
24
+ validate :validation_by_active_merchant, if: lambda { |r| r.errors.empty? }
25
+
26
+ def initialize(attrs = {})
27
+ sanitize_month_and_year(attrs)
28
+
29
+ attrs.each do | name, value |
30
+ send("#{name}=", value)
31
+ end
32
+ end
33
+
34
+ def verification_value?
35
+ true # ActiveMerchant needs this
36
+ end
37
+
38
+ def persisted?
39
+ false
40
+ end
41
+
42
+ private
43
+
44
+ def add_user_data(options = {})
45
+ options[:first_name] = first_name
46
+ options[:last_name] = last_name
47
+ end
48
+
49
+ def add_credit_card_data(options = {})
50
+ options[:year] = year
51
+ options[:month] = month
52
+ options[:number] = number
53
+ options[:type] = cardtype
54
+ options[:verification_value] = verification_value
55
+ end
56
+
57
+ def strip_non_numeric_values
58
+ self.number = number.to_s.gsub('-', '').strip
59
+ end
60
+
61
+ def validation_of_cardtype
62
+ if cardtype = ActiveMerchant::Billing::CreditCard.type?(number)
63
+ self.cardtype = cardtype
64
+ else
65
+ errors.add(:base, 'Please check credit card number. It does not seem right.')
66
+ end
67
+ end
68
+
69
+ def validation_by_active_merchant
70
+ amcard = active_merchant_creditcard
71
+
72
+ unless amcard.valid?
73
+ amcard.errors.full_messages.each { |message| errors.add(:base, message) }
74
+ end
75
+
76
+ amcard.errors.any?
77
+ end
78
+
79
+ def active_merchant_creditcard
80
+ options = {}
81
+ add_user_data(options)
82
+ add_credit_card_data(options)
83
+
84
+ ActiveMerchant::Billing::CreditCard.new(options)
85
+ end
86
+
87
+ def sanitize_month_and_year(attrs)
88
+ month = attrs.delete("expires_on(2i)")
89
+ year = attrs.delete("expires_on(1i)")
90
+ day = attrs.delete("expires_on(3i)")
91
+ attrs.reverse_merge!(month: month)
92
+ attrs.reverse_merge!(year: year)
93
+ end
94
+
95
+ end
@@ -0,0 +1,8 @@
1
+ class CustomField < ActiveRecord::Base
2
+
3
+ has_many :custom_field_answers, dependent: :destroy
4
+
5
+ validates :field_type, presence: true, inclusion: { in: %w(text number date) }
6
+
7
+ validates :name, presence: true
8
+ end
@@ -0,0 +1,101 @@
1
+ class CustomFieldAnswer
2
+ module Field
3
+ extend ActiveSupport::Concern
4
+
5
+ def custom_field=(custom_field)
6
+ set_custom_field(custom_field)
7
+
8
+ extend_module
9
+ end
10
+
11
+ # when question_id is assigned extend the module
12
+ def custom_field_id=(question_id)
13
+ super
14
+
15
+ extend_module
16
+ end
17
+
18
+ # Override Answer initialize method to extend proper Response module
19
+ # For example
20
+ # Answer instance whose question is TextFieldQuestion will extend TextFieldResponse
21
+ def initialize(attributes = nil, options = {})
22
+ super
23
+
24
+ extend_module
25
+ end
26
+
27
+ # We need to override after_initialize module to force instance to extend proper module
28
+ # ActiveRecord instances are created sometimes using malloc which will not invoke the initialize
29
+ # but they will call after_initialize
30
+ def after_initialize
31
+ extend_module
32
+ end
33
+
34
+ def extend_module
35
+ if target_module = module_to_extend
36
+ # Don't include module twice
37
+ kind_of?(target_module) || extend(target_module)
38
+
39
+ # Force value coersion for extended module
40
+ #
41
+ # For example
42
+ # if answer is created as shown below
43
+ # case(1)
44
+ # q = NumberQuestion.new
45
+ # a = Answer.new(:question => q, :value => 23.45)
46
+ # a.float_value ==> nil
47
+ # a.value ==> '23.45'
48
+ #
49
+ # case(2)
50
+ # a = Answer.new(:question => q)
51
+ # a.value = 23.45
52
+ # a.float_value ==> 23.45
53
+ # a.value ==> '23.45'
54
+ #
55
+ # Above case appears bcoz modules are extended after
56
+ # attributes are assigned. reassign_value method will
57
+ # give the modules to fix this problem please refer
58
+ # to NumberResponse reassign_value
59
+ #
60
+ # Note: currently both cases will work as expected
61
+ reassign_value
62
+ end
63
+ end
64
+
65
+ # This method will determine which module to extend
66
+ # Answer instances which are created using select might throw exception
67
+ # For example Answer.find(:conditions => [], :select => "value")
68
+ # retrieve_module_name will throw exception when it tries to access question field
69
+ # This is the only case Answer will fail to extend proper module
70
+ def module_to_extend
71
+ begin
72
+ CustomFieldAnswer::Field.const_get("#{custom_field.field_type.camelize}Field")
73
+ rescue
74
+ nil
75
+ end
76
+ end
77
+
78
+ def reassign_value
79
+ self.value = self.value
80
+ end
81
+
82
+ module DateField
83
+ def value=(value)
84
+ super
85
+
86
+ self.datetime_value = value
87
+ end
88
+ end
89
+
90
+ module NumberField
91
+ def value=(value)
92
+ super
93
+
94
+ self.number_value = value
95
+ end
96
+ end
97
+
98
+ module TextAnswerField
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,17 @@
1
+ class CustomFieldAnswer < ActiveRecord::Base
2
+
3
+ belongs_to :product
4
+
5
+ belongs_to :custom_field
6
+ alias_method :set_custom_field, :custom_field=
7
+
8
+ # this module must be included only after belong_to :custom_field definition
9
+ # this module overrides the dynamic methods which are added by belongs_to
10
+ include Field
11
+
12
+ def custom_field=(custom_field)
13
+ set_custom_field(custom_field)
14
+
15
+ extend_module
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ class LineItem < ActiveRecord::Base
2
+
3
+ # this is used only to pull the picture of the line_item. If after an order is created a product
4
+ # is deleted then that product and all the pictures are gone. In that case line item should
5
+ # display image not available. Besides image line_item should not pull any data from product and
6
+ # instead used the attributes copied from product to line_item
7
+ belongs_to :product
8
+
9
+ store :metadata, accessors: [ :picture_tiny, :picture_small, :picture_medium, :picture_large,
10
+ :picture_tiny_plus, :picture_small_plus, :picture_medium_plus, :picture_large_plus,
11
+ :product_permalink ]
12
+
13
+ belongs_to :order
14
+
15
+ validates_presence_of :order_id
16
+ validates_presence_of :product_id
17
+ validates_numericality_of :quantity, minimum: 1
18
+
19
+ before_create :copy_product_attributes
20
+
21
+ alias_attribute :name, :product_name
22
+ alias_attribute :description, :product_description
23
+
24
+ def price
25
+ product_price * quantity
26
+ end
27
+
28
+ # updates quantity count. If count is zero then deletes the line_item .
29
+ def update_quantity(count)
30
+ count = count.to_i
31
+ (count > 0) ? update_attributes(quantity: count) : destroy
32
+ end
33
+
34
+ private
35
+
36
+ def copy_product_attributes
37
+ self.product_name = product.name
38
+ self.product_description = product.description
39
+ self.product_price = product.price
40
+ self.product_permalink = product.permalink
41
+
42
+ if product.picture
43
+ %w(tiny tiny_plus small small_plus medium medium_plus large large_plus).each do |size|
44
+ send("picture_#{size}=", product.picture.picture_url(size.intern))
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,3 @@
1
+ class Link < ActiveRecord::Base
2
+ validates_presence_of :name, :url
3
+ end
@@ -0,0 +1,8 @@
1
+ class LinkGroup < ActiveRecord::Base
2
+
3
+ include Permalink::Builder
4
+
5
+ has_many :navigations, dependent: :destroy
6
+
7
+ validates :name, presence: true, uniqueness: { case_sensitive: false }
8
+ end
@@ -0,0 +1,7 @@
1
+ class Navigation < ActiveRecord::Base
2
+ belongs_to :link_group
3
+ belongs_to :product_group
4
+
5
+ validates :link_group, presence: true
6
+ validates :product_group, presence: true
7
+ end
@@ -0,0 +1,158 @@
1
+ class Order < ActiveRecord::Base
2
+
3
+ # to allow extensions to store any type of information
4
+ store :metadata
5
+
6
+ attr_accessor :validate_email, :billing_address_same_as_shipping
7
+ attr_protected :number
8
+
9
+ belongs_to :user
10
+ belongs_to :payment_method
11
+ belongs_to :shipping_method
12
+
13
+ has_one :shipping_address, dependent: :destroy
14
+ has_one :billing_address, dependent: :destroy
15
+
16
+ has_many :shipments
17
+ has_many :line_items, dependent: :destroy
18
+ has_many :products, through: :line_items
19
+ has_many :payment_transactions, dependent: :destroy
20
+
21
+ accepts_nested_attributes_for :shipping_address, allow_destroy: true
22
+ accepts_nested_attributes_for :billing_address, reject_if: :billing_address_same_as_shipping? , allow_destroy: true
23
+
24
+ delegate :tax, to: :tax_calculator
25
+ delegate :shipping_cost, to: :shipping_cost_calculator
26
+
27
+ validates :email, email: true, if: :validate_email
28
+
29
+ validates_inclusion_of :shipping_status, in: %W( nothing_to_ship shipped shipping_pending cancelled )
30
+ validates_inclusion_of :status, in: %W( open closed )
31
+ validates_inclusion_of :checkout_status, in: %W( items_added_to_cart billing_address_provided shipping_method_provided )
32
+
33
+ before_create :set_order_number
34
+
35
+ # Look at order_observer to see all the callbacks.
36
+ #
37
+ # capture is a method defined on kernel by Rails hence kapture is used .
38
+ #
39
+ # An order goes into pending state when it is paid for using 'Cash on delivery'
40
+ state_machine :payment_status, initial: :abandoned do
41
+
42
+ event(:authorize) { transition abandoned: :authorized }
43
+ event(:pending) { transition abandoned: :pending }
44
+ event(:kapture ) { transition authorized: :purchased }
45
+ event(:refund) { transition purchased: :refunded }
46
+
47
+ event(:purchase) { transition [:abandoned, :pending] => :purchased }
48
+ event(:void) { transition [:authorized, :pending] => :voided }
49
+
50
+ state all - [ :abandoned ] do
51
+ validates :payment_method, presence: true
52
+ end
53
+ end
54
+
55
+ state_machine :shipping_status, initial: :nothing_to_ship do
56
+ after_transition on: :shipped, do: :after_shipped
57
+
58
+ event(:shipping_pending) { transition nothing_to_ship: :shipping_pending }
59
+ event(:shipped) { transition shipping_pending: :shipped }
60
+ event(:cancel_shipment) { transition shipping_pending: :nothing_to_ship }
61
+ end
62
+
63
+ def mark_as_purchased!
64
+ touch(:purchased_at) unless purchased_at
65
+ end
66
+
67
+ def available_shipping_methods
68
+ ShippingMethod.available_for(line_items_total, shipping_address)
69
+ end
70
+
71
+ def item_count
72
+ line_items.count
73
+ end
74
+
75
+ def add(product)
76
+ options = { product_id: product.id }
77
+ if line_items.where(options).empty?
78
+ line_items.create(options.merge(quantity: 1))
79
+ end
80
+ end
81
+
82
+ def update_quantity(data = {})
83
+ data.each do |product_id, quantity|
84
+ if line_item = line_item_for(product_id)
85
+ line_item.update_quantity(quantity)
86
+ end
87
+ end
88
+ end
89
+
90
+ def remove(product)
91
+ update_quantity({product.id => 0})
92
+ end
93
+
94
+ # Returns the total price of all line items in float.
95
+ def line_items_total
96
+ line_items.reduce(BigDecimal('0')) do |sum, line_item|
97
+ sum + BigDecimal(line_item.price.to_s)
98
+ end.round(2).to_f
99
+ end
100
+
101
+ def total_amount
102
+ line_items_total + shipping_cost + tax
103
+ end
104
+
105
+ def total_amount_in_cents
106
+ Util.in_cents(total_amount)
107
+ end
108
+
109
+ def to_param
110
+ number
111
+ end
112
+
113
+ def final_billing_address
114
+ (shipping_address && !shipping_address.use_for_billing) ? billing_address : shipping_address
115
+ end
116
+
117
+ def initialize_addresses
118
+ shipping_address || build_shipping_address(country_code: "US", use_for_billing: true)
119
+ billing_address || build_billing_address(country_code: "US", use_for_billing: false)
120
+ end
121
+
122
+ def billing_address_same_as_shipping?
123
+ billing_address_same_as_shipping
124
+ end
125
+
126
+ def line_item_for(product_id)
127
+ line_items.find_by_product_id(product_id)
128
+ end
129
+
130
+ def shippable_countries
131
+ ShippingMethod.available_for_countries(line_items_total)
132
+ end
133
+
134
+ private
135
+
136
+ def set_order_number
137
+ num = Random.new.rand(11111111...99999999).to_s
138
+ while self.class.exists?(number: num) do
139
+ num = Random.new.rand(11111111...99999999).to_s
140
+ end
141
+
142
+ self.number = num
143
+ end
144
+
145
+ def tax_calculator
146
+ @_tax_calculator ||= TaxCalculator.new(self)
147
+ end
148
+
149
+ def shipping_cost_calculator
150
+ @_shipping_cost_calculator ||= ShippingCostCalculator.new(self)
151
+ end
152
+
153
+ def after_shipped
154
+ Mailer.delay.shipment_notification_to_buyer(number)
155
+ touch(:shipped_at)
156
+ end
157
+
158
+ end
@@ -0,0 +1,20 @@
1
+ class PaymentMethod < ActiveRecord::Base
2
+
3
+ store :metadata
4
+
5
+ include Permalink::Builder
6
+
7
+ # By default payment_method does not require that application must use SSL.
8
+ # Individual payment method should override this method.
9
+ def use_ssl?
10
+ false
11
+ end
12
+
13
+ def demodulized_underscore
14
+ self.class.name.demodulize.underscore
15
+ end
16
+
17
+ def self.partialize
18
+ name.gsub("PaymentMethod::","").underscore
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ class PaymentTransaction < ActiveRecord::Base
2
+
3
+ belongs_to :order
4
+ serialize :params, Hash
5
+ serialize :metadata, Hash
6
+
7
+ def to_partial_path
8
+ "admin/orders/payment_transactions/#{order.payment_method.class.partialize}"
9
+ end
10
+
11
+ end
@@ -0,0 +1,30 @@
1
+ class Picture < ActiveRecord::Base
2
+
3
+ belongs_to :product
4
+
5
+ mount_uploader :picture, PictureUploader
6
+
7
+ validates_presence_of :picture
8
+
9
+ before_save :update_picture_attributes
10
+
11
+ %w(tiny tiny_plus small small_plus medium medium_plus large large_plus).each do |version|
12
+ define_method :"#{version}_height" do
13
+ picture.send(version).height
14
+ end
15
+
16
+ define_method :"#{version}_width" do
17
+ picture.send(version).width
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def update_picture_attributes
24
+ if picture.present?
25
+ self.content_type = picture.file.content_type
26
+ self.file_size = picture.file.size
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,76 @@
1
+ class Product < ActiveRecord::Base
2
+
3
+ include Permalink::Builder
4
+
5
+ alias_attribute :title, :name
6
+
7
+ attr_accessor :pictures_order
8
+
9
+ validates :status, inclusion: { in: %w(active hidden sold_out) }, presence: true
10
+
11
+ has_many :pictures, order: 'pictures.position'
12
+
13
+ has_many :custom_field_answers, dependent: :destroy
14
+
15
+ accepts_nested_attributes_for :pictures, allow_destroy: true, reject_if: proc { |r| r[:picture].blank? }
16
+
17
+ accepts_nested_attributes_for :custom_field_answers, allow_destroy: true
18
+
19
+ after_initialize :initialize_status
20
+
21
+ scope :with_prictures, includes: 'pictures'
22
+
23
+ scope :active, where(status: 'active')
24
+ scope :hidden, where(status: 'hidden')
25
+ scope :sold_out, where(status: 'sold_out')
26
+
27
+
28
+ validates_presence_of :name, :description, :price
29
+
30
+ validates_numericality_of :price
31
+
32
+ def picture
33
+ pictures.first
34
+ end
35
+
36
+ # path is full path to the picture.
37
+ #
38
+ # Rails.root.join('db', 'original_pictures', filename )
39
+ #
40
+ # This method is used only in development and test to attach a picture.
41
+ def attach_picture(filename, path)
42
+ img = File.open(path) {|i| i.read}
43
+ encoded_img = Base64.encode64 img
44
+ io = FilelessIO.new(Base64.decode64(encoded_img))
45
+ io.original_filename = filename
46
+ p = Picture.new(product: self, picture: io)
47
+ p.save
48
+ end
49
+
50
+ def find_or_build_answer_for_field(field)
51
+ custom_field_answers.detect {|t| t.custom_field_id.to_s == field.id.to_s } ||
52
+ custom_field_answers.build(custom_field_id: field.id)
53
+ end
54
+
55
+ def find_or_build_all_answers
56
+ CustomField.all.each { |f| find_or_build_answer_for_field(f) }
57
+ end
58
+
59
+
60
+ def pictures_order=(value)
61
+ return if value.empty?
62
+ ordered_pictures = ActiveSupport::JSON.decode(value)
63
+ current_pictures = pictures
64
+
65
+ ordered_pictures.each{|position, picture_id|
66
+ if picture_id.present?
67
+ pic = current_pictures.find { |x| x.id == picture_id.to_i }
68
+ pic.update_column(:position, position) if pic
69
+ end
70
+ }
71
+ end
72
+
73
+ def initialize_status
74
+ self.status ||= 'active'
75
+ end
76
+ end
@@ -0,0 +1,65 @@
1
+ class ProductGroup < ActiveRecord::Base
2
+
3
+ include Permalink::Builder
4
+
5
+ validates :name, presence: true
6
+
7
+ has_many :product_group_conditions, dependent: :destroy, extend: ProductGroupSearch::Extension
8
+
9
+ has_many :navigations, dependent: :destroy
10
+
11
+ has_many :link_groups, through: :navigations
12
+
13
+ accepts_nested_attributes_for :product_group_conditions, allow_destroy: true
14
+
15
+ # determines if the given product exists in the product group
16
+ def contains?(product)
17
+ products.include?(product)
18
+ end
19
+
20
+ def self.fields
21
+ c = []
22
+ c << { "id" => 'name', "name" => 'Name', "field_type" => 'text' }
23
+ c << { "id" => 'price', "name" => 'Price', "field_type" => 'number' }
24
+
25
+ CustomField.all.map do | field |
26
+ c << field.attributes.slice("id", "name", "field_type")
27
+ end
28
+
29
+ c
30
+ end
31
+
32
+ def self.operators
33
+ {
34
+ text: [{ name: 'Contains', value: 'contains' },
35
+ { name: 'Starts With', value: 'starts'},
36
+ { name: 'Ends With', value:'ends'}],
37
+
38
+ number: [{ name: 'Equal', value: 'eq' },
39
+ { name: 'Greater Than', value: 'gt' },
40
+ { name: 'Grater Than Equal To', value:'gteq' },
41
+ { name: 'Less Than', value: 'lt' },
42
+ { name: 'Less Than Equal To', value: 'lteq'}],
43
+
44
+ date: [{ name: 'On', value: 'eq' },
45
+ { name: 'After', value: 'gt' },
46
+ { name: 'On or After', value:'gteq' },
47
+ { name: 'Before', value: 'lt' },
48
+ { name: 'On or Before', value: 'lteq'}],
49
+ }
50
+ end
51
+
52
+ def products
53
+ product_group_conditions.search
54
+ end
55
+
56
+ def summarize
57
+ product_group_conditions.map(&:summary).join(' and ')
58
+ end
59
+
60
+ # list of all product groups containing input product
61
+ def self.contains_product(product)
62
+ all.select { | product_group | product_group.contains?(product) }
63
+ end
64
+
65
+ end