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,24 @@
1
+ #= require accounting.js
2
+
3
+ # This utility function formats a value to a meaningful price.
4
+ #
5
+ # Usage:
6
+ # <%= f.text_field :price, :'data-behavior' => 'price-formatted' %>
7
+ #
8
+ # Value in the price field | After tabbing away the value becomes
9
+ # 1.2 | 1.20
10
+ # 1 | 1.00
11
+ # 1.2111 | 1.21
12
+ # abcd | 0.00
13
+ #
14
+
15
+ $ ->
16
+ $('[data-behavior~=price-formatted]').on 'focus blur paste change', ()->
17
+
18
+ # do not want comma in cases like 1,234.89
19
+ # do not want $ to be appearing like $23.78
20
+ result = accounting.formatMoney($(this).val(), {thousand: '', symbol: ''})
21
+
22
+ $(this).val(result)
23
+
24
+ $('[data-behavior~=price-formatted]').trigger('change')
@@ -0,0 +1,84 @@
1
+ require 'pathname'
2
+ require 'rails/generators'
3
+ require 'rails/generators/migration'
4
+ require 'rails/generators/active_record/migration'
5
+
6
+ module Nimbleshop
7
+ class AppGenerator < Rails::Generators::Base
8
+
9
+ source_root Pathname.new(File.expand_path('../templates', __FILE__))
10
+
11
+ def generate
12
+ copy_files!
13
+ migrate_database!
14
+ seed_database!
15
+ ensure_no_mass_protection
16
+ mount
17
+ delete_public_index_html
18
+ end
19
+
20
+ protected
21
+
22
+ def delete_public_index_html
23
+ FileUtils.rm(destination_path.join('public', 'index.html'))
24
+ end
25
+
26
+ def mount
27
+ if (routes_file = destination_path.join('config', 'routes.rb')).file?
28
+ mount = %Q{
29
+ mount NimbleshopSimply::Engine, :at => '/'
30
+
31
+ mount NimbleshopAuthorizedotnet::Engine, :at => '/nimbleshop_authorizedotnet'
32
+ mount NimbleshopPaypalwp::Engine, :at => '/nimbleshop_paypalwp'
33
+ mount NimbleshopSplitable::Engine, :at => '/nimbleshop_splitable'
34
+ mount NimbleshopCod::Engine, :at => '/nimbleshop_cod'
35
+ }
36
+
37
+ inject_into_file 'config/routes.rb', mount, :after => "Application.routes.draw do\n"
38
+ end
39
+ end
40
+
41
+ def ensure_no_mass_protection
42
+ f = 'config/application.rb'
43
+ current = 'config.active_record.whitelist_attributes = true'
44
+ new = 'config.active_record.whitelist_attributes = false'
45
+ gsub_file f, current, new, verbose: true
46
+ end
47
+
48
+ def migrate_database!
49
+ puts 'coping migration files'
50
+ run 'bundle exec rake railties:install:migrations --trace'
51
+ run 'bundle exec rake db:create db:migrate --trace'
52
+ end
53
+
54
+ def bundle!
55
+ run 'bundle install'
56
+ end
57
+
58
+ def copy_files!
59
+
60
+ # copy files like database.yml.* and application.yml
61
+ Pathname.glob(self.class.source_root.join('**', '*')).reject{|f|
62
+ f.directory? or f.to_s =~ /\/db\//
63
+ }.sort.each do |path|
64
+ copy_file path, path.to_s.gsub(self.class.source_root.to_s, destination_path.to_s)
65
+ end
66
+
67
+ template "config/initializers/airbrake.rb", "#{destination_path}/config/initializers/airbrake.rb"
68
+ template "config/initializers/cache_images.rb", "#{destination_path}/config/initializers/cache_images.rb"
69
+ template "config/initializers/carrierwave.rb", "#{destination_path}/config/initializers/carrierwave.rb"
70
+ template "config/initializers/delayed_job.rb", "#{destination_path}/config/initializers/delayed_job.rb"
71
+ template "config/initializers/setup_email.rb", "#{destination_path}/config/initializers/setup_email.rb"
72
+ end
73
+
74
+ # Helper method to quickly convert destination_root to a Pathname for easy file path manipulation
75
+ def destination_path
76
+ @destination_path ||= Pathname.new(self.destination_root)
77
+ end
78
+
79
+ def seed_database!
80
+ rake 'db:seed --trace' unless self.options[:skip_db] || self.options[:skip_migrations]
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,61 @@
1
+ # Usage
2
+ #
3
+ # Nimbleshop.config.s3.bucket_name
4
+ #
5
+ common:
6
+ airbrake_api_key: <%= ENV['AIRBRAKE_API_KEY'] %>
7
+ google_analytics_tracking_id: <%= ENV['GOOGLE_ANALYTICS_TRACKING_ID'] %>
8
+
9
+ # this is used for IPN notification and other places where external serivce cannot ping localhost
10
+ use_localhost2public_url: true
11
+ default_localhost2public_url: 4a5w.localtunnel.com
12
+
13
+ authorizedotnet:
14
+ login_id: <%= ENV['AUTHORIZE_NET_LOGIN_ID'] || '26Daqx7Jtw7R' %>
15
+ transaction_key: <%= ENV['AUTHORIZE_NET_TRANSACTION_KEY'] || '66JWf57KKc82W9y6' %>
16
+
17
+ s3:
18
+ access_key_id: <%= ENV['S3_ACCESS_KEY_ID'] %>
19
+ secret_access_key: <%= ENV['S3_SECRET_ACCESS_KEY'] %>
20
+
21
+ sendgrid:
22
+ username: <%= ENV['SENDGRID_USERNAME'] %>
23
+ password: <%= ENV['SENDGRID_PASSWORD'] %>
24
+ domain: <%= ENV['SENDGRID_DOMAIN'] %>
25
+
26
+ mailtrapio:
27
+ username: <%= ENV['MAILTRAPIO_USERNAME'] || 'nimbleshop' %>
28
+ password: <%= ENV['MAILTRAPIO_PASSWORD'] || '7663e1f272637a4b' %>
29
+
30
+ development:
31
+ use_s3: false
32
+ s3:
33
+ bucket_name: <%= ENV['S3_BUCKET_NAME'] %>
34
+ bare_url_with_port: localhost:3000
35
+
36
+ test:
37
+ use_s3: false
38
+ s3:
39
+ bucket_name: <%= ENV['S3_BUCKET_NAME'] %>
40
+ bare_url_with_port: localhost:3000
41
+ cookie_domain: nimbleshop.net
42
+ use_localhost2public_url: false
43
+ authorize_net:
44
+ login_id: 56yBAar72
45
+ transaction_key: 9r3pbH5bnKH29f7d
46
+
47
+ staging:
48
+ use_s3: true
49
+ s3:
50
+ bucket_name: <%= ENV['S3_BUCKET_NAME'] %>
51
+ bare_url_with_port: nimbleshop.net
52
+ deliver_email_for_real_in_staging: <%= ENV['DELIVER_EMAIL_FOR_REAL_IN_STAGING'] %>
53
+ cache_images: true
54
+
55
+ production:
56
+ use_s3: true
57
+ s3:
58
+ bucket_name: <%= ENV['S3_BUCKET_NAME'] %>
59
+ bare_url_with_port: nimbleshop.com
60
+ cache_images: true
61
+ use_localhost2public_url: false
@@ -0,0 +1,3 @@
1
+ #Airbrake.configure do |config|
2
+ #config.api_key = Nimbleshop.config.airbrake_api_key
3
+ #end
@@ -0,0 +1,4 @@
1
+ if Nimbleshop.config.cache_images
2
+ # cache images
3
+ Rails.application.config.static_cache_control = "public, max-age=36000"
4
+ end
@@ -0,0 +1,36 @@
1
+ if Nimbleshop.config.use_s3
2
+
3
+ unless bucket_name = Nimbleshop.config.s3.bucket_name
4
+ msg = %Q{
5
+ This application's #{Rails.env} environment is configured to use amazon s3.
6
+ However bucket_name to use is not specified at config/application.yml .
7
+ Please check guide( link here) on how to configure application to use S3.
8
+ }
9
+
10
+ raise msg
11
+ end
12
+
13
+ CarrierWave.configure do |config|
14
+ config.cache_dir = "#{Rails.root}/tmp/uploads"
15
+ config.storage = :fog
16
+ config.enable_processing = true
17
+ config.fog_directory = bucket_name
18
+ config.fog_attributes = {'Cache-Control' => 'max-age=315576000'}
19
+ config.fog_public = true
20
+
21
+ config.fog_credentials = {
22
+ provider: 'AWS',
23
+ aws_access_key_id: Nimbleshop.config.s3.access_key_id,
24
+ aws_secret_access_key: Nimbleshop.config.s3.secret_access_key,
25
+ region: 'us-east-1' #TODO make this configurable too
26
+ }
27
+ end
28
+
29
+ else
30
+
31
+ CarrierWave.configure do |config|
32
+ config.storage = :file
33
+ config.enable_processing = true
34
+ end
35
+
36
+ end
@@ -0,0 +1,15 @@
1
+ # By default DJ deletes all the failed jobs after 25 attemps. Here DJ is being configured to not to delete
2
+ # the failed jobs.
3
+ #
4
+ # By the way all the failed jobs can be cleared with rake task rake jobs:clear
5
+ Delayed::Worker.destroy_failed_jobs = false
6
+
7
+ Delayed::Worker.delay_jobs = !Rails.env.test?
8
+
9
+ # ============= ADDITIONAL NOTES ======================
10
+ #
11
+ # to start processing pending jobs using Delayed Job execute rake jobs:work
12
+ #
13
+ # access delayed_job_admin at http://localhost:3000/delayed_job_admin . See method delayed_job_admin_authentication in
14
+ # application_controller.rb for authentication for delayed_job_admin
15
+
@@ -0,0 +1,24 @@
1
+ if Nimbleshop.config.deliver_email_for_real
2
+
3
+ ActionMailer::Base.delivery_method = :smtp
4
+ ActionMailer::Base.smtp_settings = {
5
+ user_name: Nimbleshop.config.sendgrid.username,
6
+ password: Nimbleshop.config.sendgrid.password,
7
+ domain: Nimbleshop.config.sendgrid.domain,
8
+ address: "smtp.sendgrid.net",
9
+ port: 587,
10
+ authentication: :plain,
11
+ enable_starttls_auto: true
12
+ }
13
+
14
+ else
15
+
16
+ ActionMailer::Base.delivery_method = :smtp
17
+ ActionMailer::Base.smtp_settings = {
18
+ user_name: Nimbleshop.config.mailtrapio.username || "nimbleshop",
19
+ password: Nimbleshop.config.mailtrapio.password || "7663e1f272637a4b",
20
+ address: "mailtrap.io",
21
+ port: 2525,
22
+ authentication: :plain }
23
+
24
+ end
@@ -0,0 +1,18 @@
1
+ #
2
+ # If a field is nullable and if user hits spacebar a few times and submits
3
+ # the form then ActiveRecord would have the value as empty spaces.
4
+ #
5
+ # Following fix would remove all leading and trailing white spaces from a string value.
6
+ # And if the value is empty space then it will be set to nil.
7
+ #
8
+ # It would result in value being saved as NULL if user passed only a few white spaces.
9
+ #
10
+ module ActiveRecord
11
+ class Base
12
+ before_validation do |record|
13
+ record.attributes.each do |attr, value|
14
+ record[attr] = value.blank? ? nil : value.strip if value.respond_to?(:strip)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ # this is neeed to make attach_picture work
2
+ class FilelessIO < StringIO
3
+ attr_accessor :original_filename
4
+ end
@@ -0,0 +1,26 @@
1
+ #
2
+ # Rails's version of force_ssl does not force ssl in development environment.
3
+ #
4
+ # In this monkey patch that constraint has been removed. Notice the '#' before &&.
5
+ # The only code added was that single '#'
6
+ #
7
+ module ActionController
8
+ module ForceSSL
9
+ extend ActiveSupport::Concern
10
+ include AbstractController::Callbacks
11
+
12
+ module ClassMethods
13
+ def force_ssl(options = {})
14
+ host = options.delete(:host)
15
+ before_filter(options) do
16
+ if !request.ssl?# && !Rails.env.development?
17
+ redirect_options = {:protocol => 'https://', :status => :moved_permanently}
18
+ redirect_options.merge!(:host => host) if host
19
+ redirect_options.merge!(:params => request.query_parameters)
20
+ redirect_to redirect_options
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,10 @@
1
+ module MustacheTemplateHandler
2
+ def self.call(template)
3
+ if template.locals.include? :mustache
4
+ "Mustache.render(#{template.source.inspect}, mustache).html_safe"
5
+ else
6
+ "#{template.source.inspect}.html_safe"
7
+ end
8
+ end
9
+ end
10
+ ActionView::Template.register_template_handler(:mustache, MustacheTemplateHandler)
@@ -0,0 +1,23 @@
1
+ module Nimbleshop
2
+ class Engine < ::Rails::Engine
3
+
4
+ engine_name 'nimbleshop_core'
5
+
6
+ config.autoload_paths += %W(#{config.root}/lib)
7
+ config.autoload_paths += %W(#{config.root}/lib/nimbleshop)
8
+
9
+ config.to_prepare do
10
+ Address
11
+ ShippingZone
12
+ end
13
+
14
+ initializer 'nimbleshop_core.action_controller' do |app|
15
+ ActiveSupport.on_load :action_controller do
16
+ helper AdminHelper
17
+ helper NimbleshopHelper
18
+ helper PaymentMethodHelper
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ #
2
+ # This module builds permalink when the record is created for the very first time.
3
+ #
4
+ # Usage:
5
+ #
6
+ # class Product < ActiveRecord::Base
7
+ # include BuildPermalink
8
+ # build_permalink allow_nil: true
9
+ # end
10
+ #
11
+ # build_permalink line is needed only if you are passing parameter otherwise that line can be omitted
12
+ #
13
+ module Permalink
14
+ module Builder
15
+ extend ActiveSupport::Concern
16
+
17
+ included do
18
+ before_create :set_permalink
19
+ class_attribute :permalink_options
20
+ self.permalink_options = {}
21
+ end
22
+
23
+ module ClassMethods
24
+ def build_permalink(options = {})
25
+ self.permalink_options = options
26
+ end
27
+ end
28
+
29
+ def to_param
30
+ self.permalink
31
+ end
32
+
33
+ def set_permalink
34
+ return if self.name.blank? && permalink_options[:allow_nil]
35
+ permalink = self.name.parameterize
36
+ counter = 2
37
+
38
+ while self.class.exists?(permalink: permalink) do
39
+ permalink = "#{permalink}-#{counter}"
40
+ counter = counter + 1
41
+ end
42
+
43
+ self.permalink ||= permalink
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,51 @@
1
+ module Processor
2
+ class Base
3
+
4
+ extend ActiveModel::Callbacks
5
+
6
+ define_model_callbacks :transaction, :authorize,
7
+ :capture,
8
+ :purchase,
9
+ :refund,
10
+ :void
11
+
12
+ before_transaction :set_active_merchant_mode
13
+
14
+ def capture(options = {})
15
+ execute(:capture, options)
16
+ end
17
+
18
+ def authorize(options = {})
19
+ execute(:authorize, options)
20
+ end
21
+
22
+ def void(options = {})
23
+ execute(:void, options)
24
+ end
25
+
26
+ def purchase(options = {})
27
+ execute(:purchase, options)
28
+ end
29
+
30
+ def refund(options = {})
31
+ execute(:refund, options)
32
+ end
33
+
34
+ private
35
+
36
+ def execute(operation, options = {})
37
+ run_callbacks(:transaction) do
38
+ run_callbacks(operation) do
39
+ send("do_#{operation}", options)
40
+ end
41
+ end
42
+ end
43
+
44
+ # this method can be overriden by individual payment method
45
+ def set_active_merchant_mode
46
+ mode = Rails.env.production? ? :production : :test
47
+ ActiveMerchant::Billing::Base.mode = mode
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module Processor
2
+ autoload :Base, 'processor/base'
3
+ end
@@ -0,0 +1,19 @@
1
+ module ProductGroupSearch
2
+ class BaseField
3
+ attr_accessor :condition
4
+ delegate :query_field, :value, to: :condition
5
+
6
+ def initialize(condition)
7
+ self.condition = condition
8
+ end
9
+
10
+ def valid_operator?(operator)
11
+ valid_operators.include?(operator.to_s)
12
+ end
13
+
14
+ def where(proxy = nil)
15
+ clause = send(condition.operator, coerced_value)
16
+ proxy ? proxy.and(clause) : clause
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ module ProductGroupSearch
2
+ module CoreFieldStrategy
3
+ def join(proxy)
4
+ proxy
5
+ end
6
+
7
+ def target_table
8
+ unless @_target
9
+ @_target = Product.arel_table
10
+ end
11
+ @_target
12
+ end
13
+
14
+ def query_column
15
+ self.name.try(:to_sym)
16
+ end
17
+
18
+ def field_type
19
+ # TODO megpha why special treatment to :price field
20
+ if query_column == :price
21
+ 'number'
22
+ else
23
+ 'text'
24
+ end
25
+ end
26
+
27
+ def localized_name
28
+ self.name
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,39 @@
1
+ module ProductGroupSearch
2
+ module CustomFieldStrategy
3
+ def join(proxy)
4
+ proxy.join(target_table).on(join_condition)
5
+ end
6
+
7
+ def join_condition
8
+ target_table[:product_id].eq(Product.arel_table[:id])
9
+ end
10
+
11
+ def target_table
12
+ unless @_target
13
+ @_target =CustomFieldAnswer.arel_table.alias("answers#{index}")
14
+ end
15
+ @_target
16
+ end
17
+
18
+ def custom_field
19
+ @_custom_field ||= CustomField.find(self.name)
20
+ end
21
+
22
+ def query_column
23
+ field_type = custom_field.field_type
24
+ if field_type == 'text'
25
+ :value
26
+ else
27
+ "#{field_type}_value".to_sym
28
+ end
29
+ end
30
+
31
+ def field_type
32
+ custom_field.field_type
33
+ end
34
+
35
+ def localized_name
36
+ custom_field.name
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ module ProductGroupSearch
2
+ class DateField < NumberField
3
+ def coerced_value
4
+ Date.strptime(value.try(:to_s), "%d/%m/%Y")
5
+ end
6
+
7
+ def valid_value_data_type?
8
+ begin
9
+ Date.strptime(value.try(:to_s), "%d/%m/%Y")
10
+ true
11
+ rescue
12
+ false
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,46 @@
1
+ module ProductGroupSearch
2
+ module Extension
3
+ # This module bring search feature to product_group. This is how it is used in product_group .
4
+ #
5
+ # class ProductGroup
6
+ # has_many :product_group_conditions, dependent: :destroy, extend: ProductGroupSearch::Extension
7
+ # def products
8
+ # product_group_conditions.search
9
+ # end
10
+ # end
11
+ #
12
+ def search
13
+ Product.find_by_sql(to_search_sql)
14
+ end
15
+
16
+ def to_search_sql
17
+ set_indexes # custom_field_strategy needs it
18
+
19
+ search_proxy = handle_joins
20
+ search_proxy = search_proxy.where(handle_where_conditions)
21
+ search_proxy = filter_on_active(search_proxy)
22
+ search_proxy = search_proxy.project(Arel.sql("products.*"))
23
+
24
+ search_proxy.to_sql
25
+ end
26
+
27
+ private
28
+
29
+ def set_indexes
30
+ each_with_index { | condition, index | condition.index = index }
31
+ end
32
+
33
+ def handle_joins
34
+ reduce(Product.arel_table) { | p, condition | condition.join(p) }
35
+ end
36
+
37
+ def handle_where_conditions
38
+ reduce(nil) { | p, condition | condition.where(p) }
39
+ end
40
+
41
+ def filter_on_active(search)
42
+ search.where(Product.arel_table[:status].eq('active'))
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ module ProductGroupSearch
2
+ class NumberField < BaseField
3
+ delegate :eq, :lt, :gt, :lteq, :gteq, to: :query_field
4
+
5
+ def valid_value_data_type?
6
+ value && value.to_s.try(:match, /\A[+-]?\d+?(\.\d+)?\Z/).present?
7
+ end
8
+
9
+ def coerced_value
10
+ value.try(:to_f)
11
+ end
12
+
13
+ def valid_operators
14
+ %w(eq lt gt lteq gteq)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ module ProductGroupSearch
2
+ class TextField < BaseField
3
+ delegate :matches, to: :query_field
4
+
5
+ def contains(val)
6
+ matches("%#{val}%")
7
+ end
8
+
9
+ def ends(val)
10
+ matches("%#{val}")
11
+ end
12
+
13
+ def starts(val)
14
+ matches("#{val}%")
15
+ end
16
+
17
+ def eq(val)
18
+ matches(val)
19
+ end
20
+
21
+ def valid_operators
22
+ %w(eq contains starts ends)
23
+ end
24
+
25
+ def coerced_value
26
+ value.try(:to_s)
27
+ end
28
+
29
+ def valid_value_data_type?
30
+ condition.value.present?
31
+ end
32
+ end
33
+ end