spree_core 4.2.5 → 4.3.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 (263) hide show
  1. checksums.yaml +4 -4
  2. data/app/finders/concerns/spree/product_filterable.rb +9 -0
  3. data/app/finders/spree/cms_pages/find.rb +41 -0
  4. data/app/finders/spree/menus/find.rb +11 -0
  5. data/app/finders/spree/option_values/find_available.rb +20 -0
  6. data/app/finders/spree/orders/find_complete.rb +14 -2
  7. data/app/finders/spree/orders/find_current.rb +1 -13
  8. data/app/finders/spree/product_properties/find_available.rb +20 -0
  9. data/app/finders/spree/products/find.rb +80 -21
  10. data/app/finders/spree/stores/find_current.rb +24 -0
  11. data/app/finders/spree/taxons/find.rb +22 -6
  12. data/app/helpers/spree/base_helper.rb +69 -7
  13. data/app/helpers/spree/locale_helper.rb +5 -1
  14. data/app/helpers/spree/products_helper.rb +7 -3
  15. data/app/models/concerns/spree/display_link.rb +42 -0
  16. data/app/models/concerns/spree/display_money.rb +6 -2
  17. data/app/models/concerns/spree/filter_param.rb +21 -0
  18. data/app/models/concerns/spree/image_methods.rb +24 -0
  19. data/app/models/concerns/spree/memoized_data.rb +24 -0
  20. data/app/models/concerns/spree/multi_store_resource.rb +24 -0
  21. data/app/models/concerns/spree/product_scopes.rb +71 -8
  22. data/app/models/concerns/spree/single_store_resource.rb +19 -0
  23. data/app/models/concerns/spree/user_address.rb +19 -0
  24. data/app/models/concerns/spree/user_methods.rb +14 -12
  25. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  26. data/app/models/concerns/spree/user_reporting.rb +35 -10
  27. data/app/models/concerns/spree/user_roles.rb +25 -0
  28. data/app/models/spree/ability.rb +3 -1
  29. data/app/models/spree/address.rb +27 -6
  30. data/app/models/spree/app_configuration.rb +8 -0
  31. data/app/models/spree/app_dependencies.rb +20 -6
  32. data/app/models/spree/base.rb +18 -0
  33. data/app/models/spree/classification.rb +3 -0
  34. data/app/models/spree/cms/pages/feature_page.rb +7 -0
  35. data/app/models/spree/cms/pages/homepage.rb +20 -0
  36. data/app/models/spree/cms/pages/standard_page.rb +4 -0
  37. data/app/models/spree/cms/sections/featured_article.rb +22 -0
  38. data/app/models/spree/cms/sections/hero_image.rb +38 -0
  39. data/app/models/spree/cms/sections/image_gallery.rb +103 -0
  40. data/app/models/spree/cms/sections/product_carousel.rb +14 -0
  41. data/app/models/spree/cms/sections/rich_text_content.rb +13 -0
  42. data/app/models/spree/cms/sections/side_by_side_images.rb +74 -0
  43. data/app/models/spree/cms_page.rb +66 -0
  44. data/app/models/spree/cms_section.rb +69 -0
  45. data/app/models/spree/country.rb +14 -6
  46. data/app/models/spree/credit_card.rb +2 -8
  47. data/app/models/spree/customer_return.rb +8 -2
  48. data/app/models/spree/gateway/bogus.rb +6 -4
  49. data/app/models/spree/icon.rb +9 -0
  50. data/app/models/spree/image/configuration/active_storage.rb +2 -0
  51. data/app/models/spree/image.rb +5 -24
  52. data/app/models/spree/inventory_unit.rb +1 -1
  53. data/app/models/spree/line_item.rb +1 -1
  54. data/app/models/spree/menu.rb +63 -0
  55. data/app/models/spree/menu_item.rb +76 -0
  56. data/app/models/spree/option_type.rb +1 -1
  57. data/app/models/spree/option_value.rb +11 -0
  58. data/app/models/spree/option_value_variant.rb +1 -1
  59. data/app/models/spree/order/address_book.rb +3 -5
  60. data/app/models/spree/order/currency_updater.rb +1 -1
  61. data/app/models/spree/order/emails.rb +32 -0
  62. data/app/models/spree/order/payments.rb +1 -1
  63. data/app/models/spree/order/store_credit.rb +1 -1
  64. data/app/models/spree/order.rb +46 -45
  65. data/app/models/spree/payment.rb +7 -0
  66. data/app/models/spree/payment_method.rb +16 -0
  67. data/app/models/spree/preferences/preferable.rb +12 -0
  68. data/app/models/spree/preferences/preferable_class_methods.rb +10 -1
  69. data/app/models/spree/product.rb +37 -30
  70. data/app/models/spree/product_property.rb +19 -4
  71. data/app/models/spree/promotion/rules/country.rb +1 -1
  72. data/app/models/spree/promotion/rules/first_order.rb +4 -3
  73. data/app/models/spree/promotion/rules/taxon.rb +10 -7
  74. data/app/models/spree/promotion.rb +6 -15
  75. data/app/models/spree/promotion_handler/cart.rb +7 -2
  76. data/app/models/spree/promotion_handler/coupon.rb +5 -4
  77. data/app/models/spree/promotion_handler/free_shipping.rb +5 -6
  78. data/app/models/spree/promotion_handler/page.rb +3 -2
  79. data/app/models/spree/promotion_handler/promotion_duplicator.rb +1 -0
  80. data/app/models/spree/promotion_rule.rb +2 -0
  81. data/app/models/spree/property.rb +28 -1
  82. data/app/models/spree/reimbursement.rb +3 -1
  83. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +2 -1
  84. data/app/models/spree/shipment_handler.rb +4 -2
  85. data/app/models/spree/stock/quantifier.rb +6 -6
  86. data/app/models/spree/stock_location.rb +9 -0
  87. data/app/models/spree/store.rb +90 -7
  88. data/app/models/spree/store_credit.rb +7 -3
  89. data/app/models/spree/store_credit_event.rb +2 -2
  90. data/app/models/spree/store_payment_method.rb +11 -0
  91. data/app/models/spree/store_product.rb +11 -0
  92. data/app/models/spree/store_promotion.rb +11 -0
  93. data/app/models/spree/taxon.rb +22 -1
  94. data/app/models/spree/taxon_image/configuration/active_storage.rb +2 -0
  95. data/app/models/spree/taxon_image.rb +1 -0
  96. data/app/models/spree/taxonomy.rb +3 -1
  97. data/app/models/spree/variant.rb +21 -6
  98. data/app/presenters/spree/filters/options_presenter.rb +47 -0
  99. data/app/presenters/spree/filters/price_presenter.rb +22 -0
  100. data/app/presenters/spree/filters/price_range_presenter.rb +29 -0
  101. data/app/presenters/spree/filters/properties_presenter.rb +23 -0
  102. data/app/presenters/spree/filters/property_presenter.rb +42 -0
  103. data/app/presenters/spree/filters/quantified_price_range_presenter.rb +44 -0
  104. data/app/services/spree/account/addresses/create.rb +1 -0
  105. data/app/services/spree/account/addresses/helper.rb +6 -0
  106. data/app/services/spree/account/addresses/update.rb +9 -3
  107. data/app/services/spree/account/create.rb +17 -0
  108. data/app/services/spree/account/update.rb +15 -0
  109. data/app/services/spree/build_localized_redirect_url.rb +1 -1
  110. data/app/services/spree/cart/associate.rb +16 -0
  111. data/app/services/spree/cart/change_currency.rb +27 -0
  112. data/app/services/spree/cart/create.rb +5 -3
  113. data/app/services/spree/cart/destroy.rb +40 -0
  114. data/app/services/spree/cart/empty.rb +36 -0
  115. data/app/services/spree/cart/estimate_shipping_rates.rb +3 -3
  116. data/app/services/spree/checkout/add_store_credit.rb +1 -1
  117. data/app/services/spree/classifications/reposition.rb +18 -0
  118. data/app/services/spree/credit_cards/destroy.rb +41 -0
  119. data/app/sorters/spree/base_sorter.rb +23 -11
  120. data/app/sorters/spree/products/sort.rb +23 -7
  121. data/app/validators/db_maximum_length_validator.rb +5 -0
  122. data/app/validators/email_validator.rb +3 -1
  123. data/config/initializers/active_storage.rb +2 -0
  124. data/config/locales/en.yml +177 -3
  125. data/config/routes.rb +0 -5
  126. data/db/migrate/20201023152810_add_filterable_to_spree_properties.rb +8 -0
  127. data/db/migrate/20210407200948_create_spree_menus.rb +16 -0
  128. data/db/migrate/20210408092939_create_spree_menu_items.rb +31 -0
  129. data/db/migrate/20210504163720_add_filter_param_to_spree_product_properties.rb +8 -0
  130. data/db/migrate/20210505114659_add_filter_param_to_spree_properties.rb +8 -0
  131. data/db/migrate/20210512191732_create_spree_cms_pages.rb +24 -0
  132. data/db/migrate/20210514204251_create_spree_cms_sections.rb +22 -0
  133. data/db/migrate/20210527094055_create_spree_products_stores.rb +36 -0
  134. data/db/migrate/20210608045519_ensure_store_default_country_is_set.rb +5 -0
  135. data/db/migrate/20210702112334_add_missing_timestamp_columns.rb +46 -0
  136. data/db/migrate/20210713131614_add_unique_index_on_property_id_and_product_id_to_product_properties.rb +29 -0
  137. data/db/migrate/20210715091956_add_store_id_to_spree_store_credits.rb +10 -0
  138. data/db/migrate/20210716093151_add_store_id_to_spree_taxonomies.rb +11 -0
  139. data/db/migrate/20210716104141_add_index_on_name_parent_id_and_taxonomy_id_on_spree_taxons.rb +31 -0
  140. data/db/migrate/20210721120857_add_index_on_permalink_parent_id_and_taxonomy_id_on_spree_taxons.rb +31 -0
  141. data/db/migrate/20210721125657_create_spree_promotions_stores.rb +29 -0
  142. data/db/migrate/20210722090705_add_store_id_to_spree_customer_returns.rb +11 -0
  143. data/db/migrate/20210726065456_change_integer_id_columns_into_bigint.rb +305 -0
  144. data/db/migrate/20210730154425_fix_promotion_code_and_path_unique_indexes.rb +9 -0
  145. data/lib/generators/spree/dummy/dummy_generator.rb +11 -6
  146. data/lib/generators/spree/dummy/templates/rails/test.rb +2 -0
  147. data/lib/generators/spree/dummy_model/templates/model.rb.tt +1 -1
  148. data/lib/generators/spree/install/install_generator.rb +12 -24
  149. data/lib/spree/core/components.rb +8 -0
  150. data/lib/spree/core/controller_helpers/auth.rb +7 -1
  151. data/lib/spree/core/controller_helpers/common.rb +1 -1
  152. data/lib/spree/core/controller_helpers/order.rb +4 -4
  153. data/lib/spree/core/controller_helpers/search.rb +1 -0
  154. data/lib/spree/core/controller_helpers/store.rb +24 -1
  155. data/lib/spree/core/engine.rb +6 -0
  156. data/lib/spree/core/importer/product.rb +3 -1
  157. data/lib/spree/core/product_duplicator.rb +1 -0
  158. data/lib/spree/core/search/base.rb +17 -22
  159. data/lib/spree/core/version.rb +1 -1
  160. data/lib/spree/core.rb +8 -4
  161. data/lib/spree/i18n.rb +1 -1
  162. data/lib/spree/money.rb +2 -1
  163. data/lib/spree/permitted_attributes.rb +21 -3
  164. data/lib/spree/testing_support/authorization_helpers.rb +6 -3
  165. data/lib/spree/testing_support/capybara_config.rb +3 -1
  166. data/lib/spree/testing_support/common_rake.rb +17 -4
  167. data/lib/spree/testing_support/extension_rake.rb +2 -2
  168. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  169. data/lib/spree/testing_support/factories/classification_factory.rb +8 -0
  170. data/lib/spree/testing_support/factories/cms_page_factory.rb +20 -0
  171. data/lib/spree/testing_support/factories/cms_section_factory.rb +31 -0
  172. data/lib/spree/testing_support/factories/customer_return_factory.rb +24 -17
  173. data/lib/spree/testing_support/factories/icon_factory.rb +7 -0
  174. data/lib/spree/testing_support/factories/line_item_factory.rb +6 -2
  175. data/lib/spree/testing_support/factories/menu_factory.rb +16 -0
  176. data/lib/spree/testing_support/factories/menu_item_factory.rb +10 -0
  177. data/lib/spree/testing_support/factories/options_factory.rb +5 -0
  178. data/lib/spree/testing_support/factories/order_factory.rb +11 -2
  179. data/lib/spree/testing_support/factories/payment_method_factory.rb +6 -2
  180. data/lib/spree/testing_support/factories/product_factory.rb +17 -1
  181. data/lib/spree/testing_support/factories/product_property_factory.rb +1 -1
  182. data/lib/spree/testing_support/factories/promotion_factory.rb +18 -9
  183. data/lib/spree/testing_support/factories/property_factory.rb +22 -0
  184. data/lib/spree/testing_support/factories/stock_location_factory.rb +5 -4
  185. data/lib/spree/testing_support/factories/store_credit_factory.rb +1 -0
  186. data/lib/spree/testing_support/factories/store_factory.rb +11 -0
  187. data/lib/spree/testing_support/factories/taxon_factory.rb +3 -1
  188. data/lib/spree/testing_support/factories/taxon_image_factory.rb +7 -0
  189. data/lib/spree/testing_support/factories/taxonomy_factory.rb +1 -0
  190. data/lib/spree/testing_support/factories/user_factory.rb +7 -2
  191. data/lib/spree/testing_support/factories/variant_factory.rb +2 -2
  192. data/lib/spree/testing_support/flatpickr_capybara.rb +58 -35
  193. data/lib/spree/testing_support/locale_helpers.rb +1 -1
  194. data/lib/spree/testing_support/order_walkthrough.rb +9 -9
  195. data/lib/spree/testing_support/rspec_retry_config.rb +5 -0
  196. data/lib/tasks/core.rake +1 -1
  197. data/spec/fixtures/favicon.ico +0 -0
  198. data/spec/fixtures/files/icon_256x256.gif +0 -0
  199. data/spec/fixtures/files/icon_256x256.png +0 -0
  200. data/spec/fixtures/files/icon_512x512.png +0 -0
  201. data/spec/fixtures/files/img_256x128.png +0 -0
  202. data/spree_core.gemspec +12 -11
  203. metadata +211 -159
  204. data/app/assets/images/logo/spree_50.png +0 -0
  205. data/app/assets/images/noimage/large.png +0 -0
  206. data/app/assets/images/noimage/mini.png +0 -0
  207. data/app/assets/images/noimage/product.png +0 -0
  208. data/app/assets/images/noimage/small.png +0 -0
  209. data/app/assets/javascripts/spree.js +0 -78
  210. data/app/controllers/spree/errors_controller.rb +0 -11
  211. data/app/helpers/spree/mail_helper.rb +0 -29
  212. data/app/mailers/spree/base_mailer.rb +0 -46
  213. data/app/mailers/spree/order_mailer.rb +0 -26
  214. data/app/mailers/spree/reimbursement_mailer.rb +0 -12
  215. data/app/mailers/spree/shipment_mailer.rb +0 -12
  216. data/app/mailers/spree/test_mailer.rb +0 -8
  217. data/app/models/spree/validations/db_maximum_length_validator.rb +0 -22
  218. data/app/views/layouts/spree/base_mailer.html.erb +0 -46
  219. data/app/views/spree/errors/forbidden.html.erb +0 -0
  220. data/app/views/spree/errors/unauthorized.html.erb +0 -0
  221. data/app/views/spree/order_mailer/cancel_email.html.erb +0 -24
  222. data/app/views/spree/order_mailer/cancel_email.text.erb +0 -38
  223. data/app/views/spree/order_mailer/confirm_email.html.erb +0 -23
  224. data/app/views/spree/order_mailer/confirm_email.text.erb +0 -39
  225. data/app/views/spree/order_mailer/store_owner_notification_email.html.erb +0 -23
  226. data/app/views/spree/order_mailer/store_owner_notification_email.text.erb +0 -38
  227. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +0 -56
  228. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +0 -24
  229. data/app/views/spree/shared/_base_mailer_footer.html.erb +0 -12
  230. data/app/views/spree/shared/_base_mailer_header.html.erb +0 -13
  231. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +0 -456
  232. data/app/views/spree/shared/_error_messages.html.erb +0 -11
  233. data/app/views/spree/shared/_mailer_line_item.html.erb +0 -16
  234. data/app/views/spree/shared/_paths.html.erb +0 -8
  235. data/app/views/spree/shared/_purchased_items_table.html.erb +0 -69
  236. data/app/views/spree/shared/purchased_items_table/_adjustment.html.erb +0 -13
  237. data/app/views/spree/shared/purchased_items_table/_line_item.html.erb +0 -27
  238. data/app/views/spree/shared/purchased_items_table/_subtotal.html.erb +0 -13
  239. data/app/views/spree/shared/purchased_items_table/_total.html.erb +0 -13
  240. data/app/views/spree/shipment_mailer/shipped_email.html.erb +0 -36
  241. data/app/views/spree/shipment_mailer/shipped_email.text.erb +0 -17
  242. data/app/views/spree/test_mailer/test_email.html.erb +0 -40
  243. data/app/views/spree/test_mailer/test_email.text.erb +0 -4
  244. data/config/initializers/assets.rb +0 -2
  245. data/config/initializers/premailer_assets.rb +0 -1
  246. data/config/initializers/premailer_rails.rb +0 -3
  247. data/db/migrate/20140805171219_make_existing_credit_cards_default.rb +0 -10
  248. data/lib/generators/spree/dummy/templates/initializers/bullet.rb +0 -5
  249. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/backend/all.js +0 -15
  250. data/lib/generators/spree/install/templates/vendor/assets/javascripts/spree/frontend/all.js +0 -16
  251. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/backend/all.css +0 -16
  252. data/lib/generators/spree/install/templates/vendor/assets/stylesheets/spree/frontend/all.css +0 -16
  253. data/lib/generators/spree/mailers_preview/mailers_preview_generator.rb +0 -23
  254. data/lib/generators/spree/mailers_preview/templates/mailers/previews/order_preview.rb +0 -13
  255. data/lib/generators/spree/mailers_preview/templates/mailers/previews/reimbursement_preview.rb +0 -5
  256. data/lib/generators/spree/mailers_preview/templates/mailers/previews/shipment_preview.rb +0 -5
  257. data/lib/generators/spree/mailers_preview/templates/mailers/previews/user_preview.rb +0 -11
  258. data/lib/tasks/email.rake +0 -10
  259. data/vendor/assets/javascripts/cleave.js +0 -1669
  260. data/vendor/assets/javascripts/fetch.umd.js +0 -531
  261. data/vendor/assets/javascripts/jquery.payment.js +0 -652
  262. data/vendor/assets/javascripts/jsuri.js +0 -458
  263. data/vendor/assets/javascripts/polyfill.min.js +0 -1
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ module SingleStoreResource
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ validate :ensure_store_association_is_not_changed
7
+
8
+ scope :for_store, ->(store) { where(store_id: store.id) }
9
+ end
10
+
11
+ protected
12
+
13
+ def ensure_store_association_is_not_changed
14
+ if store_id_changed? && persisted?
15
+ errors.add(:store, Spree.t('errors.messages.store_association_can_not_be_changed'))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -16,7 +16,12 @@ module Spree
16
16
  has_many :addresses, -> { where(deleted_at: nil).order('updated_at DESC') },
17
17
  class_name: 'Spree::Address', foreign_key: :user_id
18
18
 
19
+ validate :address_not_associated_with_other_user, :address_not_deprecated_in_completed_order
20
+
19
21
  def persist_order_address(order)
22
+ # FIXME: we should check if the User's address is associated with country accepted by Store
23
+ # if not we should try to find an address with valid country in User's address book
24
+ # or we should call `build_bill_address`
20
25
  b_address = bill_address || build_bill_address
21
26
  b_address.attributes = order.bill_address.value_attributes
22
27
  b_address.save
@@ -30,6 +35,20 @@ module Spree
30
35
  update(ship_address_id: s_address.id)
31
36
  end
32
37
  end
38
+
39
+ private
40
+
41
+ def address_not_associated_with_other_user
42
+ errors.add(:bill_address_id, :belongs_to_other_user) if bill_address&.user_id && self != bill_address&.user
43
+ errors.add(:ship_address_id, :belongs_to_other_user) if ship_address&.user_id && self != ship_address&.user
44
+ end
45
+
46
+ def address_not_deprecated_in_completed_order
47
+ errors.add(:bill_address_id, :deprecated_in_completed_order) if
48
+ orders.complete.with_deleted_bill_address.where(bill_address: bill_address_id).any?
49
+ errors.add(:ship_address_id, :deprecated_in_completed_order) if
50
+ orders.complete.with_deleted_ship_address.where(ship_address: ship_address_id).any?
51
+ end
33
52
  end
34
53
  end
35
54
  end
@@ -4,6 +4,7 @@ module Spree
4
4
 
5
5
  include Spree::UserPaymentSource
6
6
  include Spree::UserReporting
7
+ include Spree::UserRoles
7
8
  include Spree::RansackableAttributes
8
9
 
9
10
  included do
@@ -15,9 +16,6 @@ module Spree
15
16
 
16
17
  attr_accessor :use_billing
17
18
 
18
- has_many :role_users, class_name: 'Spree::RoleUser', foreign_key: :user_id, dependent: :destroy
19
- has_many :spree_roles, through: :role_users, class_name: 'Spree::Role', source: :role
20
-
21
19
  has_many :promotion_rule_users, class_name: 'Spree::PromotionRuleUser', foreign_key: :user_id, dependent: :destroy
22
20
  has_many :promotion_rules, through: :promotion_rule_users, class_name: 'Spree::PromotionRule'
23
21
 
@@ -27,7 +25,7 @@ module Spree
27
25
  belongs_to :ship_address, class_name: 'Spree::Address', optional: true
28
26
  belongs_to :bill_address, class_name: 'Spree::Address', optional: true
29
27
 
30
- self.whitelisted_ransackable_associations = %w[bill_address ship_address]
28
+ self.whitelisted_ransackable_associations = %w[bill_address ship_address addresses]
31
29
  self.whitelisted_ransackable_attributes = %w[id email]
32
30
 
33
31
  def self.with_email(query)
@@ -47,11 +45,6 @@ module Spree
47
45
  end
48
46
  end
49
47
 
50
- # has_spree_role? simply needs to return true or false whether a user has a role or not.
51
- def has_spree_role?(role_in_question)
52
- spree_roles.any? { |role| role.name == role_in_question.to_s }
53
- end
54
-
55
48
  def last_incomplete_spree_order(store, options = {})
56
49
  orders.where(store: store).incomplete.
57
50
  includes(options[:includes]).
@@ -59,9 +52,18 @@ module Spree
59
52
  first
60
53
  end
61
54
 
62
- def total_available_store_credit(currency = nil)
63
- currency ||= Spree::Config[:currency]
64
- store_credits.where(currency: currency).reload.to_a.sum(&:amount_remaining)
55
+ def total_available_store_credit(currency = nil, store = nil)
56
+ store ||= Store.default
57
+ currency ||= store.default_currency
58
+ store_credits.for_store(store).where(currency: currency).reload.to_a.sum(&:amount_remaining)
59
+ end
60
+
61
+ def available_store_credits(store)
62
+ store ||= Store.default
63
+
64
+ store_credits.for_store(store).pluck(:currency).uniq.each_with_object([]) do |currency, arr|
65
+ arr << Spree::Money.new(total_available_store_credit(currency, store), currency: currency)
66
+ end
65
67
  end
66
68
 
67
69
  private
@@ -9,7 +9,7 @@ module Spree
9
9
  end
10
10
 
11
11
  def payment_sources
12
- credit_cards.with_payment_profile.not_expired.where(payment_method: Spree::PaymentMethod.active)
12
+ credit_cards.with_payment_profile.not_expired.where(payment_method: Spree::PaymentMethod.active).not_removed
13
13
  end
14
14
 
15
15
  def drop_payment_source(source)
@@ -3,20 +3,45 @@ module Spree
3
3
  extend DisplayMoney
4
4
  money_methods :lifetime_value, :average_order_value
5
5
 
6
- def lifetime_value
7
- orders.complete.sum(:total)
6
+ def report_values_for(report_name, store)
7
+ store ||= Store.default
8
+
9
+ completed_orders(store).pluck(:currency).uniq.each_with_object([]) do |currency, arr|
10
+ arr << send("display_#{report_name}", store: store, currency: currency)
11
+ end
8
12
  end
9
13
 
10
- def order_count
11
- orders.complete.size
14
+ def lifetime_value(**args)
15
+ order_calculate(operation: :sum,
16
+ column: :total,
17
+ **args)
12
18
  end
13
19
 
14
- def average_order_value
15
- if order_count > 0
16
- lifetime_value / order_count
17
- else
18
- BigDecimal('0.00')
19
- end
20
+ def average_order_value(**args)
21
+ order_calculate(operation: :average,
22
+ column: :total,
23
+ **args)
24
+ end
25
+
26
+ def order_count(store = nil)
27
+ store ||= Store.default
28
+ order_calculate(store: store,
29
+ currency: store.supported_currencies.split(','),
30
+ operation: :count,
31
+ column: :all)
32
+ end
33
+
34
+ private
35
+
36
+ def order_calculate(operation:, column:, store: nil, currency: nil)
37
+ store ||= Store.default
38
+ currency ||= store.default_currency
39
+
40
+ completed_orders(store).where(currency: currency).calculate(operation, column) || BigDecimal('0.00')
41
+ end
42
+
43
+ def completed_orders(store)
44
+ orders.for_store(store).complete
20
45
  end
21
46
  end
22
47
  end
@@ -0,0 +1,25 @@
1
+ module Spree
2
+ module UserRoles
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ has_many :role_users, class_name: 'Spree::RoleUser', foreign_key: :user_id, dependent: :destroy
7
+ has_many :spree_roles, through: :role_users, class_name: 'Spree::Role', source: :role
8
+
9
+ scope :admin, -> { joins(:spree_roles).where(Spree::Role.table_name => { name: 'admin' }) }
10
+
11
+ # has_spree_role? simply needs to return true or false whether a user has a role or not.
12
+ def has_spree_role?(role_name)
13
+ spree_roles.exists?(name: role_name)
14
+ end
15
+
16
+ def self.admin_created?
17
+ admin.exists?
18
+ end
19
+
20
+ def admin?
21
+ has_spree_role?('admin')
22
+ end
23
+ end
24
+ end
25
+ end
@@ -61,6 +61,8 @@ module Spree
61
61
 
62
62
  def apply_user_permissions(user)
63
63
  can :read, ::Spree::Country
64
+ can :read, ::Spree::Menu
65
+ can :read, ::Spree::CmsPage
64
66
  can :read, ::Spree::OptionType
65
67
  can :read, ::Spree::OptionValue
66
68
  can :create, ::Spree::Order
@@ -71,7 +73,7 @@ module Spree
71
73
  !order.completed? && (order.user == user || order.token && token == order.token)
72
74
  end
73
75
  can :manage, ::Spree::Address, user_id: user.id
74
- can :read, ::Spree::CreditCard, user_id: user.id
76
+ can [:read, :destroy], ::Spree::CreditCard, user_id: user.id
75
77
  can :read, ::Spree::Product
76
78
  can :read, ::Spree::ProductProperty
77
79
  can :read, ::Spree::Property
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Address < Spree::Base
3
- require 'twitter_cldr'
3
+ require 'validates_zipcode'
4
4
 
5
5
  if Rails::VERSION::STRING >= '6.1'
6
6
  serialize :preferences, Hash, default: {}
@@ -55,13 +55,21 @@ module Spree
55
55
  alias_attribute :first_name, :firstname
56
56
  alias_attribute :last_name, :lastname
57
57
 
58
- self.whitelisted_ransackable_attributes = %w[firstname lastname company]
58
+ self.whitelisted_ransackable_attributes = ADDRESS_FIELDS
59
+ self.whitelisted_ransackable_associations = %w[country state user]
59
60
 
60
61
  def self.build_default
62
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
63
+ `Address#build_default` is deprecated and will be removed in Spree 5.0.
64
+ Please use standard rails `Address.new(country: current_store.default_country)`
65
+ DEPRECATION
61
66
  new(country: Spree::Country.default)
62
67
  end
63
68
 
64
69
  def self.default(user = nil, kind = 'bill')
70
+ ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
71
+ `Address#default` is deprecated and will be removed in Spree 5.0.
72
+ DEPRECATION
65
73
  if user && user_address = user.public_send(:"#{kind}_address")
66
74
  user_address.clone
67
75
  else
@@ -157,6 +165,7 @@ module Spree
157
165
  super
158
166
  else
159
167
  update_column :deleted_at, Time.current
168
+ assign_new_default_address_to_user
160
169
  end
161
170
  end
162
171
 
@@ -214,11 +223,23 @@ module Spree
214
223
  end
215
224
 
216
225
  def postal_code_validate
217
- return if country.blank? || country.iso.blank? || !require_zipcode?
218
- return unless TwitterCldr::Shared::PostalCodes.territories.include?(country.iso.downcase.to_sym)
226
+ return if country.blank? || country_iso.blank? || !require_zipcode? || zipcode.blank?
227
+ return unless ::ValidatesZipcode::CldrRegexpCollection::ZIPCODES_REGEX.keys.include?(country_iso.upcase.to_sym)
219
228
 
220
- postal_code = TwitterCldr::Shared::PostalCodes.for_territory(country.iso)
221
- errors.add(:zipcode, :invalid) unless postal_code.valid?(zipcode.to_s.strip)
229
+ formatted_zip = ::ValidatesZipcode::Formatter.new(
230
+ zipcode: zipcode.to_s.strip,
231
+ country_alpha2: country_iso.upcase
232
+ ).format
233
+
234
+ errors.add(:zipcode, :invalid) unless ::ValidatesZipcode.valid?(formatted_zip, country_iso.upcase)
235
+ end
236
+
237
+ def assign_new_default_address_to_user
238
+ return unless user
239
+
240
+ user.bill_address = user.addresses.last if user.bill_address == self
241
+ user.ship_address = user.addresses.last if user.ship_address == self
242
+ user.save!
222
243
  end
223
244
  end
224
245
  end
@@ -45,6 +45,7 @@ module Spree
45
45
  preference :currency, :string, default: 'USD'
46
46
  preference :default_country_id, :integer
47
47
  preference :disable_sku_validation, :boolean, default: false # when turned off disables the built-in SKU uniqueness validation
48
+ preference :disable_store_presence_validation, :boolean, default: false # when turned off disables Store presence validation for Products and Payment Methods
48
49
  preference :expedited_exchanges, :boolean, default: false # NOTE this requires payment profiles to be supported on your gateway of choice as well as a delayed job handler to be configured with activejob. kicks off an exchange shipment upon return authorization save. charge customer if they do not return items within timely manner.
49
50
  preference :expedited_exchanges_days_window, :integer, default: 14 # the amount of days the customer has to return their item after the expedited exchange is shipped in order to avoid being charged
50
51
  preference :layout, :string, default: 'spree/layouts/spree_application'
@@ -52,6 +53,7 @@ module Spree
52
53
  preference :mailer_logo, :string, default: 'logo/spree_50.png'
53
54
  preference :max_level_in_taxons_menu, :integer, default: 1 # maximum nesting level in taxons menu
54
55
  preference :products_per_page, :integer, default: 12
56
+ preference :product_wysiwyg_editor_enabled, :boolean, default: true
55
57
  preference :require_master_price, :boolean, default: true
56
58
  preference :restock_inventory, :boolean, default: true # Determines if a return item is restocked automatically once it has been received
57
59
  preference :return_eligibility_number_of_days, :integer, default: 365
@@ -62,6 +64,7 @@ module Spree
62
64
  preference :show_products_without_price, :boolean, default: false
63
65
  preference :show_raw_product_description, :boolean, default: false
64
66
  preference :tax_using_ship_address, :boolean, default: true
67
+ preference :taxon_wysiwyg_editor_enabled, :boolean, default: true
65
68
  preference :track_inventory_levels, :boolean, default: true # Determines whether to track on_hand values for variants / products.
66
69
 
67
70
  # Store credits configurations
@@ -76,6 +79,11 @@ module Spree
76
79
  @searcher_class ||= Spree::Core::Search::Base
77
80
  end
78
81
 
82
+ # Sets the path used for products, taxons and pages.
83
+ preference :storefront_products_path, :string, default: 'products'
84
+ preference :storefront_taxons_path, :string, default: 't'
85
+ preference :storefront_pages_path, :string, default: 'pages'
86
+
79
87
  attr_writer :searcher_class
80
88
  end
81
89
  end
@@ -6,14 +6,14 @@ module Spree
6
6
  :ability_class,
7
7
  :cart_create_service, :cart_add_item_service, :cart_remove_item_service,
8
8
  :cart_remove_line_item_service, :cart_set_item_quantity_service, :cart_recalculate_service,
9
- :cart_update_service, :checkout_next_service, :checkout_advance_service, :checkout_update_service,
10
- :checkout_complete_service, :checkout_add_store_credit_service,
11
- :checkout_remove_store_credit_service, :checkout_get_shipping_rates_service,
12
- :coupon_handler, :country_finder, :current_order_finder, :credit_card_finder,
9
+ :cms_page_finder, :cart_update_service, :checkout_next_service, :checkout_advance_service, :checkout_update_service,
10
+ :checkout_complete_service, :checkout_add_store_credit_service, :checkout_remove_store_credit_service, :checkout_get_shipping_rates_service,
11
+ :coupon_handler, :menu_finder, :country_finder, :current_order_finder, :credit_card_finder,
13
12
  :completed_order_finder, :order_sorter, :cart_compare_line_items_service, :collection_paginator, :products_sorter,
14
13
  :products_finder, :taxon_finder, :line_item_by_variant_finder, :cart_estimate_shipping_rates_service,
15
- :account_create_address_service, :account_update_address_service, :address_finder,
16
- :collection_sorter, :error_handler
14
+ :account_create_address_service, :account_update_address_service, :account_create_service, :account_update_service,
15
+ :address_finder, :collection_sorter, :error_handler, :current_store_finder, :cart_empty_service, :cart_destroy_service,
16
+ :classification_reposition_service, :credit_cards_destroy_service, :cart_associate_service, :cart_change_currency_service
17
17
  ].freeze
18
18
 
19
19
  attr_accessor *INJECTION_POINTS
@@ -41,6 +41,10 @@ module Spree
41
41
  @cart_remove_line_item_service = 'Spree::Cart::RemoveLineItem'
42
42
  @cart_set_item_quantity_service = 'Spree::Cart::SetQuantity'
43
43
  @cart_estimate_shipping_rates_service = 'Spree::Cart::EstimateShippingRates'
44
+ @cart_empty_service = 'Spree::Cart::Empty'
45
+ @cart_destroy_service = 'Spree::Cart::Destroy'
46
+ @cart_associate_service = 'Spree::Cart::Associate'
47
+ @cart_change_currency_service = 'Spree::Cart::ChangeCurrency'
44
48
 
45
49
  # checkout
46
50
  @checkout_next_service = 'Spree::Checkout::Next'
@@ -64,16 +68,26 @@ module Spree
64
68
  @coupon_handler = 'Spree::PromotionHandler::Coupon'
65
69
 
66
70
  # account
71
+ @account_create_service = 'Spree::Account::Create'
72
+ @account_update_service = 'Spree::Account::Update'
67
73
  @account_create_address_service = 'Spree::Account::Addresses::Create'
68
74
  @account_update_address_service = 'Spree::Account::Addresses::Update'
69
75
 
76
+ # credit cards
77
+ @credit_cards_destroy_service = 'Spree::CreditCards::Destroy'
78
+
79
+ @classification_reposition_service = 'Spree::Classifications::Reposition'
80
+
70
81
  @error_handler = 'Spree::ErrorReporter'
71
82
  end
72
83
 
73
84
  def set_default_finders
74
85
  @address_finder = 'Spree::Addresses::Find'
75
86
  @country_finder = 'Spree::Countries::Find'
87
+ @cms_page_finder = 'Spree::CmsPages::Find'
88
+ @menu_finder = 'Spree::Menus::Find'
76
89
  @current_order_finder = 'Spree::Orders::FindCurrent'
90
+ @current_store_finder = 'Spree::Stores::FindCurrent'
77
91
  @completed_order_finder = 'Spree::Orders::FindComplete'
78
92
  @credit_card_finder = 'Spree::CreditCards::Find'
79
93
  @products_finder = 'Spree::Products::Find'
@@ -22,6 +22,16 @@ class Spree::Base < ApplicationRecord
22
22
  false
23
23
  end
24
24
 
25
+ def self.for_store(store)
26
+ plural_model_name = model_name.plural.gsub(/spree_/, '').to_sym
27
+
28
+ if store.respond_to?(plural_model_name)
29
+ store.send(plural_model_name)
30
+ else
31
+ self
32
+ end
33
+ end
34
+
25
35
  def self.spree_base_scopes
26
36
  where(nil)
27
37
  end
@@ -30,4 +40,12 @@ class Spree::Base < ApplicationRecord
30
40
  def self.has_many_inversing
31
41
  false
32
42
  end
43
+
44
+ def self.json_api_columns
45
+ column_names.reject { |c| c.match(/_id$|id|preferences|(.*)password|(.*)token|(.*)api_key/) }
46
+ end
47
+
48
+ def self.json_api_type
49
+ to_s.demodulize.underscore
50
+ end
33
51
  end
@@ -9,7 +9,10 @@ module Spree
9
9
  end
10
10
 
11
11
  validates :taxon, :product, presence: true
12
+ validates :position, numericality: { only_integer: true, allow_blank: true, allow_nil: true }
12
13
  # For #3494
13
14
  validates :taxon_id, uniqueness: { scope: :product_id, message: :already_linked, allow_blank: true }
15
+
16
+ self.whitelisted_ransackable_attributes = ['taxon_id', 'product_id']
14
17
  end
15
18
  end
@@ -0,0 +1,7 @@
1
+ module Spree::Cms::Pages
2
+ class FeaturePage < Spree::CmsPage
3
+ def sections?
4
+ true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ module Spree::Cms::Pages
2
+ class Homepage < Spree::CmsPage
3
+ before_create :empty_slug
4
+ after_save :empty_slug
5
+
6
+ def sections?
7
+ true
8
+ end
9
+
10
+ def seo_meta_description
11
+ meta_description if meta_description.present?
12
+ end
13
+
14
+ private
15
+
16
+ def empty_slug
17
+ self.slug = nil
18
+ end
19
+ end
20
+ end