gemgento 2.8.0

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 (429) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +8 -0
  5. data/README.md +9 -0
  6. data/Rakefile +21 -0
  7. data/app/adapters/gemgento/magento/address_adapter.rb +37 -0
  8. data/app/adapters/gemgento/magento/customer_adapter.rb +24 -0
  9. data/app/adapters/gemgento/magento/line_item_adapter.rb +41 -0
  10. data/app/adapters/gemgento/magento/order_adapter.rb +97 -0
  11. data/app/adapters/gemgento/magento/order_status_adapter.rb +24 -0
  12. data/app/adapters/gemgento/magento/payment_adapter.rb +38 -0
  13. data/app/adapters/gemgento/magento/product_adapater.rb +24 -0
  14. data/app/adapters/gemgento/magento/quote_adapter.rb +17 -0
  15. data/app/adapters/gemgento/magento/shipment_adapter.rb +74 -0
  16. data/app/adapters/gemgento/magento/shipment_item_adapter.rb +39 -0
  17. data/app/adapters/gemgento/magento/shipment_track_adapter.rb +31 -0
  18. data/app/adapters/gemgento/magento_adapter.rb +17 -0
  19. data/app/assets/fonts/FuturaStd-Bold.otf +0 -0
  20. data/app/assets/fonts/FuturaStd-Book.otf +0 -0
  21. data/app/assets/fonts/FuturaStd-Light.otf +0 -0
  22. data/app/assets/fonts/FuturaStd-Medium.otf +0 -0
  23. data/app/assets/fonts/Verlag-Black.otf +0 -0
  24. data/app/assets/fonts/Verlag-BlackItalic.otf +0 -0
  25. data/app/assets/fonts/Verlag-Bold.otf +0 -0
  26. data/app/assets/fonts/Verlag-BoldItalic.otf +0 -0
  27. data/app/assets/fonts/Verlag-Book.otf +0 -0
  28. data/app/assets/fonts/Verlag-BookItalic-2.otf +0 -0
  29. data/app/assets/fonts/Verlag-BookItalic-3.otf +0 -0
  30. data/app/assets/fonts/Verlag-BookItalic.otf +0 -0
  31. data/app/assets/fonts/Verlag-Light.otf +0 -0
  32. data/app/assets/fonts/Verlag-LightItalic.otf +0 -0
  33. data/app/assets/fonts/Verlag-XLight.otf +0 -0
  34. data/app/assets/fonts/Verlag-XLightItalic.otf +0 -0
  35. data/app/assets/images/about_store.jpg +0 -0
  36. data/app/assets/images/gemgento-icon-bolt.png +0 -0
  37. data/app/assets/javascripts/gemgento/active_admin.js.coffee +42 -0
  38. data/app/assets/javascripts/gemgento/checkout/address.coffee +23 -0
  39. data/app/assets/javascripts/gemgento/gemgento.js +1 -0
  40. data/app/assets/javascripts/gemgento/global.js.coffee +31 -0
  41. data/app/assets/stylesheets/gemgento/active_admin.css.scss +549 -0
  42. data/app/assets/stylesheets/gemgento/default-views/_address.scss +11 -0
  43. data/app/assets/stylesheets/gemgento/default-views/_category.scss +54 -0
  44. data/app/assets/stylesheets/gemgento/default-views/_checkout.scss +28 -0
  45. data/app/assets/stylesheets/gemgento/default-views/_footer.scss +13 -0
  46. data/app/assets/stylesheets/gemgento/default-views/_form.scss +127 -0
  47. data/app/assets/stylesheets/gemgento/default-views/_header.scss +32 -0
  48. data/app/assets/stylesheets/gemgento/default-views/_layout.css.scss +157 -0
  49. data/app/assets/stylesheets/gemgento/default-views/_pages.css.scss +83 -0
  50. data/app/assets/stylesheets/gemgento/default-views/_product.scss +57 -0
  51. data/app/assets/stylesheets/gemgento/default-views/_shopping_bag.scss +87 -0
  52. data/app/assets/stylesheets/gemgento/default-views/_subheader.css.scss +30 -0
  53. data/app/assets/stylesheets/gemgento/default-views/application.css.scss +1 -0
  54. data/app/controllers/concerns/gemgento/api/v1/base.rb +15 -0
  55. data/app/controllers/concerns/gemgento/api/v1/product_filters.rb +33 -0
  56. data/app/controllers/gemgento/addresses_controller.rb +14 -0
  57. data/app/controllers/gemgento/api/v1/categories_controller.rb +13 -0
  58. data/app/controllers/gemgento/api/v1/products_controller.rb +23 -0
  59. data/app/controllers/gemgento/api/v1/search_controller.rb +14 -0
  60. data/app/controllers/gemgento/application_controller.rb +5 -0
  61. data/app/controllers/gemgento/cart_controller.rb +99 -0
  62. data/app/controllers/gemgento/categories_controller.rb +37 -0
  63. data/app/controllers/gemgento/checkout/address_controller.rb +48 -0
  64. data/app/controllers/gemgento/checkout/confirm_controller.rb +72 -0
  65. data/app/controllers/gemgento/checkout/coupons_controller.rb +42 -0
  66. data/app/controllers/gemgento/checkout/gift_card_controller.rb +39 -0
  67. data/app/controllers/gemgento/checkout/gift_controller.rb +32 -0
  68. data/app/controllers/gemgento/checkout/login_controller.rb +123 -0
  69. data/app/controllers/gemgento/checkout/payment_controller.rb +70 -0
  70. data/app/controllers/gemgento/checkout/paypal_controller.rb +23 -0
  71. data/app/controllers/gemgento/checkout/shipping_controller.rb +46 -0
  72. data/app/controllers/gemgento/checkout/shipping_payment_controller.rb +58 -0
  73. data/app/controllers/gemgento/checkout/thank_you_controller.rb +45 -0
  74. data/app/controllers/gemgento/checkout_controller.rb +120 -0
  75. data/app/controllers/gemgento/countries_controller.rb +17 -0
  76. data/app/controllers/gemgento/errors_controller.rb +7 -0
  77. data/app/controllers/gemgento/footer_items_controller.rb +16 -0
  78. data/app/controllers/gemgento/home_controller.rb +7 -0
  79. data/app/controllers/gemgento/magento/addresses_controller.rb +61 -0
  80. data/app/controllers/gemgento/magento/base_controller.rb +18 -0
  81. data/app/controllers/gemgento/magento/categories_controller.rb +103 -0
  82. data/app/controllers/gemgento/magento/email/sales/credit_memos_controller.rb +21 -0
  83. data/app/controllers/gemgento/magento/email/sales/invoices_controller.rb +21 -0
  84. data/app/controllers/gemgento/magento/email/sales/orders_controller.rb +20 -0
  85. data/app/controllers/gemgento/magento/email/sales/shipments_controller.rb +25 -0
  86. data/app/controllers/gemgento/magento/emails_controller.rb +11 -0
  87. data/app/controllers/gemgento/magento/inventory_controller.rb +30 -0
  88. data/app/controllers/gemgento/magento/orders_controller.rb +12 -0
  89. data/app/controllers/gemgento/magento/price_rules_controller.rb +22 -0
  90. data/app/controllers/gemgento/magento/product_attribute_sets_controller.rb +37 -0
  91. data/app/controllers/gemgento/magento/product_attributes_controller.rb +70 -0
  92. data/app/controllers/gemgento/magento/products_controller.rb +240 -0
  93. data/app/controllers/gemgento/magento/recurring_profiles_controller.rb +42 -0
  94. data/app/controllers/gemgento/magento/stores_controller.rb +21 -0
  95. data/app/controllers/gemgento/magento/user_groups_controller.rb +23 -0
  96. data/app/controllers/gemgento/magento/users_controller.rb +63 -0
  97. data/app/controllers/gemgento/order_export_controller.rb +21 -0
  98. data/app/controllers/gemgento/orders_controller.rb +12 -0
  99. data/app/controllers/gemgento/products_controller.rb +12 -0
  100. data/app/controllers/gemgento/regions_controller.rb +18 -0
  101. data/app/controllers/gemgento/search_controller.rb +16 -0
  102. data/app/controllers/gemgento/shipments_controller.rb +5 -0
  103. data/app/controllers/gemgento/stock_notifications_controller.rb +22 -0
  104. data/app/controllers/gemgento/subscribers_controller.rb +35 -0
  105. data/app/controllers/gemgento/sync_controller.rb +50 -0
  106. data/app/controllers/gemgento/user/addresses_controller.rb +79 -0
  107. data/app/controllers/gemgento/user/base_controller.rb +14 -0
  108. data/app/controllers/gemgento/user/home_controller.rb +9 -0
  109. data/app/controllers/gemgento/user/orders_controller.rb +17 -0
  110. data/app/controllers/gemgento/user/passwords_controller.rb +18 -0
  111. data/app/controllers/gemgento/user/recurring_profiles_controller.rb +31 -0
  112. data/app/controllers/gemgento/user/registration_session_controller.rb +103 -0
  113. data/app/controllers/gemgento/user/registrations_controller.rb +28 -0
  114. data/app/controllers/gemgento/user/saved_credit_cards_controller.rb +56 -0
  115. data/app/controllers/gemgento/user/sessions_controller.rb +50 -0
  116. data/app/controllers/gemgento/user/wishlist_items_controller.rb +55 -0
  117. data/app/controllers/gemgento/users_controller.rb +36 -0
  118. data/app/helpers/gemgento/application_helper.rb +125 -0
  119. data/app/helpers/gemgento/categories_helper.rb +39 -0
  120. data/app/helpers/gemgento/checkout/payment_helper.rb +5 -0
  121. data/app/helpers/gemgento/products_helper.rb +23 -0
  122. data/app/jobs/gemgento/import_job.rb +12 -0
  123. data/app/mailers/gemgento/sales_mailer.rb +80 -0
  124. data/app/models/admin_user.rb +7 -0
  125. data/app/models/concerns/gemgento/product_touches.rb +26 -0
  126. data/app/models/gemgento.rb +5 -0
  127. data/app/models/gemgento/adapter/sellect/customer.rb +34 -0
  128. data/app/models/gemgento/adapter/sellect/order.rb +378 -0
  129. data/app/models/gemgento/adapter/sellect/product.rb +250 -0
  130. data/app/models/gemgento/adapter/sellect_adapter.rb +16 -0
  131. data/app/models/gemgento/adapter/shopify/address.rb +40 -0
  132. data/app/models/gemgento/adapter/shopify/category.rb +51 -0
  133. data/app/models/gemgento/adapter/shopify/customer.rb +66 -0
  134. data/app/models/gemgento/adapter/shopify/order.rb +334 -0
  135. data/app/models/gemgento/adapter/shopify/product.rb +377 -0
  136. data/app/models/gemgento/adapter/shopify/product_category_position.rb +58 -0
  137. data/app/models/gemgento/adapter/shopify_adapter.rb +63 -0
  138. data/app/models/gemgento/address.rb +206 -0
  139. data/app/models/gemgento/api_job.rb +68 -0
  140. data/app/models/gemgento/asset.rb +185 -0
  141. data/app/models/gemgento/asset_file.rb +57 -0
  142. data/app/models/gemgento/asset_type.rb +8 -0
  143. data/app/models/gemgento/bundle.rb +5 -0
  144. data/app/models/gemgento/bundle/item.rb +17 -0
  145. data/app/models/gemgento/bundle/option.rb +20 -0
  146. data/app/models/gemgento/category.rb +235 -0
  147. data/app/models/gemgento/country.rb +21 -0
  148. data/app/models/gemgento/gift_message.rb +8 -0
  149. data/app/models/gemgento/image_import.rb +141 -0
  150. data/app/models/gemgento/import.rb +125 -0
  151. data/app/models/gemgento/inventory.rb +60 -0
  152. data/app/models/gemgento/inventory_import.rb +51 -0
  153. data/app/models/gemgento/line_item.rb +142 -0
  154. data/app/models/gemgento/line_item_option.rb +10 -0
  155. data/app/models/gemgento/magento_db.rb +35 -0
  156. data/app/models/gemgento/magento_response.rb +10 -0
  157. data/app/models/gemgento/order.rb +56 -0
  158. data/app/models/gemgento/order_status.rb +7 -0
  159. data/app/models/gemgento/payment.rb +50 -0
  160. data/app/models/gemgento/price_rule.rb +258 -0
  161. data/app/models/gemgento/price_tier.rb +36 -0
  162. data/app/models/gemgento/product.rb +607 -0
  163. data/app/models/gemgento/product_attribute.rb +48 -0
  164. data/app/models/gemgento/product_attribute_option.rb +39 -0
  165. data/app/models/gemgento/product_attribute_set.rb +22 -0
  166. data/app/models/gemgento/product_attribute_value.rb +26 -0
  167. data/app/models/gemgento/product_category.rb +34 -0
  168. data/app/models/gemgento/product_import.rb +359 -0
  169. data/app/models/gemgento/quote.rb +586 -0
  170. data/app/models/gemgento/recurring_profile.rb +28 -0
  171. data/app/models/gemgento/region.rb +14 -0
  172. data/app/models/gemgento/relation.rb +10 -0
  173. data/app/models/gemgento/relation_type.rb +7 -0
  174. data/app/models/gemgento/saved_credit_card.rb +45 -0
  175. data/app/models/gemgento/search.rb +14 -0
  176. data/app/models/gemgento/session.rb +49 -0
  177. data/app/models/gemgento/shipment.rb +38 -0
  178. data/app/models/gemgento/shipment_comment.rb +19 -0
  179. data/app/models/gemgento/shipment_item.rb +11 -0
  180. data/app/models/gemgento/shipment_track.rb +21 -0
  181. data/app/models/gemgento/stock_notification.rb +17 -0
  182. data/app/models/gemgento/store.rb +31 -0
  183. data/app/models/gemgento/store_tag.rb +8 -0
  184. data/app/models/gemgento/subscriber.rb +30 -0
  185. data/app/models/gemgento/swatch.rb +9 -0
  186. data/app/models/gemgento/sync.rb +134 -0
  187. data/app/models/gemgento/tag.rb +64 -0
  188. data/app/models/gemgento/user.rb +161 -0
  189. data/app/models/gemgento/user_group.rb +13 -0
  190. data/app/models/gemgento/wishlist_item.rb +11 -0
  191. data/app/services/gemgento/magento_api.rb +173 -0
  192. data/app/services/gemgento/price.rb +67 -0
  193. data/app/validators/gemgento/credit_card_validator.rb +50 -0
  194. data/app/validators/gemgento/image_import_validator.rb +100 -0
  195. data/app/validators/gemgento/inventory_import_validator.rb +73 -0
  196. data/app/validators/gemgento/inventory_validator.rb +14 -0
  197. data/app/validators/gemgento/product_import_validator.rb +163 -0
  198. data/app/views/admin/product_positions/_index.html.haml +14 -0
  199. data/app/views/devise/registrations/edit.haml +37 -0
  200. data/app/views/gemgento/addresses/_address.json.jbuilder +6 -0
  201. data/app/views/gemgento/addresses/region_options.html.haml +1 -0
  202. data/app/views/gemgento/api/v1/categories/_category.json.jbuilder +52 -0
  203. data/app/views/gemgento/api/v1/categories/index.json.jbuilder +8 -0
  204. data/app/views/gemgento/api/v1/categories/show.json.jbuilder +7 -0
  205. data/app/views/gemgento/api/v1/products/_attributes.json.jbuilder +9 -0
  206. data/app/views/gemgento/api/v1/products/_product.json.jbuilder +18 -0
  207. data/app/views/gemgento/api/v1/products/_relationships.json.jbuilder +48 -0
  208. data/app/views/gemgento/api/v1/products/index.json.jbuilder +8 -0
  209. data/app/views/gemgento/api/v1/products/show.json.jbuilder +7 -0
  210. data/app/views/gemgento/api/v1/search/index.json.jbuilder +8 -0
  211. data/app/views/gemgento/api/v1/search/show.json.jbuilder +8 -0
  212. data/app/views/gemgento/assets/_asset.json.jbuilder +13 -0
  213. data/app/views/gemgento/cart/show.html.haml +67 -0
  214. data/app/views/gemgento/categories/_category.json.jbuilder +9 -0
  215. data/app/views/gemgento/categories/_product_tile.html.haml +16 -0
  216. data/app/views/gemgento/categories/index.html.haml +10 -0
  217. data/app/views/gemgento/categories/index.json.jbuilder +1 -0
  218. data/app/views/gemgento/categories/show.html.haml +16 -0
  219. data/app/views/gemgento/categories/show.json.jbuilder +1 -0
  220. data/app/views/gemgento/checkout/_checkout_header.html.haml +17 -0
  221. data/app/views/gemgento/checkout/address/error.js.erb +1 -0
  222. data/app/views/gemgento/checkout/address/show.html.haml +88 -0
  223. data/app/views/gemgento/checkout/address/success.js.erb +1 -0
  224. data/app/views/gemgento/checkout/confirm/error.js.erb +0 -0
  225. data/app/views/gemgento/checkout/confirm/show.html.haml +60 -0
  226. data/app/views/gemgento/checkout/confirm/success.js.erb +1 -0
  227. data/app/views/gemgento/checkout/login/login_fail.js.erb +1 -0
  228. data/app/views/gemgento/checkout/login/login_guest_fail.js.erb +1 -0
  229. data/app/views/gemgento/checkout/login/login_guest_success.js.erb +1 -0
  230. data/app/views/gemgento/checkout/login/login_success.js.erb +1 -0
  231. data/app/views/gemgento/checkout/login/registration_fail.js.erb +1 -0
  232. data/app/views/gemgento/checkout/login/registration_success.js.erb +1 -0
  233. data/app/views/gemgento/checkout/login/show.html.haml +50 -0
  234. data/app/views/gemgento/checkout/payment/error.js.erb +1 -0
  235. data/app/views/gemgento/checkout/payment/show.html.haml +56 -0
  236. data/app/views/gemgento/checkout/payment/success.js.erb +1 -0
  237. data/app/views/gemgento/checkout/shipping/error.js.erb +0 -0
  238. data/app/views/gemgento/checkout/shipping/show.html.haml +26 -0
  239. data/app/views/gemgento/checkout/shipping/success.js.erb +1 -0
  240. data/app/views/gemgento/checkout/shipping_payment/show.haml +52 -0
  241. data/app/views/gemgento/checkout/thank_you/show.html.haml +6 -0
  242. data/app/views/gemgento/countries/_country.json.jbuilder +4 -0
  243. data/app/views/gemgento/countries/index.json.jbuilder +3 -0
  244. data/app/views/gemgento/countries/show.json.jbuilder +1 -0
  245. data/app/views/gemgento/home/index.html.haml +1 -0
  246. data/app/views/gemgento/order/add_item.js.erb +0 -0
  247. data/app/views/gemgento/order/no_inventory.js.erb +1 -0
  248. data/app/views/gemgento/order/remove_item.js.erb +0 -0
  249. data/app/views/gemgento/order/update_item.js.erb +0 -0
  250. data/app/views/gemgento/order_export/index.html.haml +2 -0
  251. data/app/views/gemgento/order_items/_order_item.json.jbuilder +7 -0
  252. data/app/views/gemgento/orders/_order.json.jbuilder +29 -0
  253. data/app/views/gemgento/products/_product.json.jbuilder +40 -0
  254. data/app/views/gemgento/products/index.html.haml +19 -0
  255. data/app/views/gemgento/products/show.html.haml +67 -0
  256. data/app/views/gemgento/products/show.json.jbuilder +1 -0
  257. data/app/views/gemgento/sales_mailer/credit_memo_email.html.haml +1 -0
  258. data/app/views/gemgento/sales_mailer/invoice_email.html.haml +1 -0
  259. data/app/views/gemgento/sales_mailer/order_email.html.haml +1 -0
  260. data/app/views/gemgento/sales_mailer/shipment_email.html.haml +1 -0
  261. data/app/views/gemgento/search/index.html.haml +8 -0
  262. data/app/views/gemgento/shared/_asset.json.jbuilder +35 -0
  263. data/app/views/gemgento/shared/_asset_file.json.jbuilder +19 -0
  264. data/app/views/gemgento/shared/_asset_type.json.jbuilder +13 -0
  265. data/app/views/gemgento/shared/_error_messages.haml +7 -0
  266. data/app/views/gemgento/shared/_flash_messages.haml +4 -0
  267. data/app/views/gemgento/shared/_footer.haml +7 -0
  268. data/app/views/gemgento/shared/_header.haml +23 -0
  269. data/app/views/gemgento/shared/_mini_bag.haml +36 -0
  270. data/app/views/gemgento/shared/_product_image.haml +8 -0
  271. data/app/views/gemgento/shipments/_shipment.json.jbuilder +12 -0
  272. data/app/views/gemgento/subscribers/create.js.erb +2 -0
  273. data/app/views/gemgento/subscribers/errors.js.erb +1 -0
  274. data/app/views/gemgento/user/_user.json.jbuilder +2 -0
  275. data/app/views/gemgento/user/addresses/_form.haml +39 -0
  276. data/app/views/gemgento/user/addresses/errors.js.erb +1 -0
  277. data/app/views/gemgento/user/addresses/index.haml +33 -0
  278. data/app/views/gemgento/user/addresses/new.haml +11 -0
  279. data/app/views/gemgento/user/addresses/success.js.erb +1 -0
  280. data/app/views/gemgento/user/confirmations/new.haml +9 -0
  281. data/app/views/gemgento/user/home/index.haml +8 -0
  282. data/app/views/gemgento/user/mailer/confirmation_instructions.html.erb +5 -0
  283. data/app/views/gemgento/user/mailer/reset_password_instructions.html.erb +8 -0
  284. data/app/views/gemgento/user/mailer/unlock_instructions.html.erb +7 -0
  285. data/app/views/gemgento/user/orders/index.html.haml +29 -0
  286. data/app/views/gemgento/user/orders/show.html.haml +87 -0
  287. data/app/views/gemgento/user/passwords/edit.html.erb +18 -0
  288. data/app/views/gemgento/user/passwords/new.html.haml +21 -0
  289. data/app/views/gemgento/user/registration_session/new.haml +67 -0
  290. data/app/views/gemgento/user/registrations/new.html.haml +28 -0
  291. data/app/views/gemgento/user/saved_credit_cards/_form.haml +69 -0
  292. data/app/views/gemgento/user/saved_credit_cards/index.haml +25 -0
  293. data/app/views/gemgento/user/saved_credit_cards/new.haml +13 -0
  294. data/app/views/gemgento/user/sessions/new.html.haml +29 -0
  295. data/app/views/gemgento/user/shared/_links.erb +25 -0
  296. data/app/views/gemgento/user/shared/_user_header.haml +8 -0
  297. data/app/views/gemgento/user/wishlist_items/index.html.haml +20 -0
  298. data/app/views/kaminari/_first_page.html.haml +9 -0
  299. data/app/views/kaminari/_gap.html.haml +8 -0
  300. data/app/views/kaminari/_last_page.html.haml +9 -0
  301. data/app/views/kaminari/_next_page.html.haml +9 -0
  302. data/app/views/kaminari/_page.html.haml +10 -0
  303. data/app/views/kaminari/_paginator.html.haml +18 -0
  304. data/app/views/kaminari/_prev_page.html.haml +9 -0
  305. data/app/views/layouts/_footer.html.haml +5 -0
  306. data/app/views/layouts/_header.html.haml +39 -0
  307. data/app/views/layouts/gemgento.html.haml +22 -0
  308. data/app/workers/gemgento/apply_price_rule.rb +24 -0
  309. data/app/workers/gemgento/cart/add_item_worker.rb +23 -0
  310. data/app/workers/gemgento/cart/update_item_worker.rb +18 -0
  311. data/bin/rails +12 -0
  312. data/config/gemgento_config.yml +12 -0
  313. data/config/initializers/active_admin.rb +14 -0
  314. data/config/initializers/active_touch.rb +3 -0
  315. data/config/initializers/assets.rb +1 -0
  316. data/config/initializers/boolean_typecasting.rb +37 -0
  317. data/config/initializers/devise.rb +49 -0
  318. data/config/initializers/gemgento_config.rb +67 -0
  319. data/config/initializers/mime_types.rb +4 -0
  320. data/config/initializers/state_machine.rb +7 -0
  321. data/config/locales/en.yml +24 -0
  322. data/config/routes.rb +138 -0
  323. data/db/migrate/20151201231300_add_validation_indexes_to_gemgento_products.rb +22 -0
  324. data/db/migrate/20160122174450_gemgento2.rb +969 -0
  325. data/db/migrate/20160217142910_create_gemgento_imports.rb +15 -0
  326. data/db/migrate/20160219235858_add_timestamps_to_gemgento_asset_files.rb +6 -0
  327. data/gemgento.gemspec +44 -0
  328. data/lib/devise/models/validatable.rb +76 -0
  329. data/lib/gemgento.rb +24 -0
  330. data/lib/gemgento/admin/admin_user.rb +29 -0
  331. data/lib/gemgento/admin/api_jobs.rb +30 -0
  332. data/lib/gemgento/admin/image_import.rb +87 -0
  333. data/lib/gemgento/admin/inventory_import.rb +81 -0
  334. data/lib/gemgento/admin/product_import.rb +138 -0
  335. data/lib/gemgento/admin/product_positions.rb +49 -0
  336. data/lib/gemgento/admin/stores.rb +33 -0
  337. data/lib/gemgento/admin/subscribers.rb +31 -0
  338. data/lib/gemgento/admin/syncs.rb +26 -0
  339. data/lib/gemgento/api/soap/authnetcim/payment.rb +127 -0
  340. data/lib/gemgento/api/soap/catalog/category.rb +237 -0
  341. data/lib/gemgento/api/soap/catalog/product.rb +481 -0
  342. data/lib/gemgento/api/soap/catalog/product_attribute.rb +147 -0
  343. data/lib/gemgento/api/soap/catalog/product_attribute_media.rb +202 -0
  344. data/lib/gemgento/api/soap/catalog/product_attribute_set.rb +80 -0
  345. data/lib/gemgento/api/soap/catalog/product_tag.rb +146 -0
  346. data/lib/gemgento/api/soap/catalog/product_tier_price.rb +21 -0
  347. data/lib/gemgento/api/soap/catalog/search.rb +27 -0
  348. data/lib/gemgento/api/soap/catalog_inventory/stock_item.rb +87 -0
  349. data/lib/gemgento/api/soap/catalog_rule/rule.rb +54 -0
  350. data/lib/gemgento/api/soap/checkout/cart.rb +85 -0
  351. data/lib/gemgento/api/soap/checkout/coupon.rb +37 -0
  352. data/lib/gemgento/api/soap/checkout/customer.rb +87 -0
  353. data/lib/gemgento/api/soap/checkout/payment.rb +59 -0
  354. data/lib/gemgento/api/soap/checkout/product.rb +138 -0
  355. data/lib/gemgento/api/soap/checkout/shipping.rb +37 -0
  356. data/lib/gemgento/api/soap/customer/address.rb +143 -0
  357. data/lib/gemgento/api/soap/customer/customer.rb +200 -0
  358. data/lib/gemgento/api/soap/directory/country.rb +49 -0
  359. data/lib/gemgento/api/soap/directory/region.rb +50 -0
  360. data/lib/gemgento/api/soap/enterprise_gift_message/gift_message.rb +26 -0
  361. data/lib/gemgento/api/soap/gift_card.rb +35 -0
  362. data/lib/gemgento/api/soap/globalcollect/saved_cc.rb +58 -0
  363. data/lib/gemgento/api/soap/miscellaneous/store.rb +47 -0
  364. data/lib/gemgento/api/soap/sales/order.rb +249 -0
  365. data/lib/gemgento/api/soap/sales/order_shipment.rb +122 -0
  366. data/lib/gemgento/api/soap/sales/recurring_profile.rb +88 -0
  367. data/lib/gemgento/api/soap/stock_notification.rb +27 -0
  368. data/lib/gemgento/engine.rb +61 -0
  369. data/lib/gemgento/version.rb +3 -0
  370. data/lib/generators/gemgento/assets_generator.rb +11 -0
  371. data/lib/generators/gemgento/install_generator.rb +34 -0
  372. data/lib/generators/gemgento/templates/active_admin.css.scss +1 -0
  373. data/lib/generators/gemgento/templates/active_admin.js.coffee +1 -0
  374. data/lib/generators/gemgento/templates/active_admin.rb +3 -0
  375. data/lib/generators/gemgento/views_generator.rb +10 -0
  376. data/spec/dummy/README.rdoc +28 -0
  377. data/spec/dummy/Rakefile +6 -0
  378. data/spec/dummy/app/assets/images/.keep +0 -0
  379. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  380. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  381. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  382. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  383. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  384. data/spec/dummy/app/mailers/.keep +0 -0
  385. data/spec/dummy/app/models/.keep +0 -0
  386. data/spec/dummy/app/models/concerns/.keep +0 -0
  387. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  388. data/spec/dummy/bin/bundle +3 -0
  389. data/spec/dummy/bin/rails +4 -0
  390. data/spec/dummy/bin/rake +4 -0
  391. data/spec/dummy/bin/setup +29 -0
  392. data/spec/dummy/config.ru +4 -0
  393. data/spec/dummy/config/application.rb +32 -0
  394. data/spec/dummy/config/boot.rb +5 -0
  395. data/spec/dummy/config/database.yml +20 -0
  396. data/spec/dummy/config/environment.rb +5 -0
  397. data/spec/dummy/config/environments/development.rb +41 -0
  398. data/spec/dummy/config/environments/production.rb +79 -0
  399. data/spec/dummy/config/environments/test.rb +42 -0
  400. data/spec/dummy/config/gemgento_config.yml +22 -0
  401. data/spec/dummy/config/initializers/assets.rb +11 -0
  402. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  403. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  404. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  405. data/spec/dummy/config/initializers/inflections.rb +16 -0
  406. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  407. data/spec/dummy/config/initializers/session_store.rb +3 -0
  408. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  409. data/spec/dummy/config/locales/en.yml +23 -0
  410. data/spec/dummy/config/routes.rb +4 -0
  411. data/spec/dummy/config/secrets.yml +22 -0
  412. data/spec/dummy/lib/assets/.keep +0 -0
  413. data/spec/dummy/public/404.html +67 -0
  414. data/spec/dummy/public/422.html +67 -0
  415. data/spec/dummy/public/500.html +66 -0
  416. data/spec/dummy/public/favicon.ico +0 -0
  417. data/spec/factories/gemgento/price_tiers.rb +8 -0
  418. data/spec/factories/gemgento/product_attribute_sets.rb +22 -0
  419. data/spec/factories/gemgento/product_attributes.rb +5 -0
  420. data/spec/factories/gemgento/products.rb +14 -0
  421. data/spec/factories/gemgento/stores.rb +12 -0
  422. data/spec/factories/gemgento/user_groups.rb +6 -0
  423. data/spec/factories/gemgento/users.rb +13 -0
  424. data/spec/factories/gemgento_imports.rb +12 -0
  425. data/spec/model/gemgento/price_tier_spec.rb +45 -0
  426. data/spec/rails_helper.rb +55 -0
  427. data/spec/services/gemgento/price_spec.rb +152 -0
  428. data/spec/spec_helper.rb +87 -0
  429. metadata +919 -0
@@ -0,0 +1,586 @@
1
+ module Gemgento
2
+
3
+ # @author Gemgento LLC
4
+ class Quote < ActiveRecord::Base
5
+ belongs_to :store, class_name: 'Store'
6
+ belongs_to :user, class_name: 'User'
7
+ belongs_to :user_group, class_name: 'UserGroup'
8
+
9
+ has_many :line_items, as: :itemizable, dependent: :destroy
10
+ has_many :products, through: :line_items
11
+
12
+ has_one :order, class_name: '::Gemgento::Order'
13
+ has_one :payment, as: :payable, dependent: :destroy
14
+ has_one :billing_address, -> { where is_billing: true }, class_name: 'Address', as: :addressable, dependent: :destroy
15
+ has_one :shipping_address, -> { where is_shipping: true }, class_name: 'Address', as: :addressable, dependent: :destroy
16
+
17
+ accepts_nested_attributes_for :billing_address
18
+ accepts_nested_attributes_for :shipping_address
19
+ accepts_nested_attributes_for :payment
20
+
21
+ attr_accessor :push_customer, :push_addresses, :push_shipping_method, :push_payment_method, :subscribe,
22
+ :same_as_billing, :same_as_shipping, :destroy_after_rollback, :order_increment_id
23
+
24
+ serialize :coupon_codes, Array
25
+ serialize :gift_card_codes, Array
26
+
27
+ validates :customer_email, format: /@/, allow_nil: true
28
+ validates :billing_address, :shipping_address, presence: true, if: -> { push_addresses.to_bool }
29
+ validates :shipping_method, presence: true, if: -> { push_shipping_method.to_bool }
30
+
31
+ before_validation :copy_billing_address_to_shipping_address, if: -> { same_as_billing.to_bool }
32
+ before_validation :copy_shipping_address_to_billing_address, if: -> { same_as_shipping.to_bool }
33
+
34
+ before_create :create_magento_quote, if: -> { magento_id.nil? }
35
+
36
+ before_save :set_magento_customer, if: -> { push_customer.to_bool }
37
+ before_save :set_magento_addresses, if: -> { push_addresses.to_bool }
38
+ before_save :set_magento_shipping_method, if: -> { push_shipping_method.to_bool }
39
+ before_save :set_magento_payment_method, if: -> { push_payment_method.to_bool }
40
+
41
+ after_save :create_subscriber, if: -> { subscribe.to_bool }
42
+
43
+ after_rollback :self_destruct, if: -> { destroy_after_rollback == true }
44
+
45
+ # Get the current quote given a quote_id, Store, and User.
46
+ #
47
+ # @param store [Gemgento::Store]
48
+ # @param quote_id [Integer]
49
+ # @param user [Gemgento::User]
50
+ # @return [Gemgento:Quote]
51
+ def self.current(store, quote_id = nil, user = nil)
52
+
53
+ if !quote_id.blank? && user.nil? # quote_id but no current_user
54
+ quote = Quote.where('created_at >= ?', Date.today - 30.days).
55
+ find_by(id: quote_id, store: store, converted_at: nil)
56
+ quote = Quote.new(store: store) if quote.nil?
57
+
58
+ elsif !quote_id.blank? && !user.nil? # quote_id and current_user
59
+ quote = Quote.where('created_at >= ?', Date.today - 30.days).
60
+ find_by(id: quote_id, store: store, converted_at: nil)
61
+
62
+ if quote.nil? || (!quote.user.nil? && quote.user != user) # when quote does not belong to user
63
+ quote = Quote.where('created_at >= ?', Date.today - 30.days).
64
+ find_by(id: quote_id, store: store, user: user, converted_at: nil)
65
+ quote = Quote.new(store: store) if quote.nil?
66
+ end
67
+
68
+ elsif quote_id.blank? && !user.nil? # no quote id and a current_user
69
+ quote = Quote.where('created_at >= ?', Date.today - 30.days).
70
+ where(store: store, user: user, converted_at: nil).
71
+ order(updated_at: :desc).first_or_initialize
72
+ quote.reset unless quote.magento_id.nil?
73
+
74
+ else
75
+ quote = Quote.new(store: store)
76
+ end
77
+
78
+ return quote
79
+ end
80
+
81
+ # Quote totals.
82
+ #
83
+ # @return [Hash]
84
+ def totals
85
+ @totals ||= set_totals
86
+ end
87
+
88
+ # Fetch quote totals from Magento.
89
+ #
90
+ # @return [Array(Hash), nil]
91
+ def get_totals
92
+ response = API::SOAP::Checkout::Cart.totals(self)
93
+
94
+ if response.success?
95
+ return response.body[:result][:item]
96
+ else
97
+ handle_magento_response(response)
98
+ return nil
99
+ end
100
+ end
101
+
102
+ # Recalculate quote totals.
103
+ #
104
+ # @return [Hash]
105
+ def reset_totals
106
+ @totals = set_totals
107
+ end
108
+
109
+ # Apply a gift card to quote.
110
+ #
111
+ # @param code [String] gift card code
112
+ # @return [Boolean]
113
+ def apply_gift_card(code)
114
+ response = API::SOAP::GiftCard.quote_add(self.magento_id, code, self.store.magento_id)
115
+
116
+ if response.success?
117
+ self.gift_card_codes << code unless self.gift_card_codes.include? code
118
+ save
119
+ return true
120
+ else
121
+ handle_magento_response(response)
122
+ return false
123
+ end
124
+ end
125
+
126
+ # Remove a gift card from quote.
127
+ #
128
+ # @param code [String] gift card code
129
+ # @return [Boolean] true if the gift card was removed, otherwise an error message.
130
+ def remove_gift_card(code)
131
+ response = API::SOAP::GiftCard.quote_remove(self.magento_id, code, self.store.magento_id)
132
+
133
+ if response.success?
134
+ self.gift_card_codes.delete code
135
+ save
136
+ return true
137
+ else
138
+ handle_magento_response(response)
139
+ return false
140
+ end
141
+ end
142
+
143
+ # Apply a coupon code to the quote.
144
+ #
145
+ # @param code [String] coupon code
146
+ # @return [Boolean]
147
+ def apply_coupon(code)
148
+ response = API::SOAP::Checkout::Coupon.add(self, code)
149
+
150
+ if response.success?
151
+ self.coupon_codes << code unless self.coupon_codes.include? code
152
+ save
153
+ return true
154
+ else
155
+ handle_magento_response(response)
156
+ return false
157
+ end
158
+ end
159
+
160
+ # Remove a coupon code from the quote.
161
+ #
162
+ # @return [Boolean]
163
+ def remove_coupons
164
+ response = API::SOAP::Checkout::Coupon.remove(self)
165
+
166
+ if response.success?
167
+ self.coupon_codes = []
168
+ self.save
169
+ return true
170
+ else
171
+ handle_magento_response(response)
172
+ return false
173
+ end
174
+ end
175
+
176
+ # Set quote customer in Magento.
177
+ #
178
+ # @return [Boolean]
179
+ def set_magento_customer
180
+ response = API::SOAP::Checkout::Customer.set(self)
181
+
182
+ if response.success?
183
+ return true
184
+ else
185
+ handle_magento_response(response)
186
+ return false
187
+ end
188
+ end
189
+
190
+ # Push Quote shipping and billing addresses to Magento.
191
+ #
192
+ # @return [Boolean]
193
+ def set_magento_addresses
194
+ # re-set magento customer if guest so that customer name can be pulled from addresses.
195
+ return false if self.customer_is_guest && !self.set_magento_customer
196
+
197
+ response = API::SOAP::Checkout::Customer.address(self)
198
+
199
+ if response.success?
200
+ return true
201
+ else
202
+ handle_magento_response(response)
203
+ return false
204
+ end
205
+ end
206
+
207
+ # Fetch available shipping methods from Magento.
208
+ #
209
+ # @return [Array(Hash)]
210
+ def shipping_methods
211
+ response = API::SOAP::Checkout::Shipping.list(self)
212
+
213
+ if response.success?
214
+ return [] if response.body[:result][:item].nil?
215
+ response.body[:result][:item] = [response.body[:result][:item]] unless response.body[:result][:item].is_a? Array
216
+
217
+ return response.body[:result][:item]
218
+ else
219
+ handle_magento_response(response)
220
+ return []
221
+ end
222
+ end
223
+
224
+ # Get the shipping method price.
225
+ #
226
+ # @param selected_method [String]
227
+ # @param shipping_methods [Array(Hash), nil]
228
+ # @return [BigDecimal]
229
+ def get_shipping_amount(selected_method, shipping_methods = nil)
230
+ shipping_methods = self.shipping_methods if shipping_methods.blank?
231
+
232
+ shipping_methods.each do |shipping_method|
233
+ if shipping_method[:code] == selected_method
234
+ return shipping_method[:price].to_d
235
+ end
236
+ end
237
+
238
+ shipping_methods.uniq! { |sm| sm[:code] }
239
+
240
+ return 0.0
241
+ end
242
+
243
+ # Set Quote shipping method in Magento.
244
+ #
245
+ # @return [Boolean]
246
+ def set_magento_shipping_method
247
+ response = API::SOAP::Checkout::Shipping.method(self, self.shipping_method)
248
+
249
+ if response.success?
250
+ return true
251
+ else
252
+ handle_magento_response(response)
253
+ return false
254
+ end
255
+ end
256
+
257
+ # Get payment methods from Magento.
258
+ #
259
+ # @return [Array(Hash), nil]
260
+ def payment_methods
261
+ response = API::SOAP::Checkout::Payment.list(self)
262
+ response.body[:result]
263
+
264
+ if response.success?
265
+ return response.body[:result]
266
+ else
267
+ handle_magento_response(response)
268
+ return nil
269
+ end
270
+ end
271
+
272
+ def set_magento_payment_method
273
+ response = API::SOAP::Checkout::Payment.method(self, self.payment)
274
+
275
+ if response.success?
276
+ return true
277
+ else
278
+ handle_magento_response(response)
279
+ return false
280
+ end
281
+ end
282
+
283
+ # Convert a Quote to an Order.
284
+ #
285
+ # @return [Boolean]
286
+ def convert(remote_ip = nil)
287
+ return false unless items_in_stock?
288
+
289
+ before_convert
290
+ response = API::SOAP::Checkout::Cart.order(self, self.payment, remote_ip)
291
+
292
+ if response.success?
293
+ self.order_increment_id = response.body[:result]
294
+ self.mark_converted!
295
+ return true
296
+
297
+ else
298
+ handle_magento_response(response)
299
+ after_convert_fail
300
+ return false
301
+ end
302
+
303
+ end
304
+
305
+ # Mark a quote as converted. Ensures the Order data is fetched from Magento and calls
306
+ # the after_convert_success method.
307
+ #
308
+ # @return [Void]
309
+ def mark_converted!
310
+ begin
311
+ Gemgento::Magento::OrderAdapter.find(self.order_increment_id).import
312
+
313
+ # attempt to rescue once due to race condition of Magento pushing at the same time
314
+ # after one retry, just move past, the quote has been converted and
315
+ # we can't throw an error at this point in time
316
+ rescue Exception
317
+ if (retries ||= 0) <= 1
318
+ retries += 1
319
+ retry
320
+ end
321
+ end
322
+
323
+ self.converted_at = Time.now
324
+ self.save
325
+ self.reload
326
+
327
+ if self.user && Config[:extensions]['authorize-net-cim-payment-module']
328
+ Gemgento::API::SOAP::Authnetcim::Payment.fetch(self.user)
329
+ end
330
+
331
+ after_convert_success
332
+ end
333
+
334
+ def before_convert
335
+
336
+ end
337
+
338
+ def after_convert_success
339
+ push_gift_message_comment unless self.gift_message.blank?
340
+ end
341
+
342
+ def after_convert_fail
343
+
344
+ end
345
+
346
+ def as_json(options = nil)
347
+ result = super
348
+ result['user'] = self.user
349
+ result['line_items'] = self.line_items
350
+ result['shipping_address'] = self.shipping_address
351
+ result['billing_address'] = self.billing_address
352
+ result['payment'] = self.payment
353
+ result['totals'] = self.totals
354
+ return result
355
+ end
356
+
357
+ # Calculate the subtotal of the Quote.
358
+ #
359
+ # @return [BigDecimal]
360
+ def subtotal
361
+ if self.line_items.any?
362
+ return self.line_items.map{ |li| li.price * li.qty_ordered.to_d }.inject(&:+)
363
+ else
364
+ return 0
365
+ end
366
+ end
367
+
368
+ # Total quantity of line items.
369
+ #
370
+ # @return [BigDecimal]
371
+ def item_quantity
372
+ line_items.sum(:qty_ordered).to_d
373
+ end
374
+
375
+ # Reset quote data to before checkout began.
376
+ #
377
+ # @return [Void]
378
+ def reset
379
+ self.user_id = nil
380
+ self.customer_email = nil
381
+ self.billing_address.destroy unless self.billing_address.nil?
382
+ self.shipping_address.destroy unless self.shipping_address.nil?
383
+ self.shipping_method = nil
384
+ self.shipping_amount = nil
385
+ self.payment.destroy unless self.payment.nil?
386
+ self.save
387
+ end
388
+
389
+ # Push the gift_message to associated Magento Order as a comment.
390
+ #
391
+ # @return [Void]
392
+ def push_gift_message_comment
393
+ API::SOAP::Sales::Order.add_comment(self.order.increment_id, self.order.status, "Gemgento Gift Message: #{self.gift_message}")
394
+ order.update(gift_message: self.gift_message)
395
+ end
396
+
397
+ def items_in_stock?
398
+ self.line_items.each do |line_item|
399
+ self.equalize_qty_ordered(line_item) unless line_item.product.in_stock?(line_item.qty_ordered, self.store)
400
+ end
401
+ end
402
+
403
+ def equalize_qty_ordered(line_item)
404
+ inventory = line_item.product.inventories.find_by(store: self.store)
405
+
406
+ if inventory.quantity > 0
407
+ line_item.update(qty_ordered: inventory.quantity)
408
+ errors.add(:base, "available quantity of #{line_item.product.attribute_value('name', self.store)} has been reduced to reflect inventory updates")
409
+ else
410
+ line_item.destroy
411
+ errors.add(:base, "#{line_item.product.attribute_value('name', self.store)} is no longer available and has been removed from your cart")
412
+ end
413
+ end
414
+
415
+ # Determine if a shipping method is required for the Quote.
416
+ #
417
+ # @return [Boolean]
418
+ def shipping_method_required?
419
+ self.line_items.collect do |li|
420
+ return true if li.product.magento_type != 'giftvoucher'
421
+ end
422
+
423
+ return false
424
+ end
425
+
426
+ private
427
+
428
+ # Create the quote in Magento. Used as a before_create callback.
429
+ #
430
+ # @return [Void]
431
+ def create_magento_quote
432
+ response = API::SOAP::Checkout::Cart.create(self)
433
+
434
+ if response.success?
435
+ self.magento_id = response.body[:quote_id]
436
+ return true
437
+ else
438
+ handle_magento_response(response)
439
+ return false
440
+ end
441
+ end
442
+
443
+ # Create a Subscriber from the Quote User.
444
+ #
445
+ # @return [Gemgento::Subscriber]
446
+ def create_subscriber
447
+ Subscriber.create(email: self.customer_email)
448
+ end
449
+
450
+ # Duplicate the billing address to use as shipping address.
451
+ #
452
+ # @return [Void]
453
+ def copy_billing_address_to_shipping_address
454
+ Rails.logger.debug 'Copying billing address to shipping address'
455
+ self.build_shipping_address if self.shipping_address.nil?
456
+ self.shipping_address.attributes = self.billing_address.duplicate.attributes.reject{ |k| k == 'id' }.merge(
457
+ {
458
+ id: self.shipping_address ? self.shipping_address.id : nil,
459
+ address1: self.billing_address.address1,
460
+ address2: self.billing_address.address2,
461
+ address3: self.billing_address.address3,
462
+ is_shipping: true,
463
+ is_billing: false
464
+ }
465
+ )
466
+ self.shipping_address.addressable = self
467
+ end
468
+
469
+ # Duplicate the shipping address to use as billing address.
470
+ #
471
+ # @return [Void]
472
+ def copy_shipping_address_to_billing_address
473
+ Rails.logger.debug 'Copying shipping address to billing address'
474
+ self.build_billing_address if self.billing_address.nil?
475
+ self.billing_address.attributes = self.shipping_address.duplicate.attributes.reject{ |k| k == 'id' }.merge(
476
+ {
477
+ id: self.billing_address ? self.billing_address.id : nil,
478
+ address1: self.shipping_address.address1,
479
+ address2: self.shipping_address.address2,
480
+ address3: self.shipping_address.address3,
481
+ is_shipping: false,
482
+ is_billing: true
483
+ }
484
+ )
485
+ self.billing_address.addressable = self
486
+ end
487
+
488
+ # Set quote totals based on Magento API call.
489
+ #
490
+ # @return [Hash]
491
+ def set_totals
492
+ magento_totals = self.get_totals
493
+ totals = {
494
+ subtotal: 0,
495
+ discounts: {},
496
+ gift_card: 0,
497
+ nominal: {},
498
+ shipping: 0,
499
+ tax: 0,
500
+ total: 0
501
+ }
502
+
503
+ unless magento_totals.nil?
504
+ magento_totals.each do |total|
505
+ unless total[:title].include? 'Discount'
506
+ if !total[:title].include? 'Nominal' # regular checkout values
507
+ if total[:title].include? 'Subtotal'
508
+ totals[:subtotal] = total[:amount].to_f
509
+ totals[:subtotal] = self.subtotal if totals[:subtotal] == 0
510
+ elsif total[:title].include? 'Grand Total'
511
+ totals[:total] = total[:amount].to_f
512
+ elsif total[:title].include? 'Tax'
513
+ totals[:tax] = total[:amount].to_f
514
+ elsif total[:title].include? 'Shipping'
515
+ totals[:shipping] = total[:amount].to_f
516
+ elsif total[:title].include? 'Gift Card'
517
+ totals[:gift_card] = total[:amount].to_f
518
+ end
519
+ else # checkout values for a nominal item
520
+ if total[:title].include? 'Subtotal'
521
+ totals[:nominal][:subtotal] = total[:amount].to_f
522
+ totals[:nominal][:subtotal] = self.subtotal if totals[:nominal][:subtotal] == 0
523
+ elsif total[:title].include? 'Total'
524
+ totals[:nominal][:total] = total[:amount].to_f
525
+ elsif total[:title].include? 'Tax'
526
+ totals[:nominal][:tax] = total[:amount].to_f
527
+ elsif total[:title].include? 'Shipping'
528
+ totals[:nominal][:shipping] = total[:amount].to_f
529
+ elsif total[:title].include? 'Gift Card'
530
+ totals[:gift_card] == total[:amount].to_f
531
+ end
532
+ end
533
+ else
534
+ code = total[:title][10..-2]
535
+ totals[:discounts][code.to_sym] = total[:amount].to_f
536
+ end
537
+ end
538
+
539
+ # if subtotal is not zero and total is zero, we need to calculate total to ensure it should be zero.
540
+ # Magento may not have calculated total because of missing addresses, shipping methods, etc.
541
+ if totals[:total].zero? && !totals[:subtotal].zero?
542
+ totals[:total] += totals[:subtotal]
543
+ totals[:total] += totals[:shipping]
544
+ totals[:total] += totals[:tax]
545
+ totals[:total] -= totals[:gift_card].abs
546
+ totals[:total] -= totals[:discounts].values.inject(0, :+).abs
547
+ totals[:total] = totals[:total].round(2) # fix loss of float precision
548
+ end
549
+
550
+ # nominal shipping isn't calculated correctly, so we can set it based on known selected values
551
+ if !totals[:nominal].has_key?(:shipping) && totals[:nominal].has_key?(:subtotal) && self.shipping_address
552
+ if totals[:shipping] && totals[:shipping] > 0
553
+ totals[:nominal][:shipping] = totals[:shipping]
554
+ elsif shipping_method = get_magento_shipping_method
555
+ totals[:nominal][:shipping] = shipping_method['price'].to_f
556
+ else
557
+ totals[:nominal][:shipping] = 0.0
558
+ end
559
+
560
+ totals[:nominal][:total] += totals[:nominal][:shipping] if totals[:nominal].has_key?(:total) # make sure the grand total reflects the shipping changes
561
+ end
562
+ end
563
+
564
+ return totals
565
+ end
566
+
567
+ # Handle the Magento create/update/destroy response. Mark self for destruction if it no longer exists in Magento.
568
+ #
569
+ # @param response [Gemgento::MagentoResponse]
570
+ # @return [Void]
571
+ def handle_magento_response(response)
572
+ if response.body[:faultcode].to_i == 1002 # quote doesn't exist in Magento.
573
+ self.destroy_after_rollback = true
574
+ else
575
+ self.errors.add(:base, response.body[:faultstring])
576
+ end
577
+ end
578
+
579
+ def self_destruct
580
+ LineItem.skip_callback(:destroy, :before, :destroy_magento_quote_item)
581
+ self.destroy
582
+ LineItem.set_callback(:destroy, :before, :destroy_magento_quote_item)
583
+ end
584
+
585
+ end
586
+ end