spree_core 4.10.1 → 5.0.0.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.
- checksums.yaml +4 -4
- data/app/assets/config/spree_core_manifest.js +4 -0
- data/app/assets/images/google_on_white_hdpi.png +0 -0
- data/app/controllers/spree/base_controller.rb +1 -4
- data/app/finders/spree/orders/find_complete.rb +14 -2
- data/app/finders/spree/products/find.rb +74 -23
- data/app/finders/spree/stores/find_current.rb +6 -2
- data/app/helpers/spree/addresses_helper.rb +106 -0
- data/app/helpers/spree/base_helper.rb +83 -55
- data/app/helpers/spree/currency_helper.rb +12 -0
- data/app/helpers/spree/images_helper.rb +18 -0
- data/app/helpers/spree/mail_helper.rb +24 -0
- data/app/helpers/spree/products_helper.rb +1 -20
- data/app/javascript/spree/core/controllers/address_autocomplete_controller.js +233 -0
- data/app/javascript/spree/core/controllers/address_form_controller.js +98 -0
- data/app/javascript/spree/core/controllers/enable_button_controller.js +29 -0
- data/app/javascript/spree/core/helpers/address_autocomplete/google_places_suggestions_provider.js +179 -0
- data/app/javascript/spree/core/helpers/debounce.js +9 -0
- data/app/javascript/spree/core/helpers/scroll_lock.js +25 -0
- data/app/jobs/spree/addresses/geocode_address_job.rb +31 -0
- data/app/jobs/spree/base_job.rb +1 -0
- data/app/jobs/spree/coupon_codes/bulk_generate_job.rb +17 -0
- data/app/jobs/spree/exports/generate_job.rb +12 -0
- data/app/jobs/spree/products/auto_match_taxons_job.rb +14 -0
- data/app/jobs/spree/products/touch_taxons_job.rb +12 -0
- data/app/jobs/spree/reports/generate_job.rb +12 -0
- data/app/jobs/spree/stock_locations/stock_items/create_job.rb +1 -1
- data/app/jobs/spree/themes/duplicate_components_job.rb +59 -0
- data/app/jobs/spree/themes/screenshot_job.rb +81 -0
- data/app/jobs/spree/variants/remove_from_incomplete_orders_job.rb +2 -0
- data/app/jobs/spree/variants/remove_line_item_job.rb +2 -0
- data/app/mailers/spree/base_mailer.rb +51 -0
- data/app/mailers/spree/export_mailer.rb +19 -0
- data/app/mailers/spree/report_mailer.rb +20 -0
- data/app/mailers/spree/test_mailer.rb +8 -0
- data/app/models/action_text/rich_text_decorator.rb +11 -0
- data/app/models/action_text/video_embed.rb +13 -0
- data/app/models/acts_as_taggable_on/tag_decorator.rb +10 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +2 -0
- data/app/models/concerns/spree/display_on.rb +13 -0
- data/app/models/concerns/spree/has_one_link.rb +42 -0
- data/app/models/concerns/spree/has_page_links.rb +53 -0
- data/app/models/concerns/spree/metadata.rb +3 -7
- data/app/models/concerns/spree/multi_searchable.rb +21 -0
- data/app/models/concerns/spree/multi_store_resource.rb +9 -0
- data/app/models/concerns/spree/number_as_param.rb +4 -2
- data/app/models/concerns/spree/parameterizable_name.rb +21 -0
- data/app/models/concerns/spree/previewable.rb +17 -0
- data/app/models/concerns/spree/product_scopes.rb +7 -7
- data/app/models/concerns/spree/stores/setup.rb +52 -0
- data/app/models/concerns/spree/stores/socials.rb +68 -0
- data/app/models/concerns/spree/user_address.rb +4 -0
- data/app/models/concerns/spree/user_methods.rb +61 -11
- data/app/models/concerns/spree/user_reporting.rb +14 -6
- data/app/models/concerns/spree/user_roles.rb +1 -1
- data/app/models/spree/ability.rb +4 -2
- data/app/models/spree/address.rb +122 -28
- data/app/models/spree/adjustment.rb +4 -1
- data/app/models/spree/asset/support/active_storage.rb +1 -1
- data/app/models/spree/asset.rb +18 -6
- data/app/models/spree/base.rb +38 -7
- data/app/models/spree/base_analytics_event_handler.rb +49 -0
- data/app/models/spree/calculator.rb +1 -1
- data/app/models/spree/classification.rb +10 -1
- data/app/models/spree/country.rb +1 -1
- data/app/models/spree/coupon_code.rb +38 -0
- data/app/models/spree/credit_card.rb +4 -3
- data/app/models/spree/current.rb +9 -0
- data/app/models/spree/custom_domain.rb +53 -0
- data/app/models/spree/customer_return.rb +13 -1
- data/app/models/spree/data_feed.rb +1 -1
- data/app/models/spree/digital.rb +5 -6
- data/app/models/spree/digital_link.rb +11 -6
- data/app/models/spree/export.rb +172 -0
- data/app/models/spree/exports/orders.rb +23 -0
- data/app/models/spree/exports/products.rb +35 -0
- data/app/models/spree/gateway/bogus.rb +5 -0
- data/app/models/spree/gateway.rb +14 -4
- data/app/models/spree/gateway_customer.rb +13 -0
- data/app/models/spree/image/configuration/active_storage.rb +1 -1
- data/app/models/spree/inventory_unit.rb +1 -1
- data/app/models/spree/legacy_user.rb +3 -1
- data/app/models/spree/line_item.rb +37 -2
- data/app/models/spree/log_entry.rb +1 -1
- data/app/models/spree/option_type.rb +40 -6
- data/app/models/spree/option_type_prototype.rb +1 -1
- data/app/models/spree/option_value.rb +35 -5
- data/app/models/spree/option_value_variant.rb +2 -2
- data/app/models/spree/order/address_book.rb +34 -15
- data/app/models/spree/order/checkout.rb +12 -2
- data/app/models/spree/order/currency_updater.rb +1 -1
- data/app/models/spree/order/digital.rb +14 -3
- data/app/models/spree/order/emails.rb +1 -1
- data/app/models/spree/order/payments.rb +1 -13
- data/app/models/spree/order/store_credit.rb +17 -5
- data/app/models/spree/order/webhooks.rb +1 -1
- data/app/models/spree/order.rb +179 -49
- data/app/models/spree/order_promotion.rb +1 -1
- data/app/models/spree/order_updater.rb +9 -3
- data/app/models/spree/page.rb +184 -0
- data/app/models/spree/page_block.rb +69 -0
- data/app/models/spree/page_blocks/buttons.rb +29 -0
- data/app/models/spree/page_blocks/heading.rb +18 -0
- data/app/models/spree/page_blocks/image.rb +17 -0
- data/app/models/spree/page_blocks/link.rb +21 -0
- data/app/models/spree/page_blocks/mega_nav.rb +33 -0
- data/app/models/spree/page_blocks/mega_nav_with_subcategories.rb +32 -0
- data/app/models/spree/page_blocks/nav.rb +15 -0
- data/app/models/spree/page_blocks/newsletter_form.rb +18 -0
- data/app/models/spree/page_blocks/products/buy_buttons.rb +12 -0
- data/app/models/spree/page_blocks/products/price.rb +18 -0
- data/app/models/spree/page_blocks/products/quantity_selector.rb +12 -0
- data/app/models/spree/page_blocks/products/share.rb +8 -0
- data/app/models/spree/page_blocks/products/title.rb +15 -0
- data/app/models/spree/page_blocks/products/variant_picker.rb +9 -0
- data/app/models/spree/page_blocks/subheading.rb +17 -0
- data/app/models/spree/page_blocks/text.rb +16 -0
- data/app/models/spree/page_link.rb +59 -0
- data/app/models/spree/page_section.rb +215 -0
- data/app/models/spree/page_sections/announcement_bar.rb +30 -0
- data/app/models/spree/page_sections/collection_banner.rb +18 -0
- data/app/models/spree/page_sections/custom_code.rb +11 -0
- data/app/models/spree/page_sections/featured_posts.rb +43 -0
- data/app/models/spree/page_sections/featured_product.rb +46 -0
- data/app/models/spree/page_sections/featured_taxon.rb +88 -0
- data/app/models/spree/page_sections/featured_taxons.rb +45 -0
- data/app/models/spree/page_sections/footer.rb +94 -0
- data/app/models/spree/page_sections/header.rb +62 -0
- data/app/models/spree/page_sections/image_banner.rb +38 -0
- data/app/models/spree/page_sections/image_with_text.rb +48 -0
- data/app/models/spree/page_sections/main_password_footer.rb +18 -0
- data/app/models/spree/page_sections/main_password_header.rb +20 -0
- data/app/models/spree/page_sections/newsletter.rb +47 -0
- data/app/models/spree/page_sections/page_title.rb +19 -0
- data/app/models/spree/page_sections/post_details.rb +19 -0
- data/app/models/spree/page_sections/post_grid.rb +19 -0
- data/app/models/spree/page_sections/product_details.rb +16 -0
- data/app/models/spree/page_sections/product_grid.rb +13 -0
- data/app/models/spree/page_sections/related_products.rb +60 -0
- data/app/models/spree/page_sections/rich_text.rb +20 -0
- data/app/models/spree/page_sections/taxon_banner.rb +18 -0
- data/app/models/spree/page_sections/taxon_grid.rb +17 -0
- data/app/models/spree/page_sections/video.rb +99 -0
- data/app/models/spree/pages/account.rb +15 -0
- data/app/models/spree/pages/cart.rb +9 -0
- data/app/models/spree/pages/checkout.rb +9 -0
- data/app/models/spree/pages/custom.rb +34 -0
- data/app/models/spree/pages/homepage.rb +68 -0
- data/app/models/spree/pages/login.rb +15 -0
- data/app/models/spree/pages/password.rb +57 -0
- data/app/models/spree/pages/post.rb +27 -0
- data/app/models/spree/pages/post_list.rb +32 -0
- data/app/models/spree/pages/product_details.rb +29 -0
- data/app/models/spree/pages/search_results.rb +43 -0
- data/app/models/spree/pages/shop_all.rb +36 -0
- data/app/models/spree/pages/taxon.rb +29 -0
- data/app/models/spree/pages/taxon_list.rb +41 -0
- data/app/models/spree/pages/wishlist.rb +11 -0
- data/app/models/spree/payment/gateway_options.rb +13 -15
- data/app/models/spree/payment/processing.rb +1 -1
- data/app/models/spree/payment/webhooks.rb +1 -1
- data/app/models/spree/payment.rb +61 -12
- data/app/models/spree/payment_capture_event.rb +1 -1
- data/app/models/spree/payment_method/store_credit.rb +9 -1
- data/app/models/spree/payment_method.rb +26 -8
- data/app/models/spree/payment_source.rb +2 -2
- data/app/models/spree/post.rb +108 -0
- data/app/models/spree/post_category.rb +33 -0
- data/app/models/spree/preference.rb +1 -1
- data/app/models/spree/price.rb +10 -3
- data/app/models/spree/product/webhooks.rb +1 -1
- data/app/models/spree/product.rb +325 -54
- data/app/models/spree/product_option_type.rb +1 -1
- data/app/models/spree/product_promotion_rule.rb +1 -1
- data/app/models/spree/product_property.rb +4 -1
- data/app/models/spree/promotion/actions/create_line_items.rb +37 -2
- data/app/models/spree/promotion/rules/country.rb +22 -4
- data/app/models/spree/promotion/rules/currency.rb +21 -0
- data/app/models/spree/promotion/rules/item_total.rb +12 -3
- data/app/models/spree/promotion/rules/option_value.rb +5 -20
- data/app/models/spree/promotion/rules/product.rb +33 -1
- data/app/models/spree/promotion/rules/taxon.rb +31 -0
- data/app/models/spree/promotion/rules/user.rb +33 -4
- data/app/models/spree/promotion.rb +136 -15
- data/app/models/spree/promotion_action.rb +31 -1
- data/app/models/spree/promotion_action_line_item.rb +1 -1
- data/app/models/spree/promotion_category.rb +1 -1
- data/app/models/spree/promotion_handler/cart.rb +1 -1
- data/app/models/spree/promotion_handler/coupon.rb +46 -8
- data/app/models/spree/promotion_handler/free_shipping.rb +1 -1
- data/app/models/spree/promotion_handler/promotion_duplicator.rb +6 -5
- data/app/models/spree/promotion_rule.rb +23 -1
- data/app/models/spree/promotion_rule_taxon.rb +1 -1
- data/app/models/spree/promotion_rule_user.rb +1 -1
- data/app/models/spree/property.rb +11 -3
- data/app/models/spree/property_prototype.rb +1 -1
- data/app/models/spree/prototype.rb +1 -1
- data/app/models/spree/prototype_taxon.rb +1 -1
- data/app/models/spree/refund.rb +24 -4
- data/app/models/spree/refund_reason.rb +12 -2
- data/app/models/spree/reimbursement/credit.rb +1 -1
- data/app/models/spree/reimbursement/emails.rb +1 -1
- data/app/models/spree/reimbursement.rb +5 -3
- data/app/models/spree/reimbursement_type.rb +1 -1
- data/app/models/spree/report.rb +110 -0
- data/app/models/spree/report_line_item.rb +27 -0
- data/app/models/spree/report_line_items/products_performance.rb +76 -0
- data/app/models/spree/report_line_items/sales_total.rb +49 -0
- data/app/models/spree/reports/products_performance.rb +44 -0
- data/app/models/spree/reports/sales_total.rb +14 -0
- data/app/models/spree/return_authorization.rb +4 -1
- data/app/models/spree/return_authorization_reason.rb +1 -1
- data/app/models/spree/return_item.rb +2 -1
- data/app/models/spree/role.rb +5 -2
- data/app/models/spree/role_user.rb +2 -2
- data/app/models/spree/shipment/emails.rb +1 -1
- data/app/models/spree/shipment/webhooks.rb +1 -1
- data/app/models/spree/shipment.rb +14 -4
- data/app/models/spree/shipping_category.rb +1 -1
- data/app/models/spree/shipping_method.rb +48 -8
- data/app/models/spree/shipping_method_category.rb +1 -1
- data/app/models/spree/shipping_method_zone.rb +1 -1
- data/app/models/spree/shipping_rate.rb +21 -3
- data/app/models/spree/state.rb +1 -1
- data/app/models/spree/state_change.rb +1 -1
- data/app/models/spree/stock_item/webhooks.rb +1 -1
- data/app/models/spree/stock_item.rb +9 -6
- data/app/models/spree/stock_location.rb +35 -8
- data/app/models/spree/stock_movement/webhooks.rb +1 -1
- data/app/models/spree/stock_movement.rb +9 -3
- data/app/models/spree/stock_transfer.rb +41 -3
- data/app/models/spree/store.rb +345 -72
- data/app/models/spree/store_credit.rb +12 -4
- data/app/models/spree/store_credit_category.rb +1 -1
- data/app/models/spree/store_credit_event.rb +21 -1
- data/app/models/spree/store_credit_type.rb +1 -1
- data/app/models/spree/store_payment_method.rb +1 -1
- data/app/models/spree/store_product.rb +1 -1
- data/app/models/spree/store_promotion.rb +1 -1
- data/app/models/spree/tax_category.rb +15 -1
- data/app/models/spree/tax_rate.rb +1 -1
- data/app/models/spree/taxon.rb +210 -27
- data/app/models/spree/taxon_image/configuration/active_storage.rb +1 -1
- data/app/models/spree/taxon_rule.rb +25 -0
- data/app/models/spree/taxon_rules/available_on.rb +20 -0
- data/app/models/spree/taxon_rules/sale.rb +16 -0
- data/app/models/spree/taxon_rules/tag.rb +19 -0
- data/app/models/spree/taxonomy.rb +3 -2
- data/app/models/spree/theme.rb +200 -0
- data/app/models/spree/themes/default.rb +94 -0
- data/app/models/spree/variant/webhooks.rb +1 -1
- data/app/models/spree/variant.rb +211 -62
- data/app/models/spree/wished_item.rb +1 -1
- data/app/models/spree/wishlist.rb +1 -1
- data/app/models/spree/zone.rb +1 -1
- data/app/models/spree/zone_member.rb +1 -1
- data/app/presenters/spree/csv/order_line_item_presenter.rb +145 -0
- data/app/presenters/spree/csv/product_presenter.rb +63 -0
- data/app/presenters/spree/csv/product_variant_presenter.rb +130 -0
- data/app/services/spree/addresses/create.rb +31 -6
- data/app/services/spree/addresses/helper.rb +7 -4
- data/app/services/spree/addresses/update.rb +79 -12
- data/app/services/spree/cart/remove_out_of_stock_items.rb +56 -0
- data/app/services/spree/checkout/add_store_credit.rb +6 -1
- data/app/services/spree/checkout/advance.rb +44 -4
- data/app/services/spree/checkout/select_shipping_method.rb +2 -0
- data/app/services/spree/coupon_codes/bulk_generate.rb +37 -0
- data/app/services/spree/coupon_codes/coupon_codes_handler.rb +34 -0
- data/app/services/spree/orders/create_user_account.rb +70 -0
- data/app/services/spree/orders/update_contact_information.rb +19 -0
- data/app/services/spree/products/auto_match_taxons.rb +64 -0
- data/app/services/spree/products/duplicator.rb +121 -0
- data/app/services/spree/products/prepare_nested_attributes.rb +169 -0
- data/app/services/spree/seeds/admin_user.rb +22 -0
- data/app/services/spree/seeds/all.rb +1 -0
- data/app/services/spree/seeds/stores.rb +5 -10
- data/app/services/spree/seeds/zones.rb +2 -0
- data/app/services/spree/tags/bulk_add.rb +38 -0
- data/app/services/spree/tags/bulk_remove.rb +24 -0
- data/app/services/spree/taxons/add_products.rb +39 -0
- data/app/services/spree/taxons/regenerate_products.rb +53 -0
- data/app/services/spree/taxons/remove_products.rb +53 -0
- data/app/services/spree/taxons/touch_featured_sections.rb +21 -0
- data/app/services/spree/themes/duplicator.rb +40 -0
- data/app/services/spree/variants/remove_line_items.rb +1 -1
- data/app/sorters/spree/classifications/sort.rb +68 -0
- data/app/sorters/spree/products/sort.rb +2 -3
- data/app/views/action_text/video_embeds/_thumbnail.html.erb +1 -0
- data/app/views/action_text/video_embeds/_video_embed.html.erb +3 -0
- data/app/views/active_storage/blobs/_blob.html.erb +20 -0
- data/app/views/layouts/action_text/contents/_content.html.erb +3 -0
- data/app/views/layouts/spree/base_mailer.html.erb +46 -0
- data/app/views/spree/addresses/_form.html.erb +58 -0
- data/app/views/spree/addresses/_suggestions_box.erb +14 -0
- data/app/views/spree/export_mailer/export_done.html.erb +15 -0
- data/app/views/spree/report_mailer/report_done.html.erb +15 -0
- data/app/views/spree/shared/_base_mailer_footer.html.erb +12 -0
- data/app/views/spree/shared/_base_mailer_header.html.erb +6 -0
- data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +456 -0
- data/app/views/spree/shared/_google_places_api_loader.html.erb +7 -0
- data/app/views/spree/shared/_mailer_line_item.html.erb +12 -0
- data/app/views/spree/shared/_mailer_logo.html.erb +41 -0
- data/app/views/spree/shared/_payment.html.erb +41 -0
- data/app/views/spree/test_mailer/test_email.html.erb +40 -0
- data/app/views/spree/test_mailer/test_email.text.erb +4 -0
- data/config/i18n-tasks.yml +178 -0
- data/config/importmap.rb +14 -0
- data/config/initializers/acts_as_taggable_on.rb +2 -0
- data/config/initializers/inflections.rb +2 -0
- data/config/initializers/mobility.rb +4 -0
- data/config/initializers/oembed.rb +1 -0
- data/config/locales/en.yml +823 -413
- data/config/routes.rb +6 -5
- data/db/migrate/20210914000000_spree_four_three.rb +0 -79
- data/db/migrate/20240913143518_change_default_value_of_spree_option_types_filterable.rb +5 -0
- data/db/migrate/20240914153106_add_display_on_to_spree_properties.rb +5 -0
- data/db/migrate/20240915144935_add_position_to_spree_properties.rb +6 -0
- data/db/migrate/20241004181911_create_spree_coupon_codes.rb +15 -0
- data/db/migrate/20241005093437_add_multi_code_to_spree_promotions.rb +14 -0
- data/db/migrate/20241014140140_translate_rich_texts.rb +17 -0
- data/db/migrate/20241030134309_create_spree_exports.rb +23 -0
- data/db/migrate/20241104083457_migrate_spree_promotion_rules_option_value_eligible_values.rb +16 -0
- data/db/migrate/20241123110646_add_estimated_transit_fields_to_spree_shipping_methods.rb +6 -0
- data/db/migrate/20241127193411_create_spree_taxon_rules.rb +13 -0
- data/db/migrate/20241127223627_add_rules_match_policy_and_sort_order_to_spree_taxons.rb +6 -0
- data/db/migrate/20241128103947_add_automatic_to_spree_taxons.rb +5 -0
- data/db/migrate/20241218183905_add_gateway_customer_profile_id_to_spree_payment_sources.rb +5 -0
- data/db/migrate/20250107220432_add_accept_marketing_and_signup_for_an_account_to_spree_orders.rb +6 -0
- data/db/migrate/20250110171203_add_quick_checkout_to_spree_addresses.rb +6 -0
- data/db/migrate/20250113180019_add_preferences_to_spree_stores.rb +5 -0
- data/db/migrate/20250114193857_add_metadata_to_spree_stores.rb +13 -0
- data/db/migrate/20250119165904_create_spree_custom_domains.rb +22 -0
- data/db/migrate/20250120094216_create_page_builder_models.rb +78 -0
- data/db/migrate/20250120152208_add_default_locale_to_action_text_rich_texts.rb +7 -0
- data/db/migrate/20250121160028_create_spree_posts_and_spree_post_categories.rb +33 -0
- data/db/migrate/20250122113708_add_first_and_last_name_to_spree_admin_class.rb +9 -0
- data/db/migrate/20250123135358_add_custom_code_fields_to_spree_store.rb +7 -0
- data/db/migrate/20250127083740_add_kind_to_spree_properties.rb +5 -0
- data/db/migrate/20250127112758_add_latitude_and_longitude_to_spree_addresses.rb +6 -0
- data/db/migrate/20250127151258_add_phone_to_spree_users.rb +5 -0
- data/db/migrate/20250204162453_create_spree_reports.rb +13 -0
- data/db/migrate/20250207084000_add_accepts_email_marketing_field_to_spree_users_table.rb +6 -0
- data/db/migrate/20250217171018_create_action_text_video_embeds.rb +11 -0
- data/db/migrate/20250304115943_add_performed_by_to_spree_reimbursements.rb +5 -0
- data/db/migrate/20250305121352_remove_page_builder_indices.rb +11 -0
- data/db/migrate/20250305121657_remove_spree_posts_indices.rb +7 -0
- data/db/migrate/20250311105934_create_spree_gateway_customers.rb +18 -0
- data/db/migrate/20250312202705_add_unique_index_on_promotion_rules_associations.rb +75 -0
- data/db/migrate/20250313104226_add_user_type_to_spree_role_users.rb +18 -0
- data/db/migrate/20250313175830_add_unique_index_on_promotion_action_line_items.rb +29 -0
- data/db/migrate/20250314144210_create_spree_taggings_and_spree_tags.rb +38 -0
- data/lib/generators/spree/authentication/custom/custom_generator.rb +49 -0
- data/lib/generators/spree/authentication/custom/templates/authentication_helpers.rb.tt +50 -0
- data/lib/generators/spree/authentication/devise/devise_generator.rb +57 -0
- data/lib/generators/spree/authentication/devise/templates/authentication_helpers.rb.tt +50 -0
- data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
- data/lib/generators/spree/dummy/templates/rails/database.yml +1 -0
- data/lib/generators/spree/dummy/templates/rails/test.rb +1 -1
- data/lib/generators/spree/install/install_generator.rb +21 -36
- data/lib/generators/spree/install/templates/config/initializers/spree.rb +40 -6
- data/lib/normalize_string.rb +18 -0
- data/lib/spree/analytics.rb +11 -0
- data/lib/spree/core/components.rb +1 -1
- data/lib/spree/core/configuration.rb +14 -11
- data/lib/spree/core/controller_helpers/auth.rb +0 -26
- data/lib/spree/core/controller_helpers/order.rb +77 -12
- data/lib/spree/core/controller_helpers/search.rb +2 -0
- data/lib/spree/core/controller_helpers/store.rb +0 -5
- data/lib/spree/core/controller_helpers/strong_parameters.rb +4 -0
- data/lib/spree/core/controller_helpers/turbo.rb +19 -0
- data/lib/spree/core/dependencies.rb +3 -5
- data/lib/spree/core/engine.rb +158 -7
- data/lib/spree/core/preferences/configuration.rb +2 -44
- data/lib/spree/core/preferences/preferable.rb +9 -0
- data/lib/spree/core/preferences/preferable_class_methods.rb +11 -1
- data/lib/spree/core/preferences/runtime_configuration.rb +13 -2
- data/lib/spree/core/search/base.rb +2 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +61 -11
- data/lib/spree/i18n.rb +5 -8
- data/lib/spree/migrations.rb +1 -1
- data/lib/spree/permitted_attributes.rb +24 -15
- data/lib/spree/testing_support/authorization_helpers.rb +9 -6
- data/lib/spree/testing_support/capybara_config.rb +11 -0
- data/lib/spree/testing_support/common_rake.rb +20 -12
- data/lib/spree/testing_support/factories/calculator_factory.rb +16 -0
- data/lib/spree/testing_support/factories/country_factory.rb +8 -0
- data/lib/spree/testing_support/factories/coupon_code_factory.rb +7 -0
- data/lib/spree/testing_support/factories/custom_domain_factory.rb +7 -0
- data/lib/spree/testing_support/factories/export_factory.rb +32 -0
- data/lib/spree/testing_support/factories/gateway_customer_factory.rb +7 -0
- data/lib/spree/testing_support/factories/order_factory.rb +14 -3
- data/lib/spree/testing_support/factories/page_block_factory.rb +21 -0
- data/lib/spree/testing_support/factories/page_factory.rb +33 -0
- data/lib/spree/testing_support/factories/page_link_factory.rb +7 -0
- data/lib/spree/testing_support/factories/page_section_factory.rb +24 -0
- data/lib/spree/testing_support/factories/payment_factory.rb +2 -2
- data/lib/spree/testing_support/factories/post_category_factory.rb +7 -0
- data/lib/spree/testing_support/factories/post_factory.rb +10 -0
- data/lib/spree/testing_support/factories/product_factory.rb +3 -8
- data/lib/spree/testing_support/factories/product_property_factory.rb +1 -1
- data/lib/spree/testing_support/factories/promotion_action_factory.rb +5 -0
- data/lib/spree/testing_support/factories/promotion_factory.rb +7 -9
- data/lib/spree/testing_support/factories/promotion_rule_factory.rb +12 -0
- data/lib/spree/testing_support/factories/property_factory.rb +1 -1
- data/lib/spree/testing_support/factories/report_factory.rb +33 -0
- data/lib/spree/testing_support/factories/role_user_factory.rb +7 -0
- data/lib/spree/testing_support/factories/shipping_method_factory.rb +9 -0
- data/lib/spree/testing_support/factories/stock_transfer_factory.rb +5 -2
- data/lib/spree/testing_support/factories/store_factory.rb +6 -9
- data/lib/spree/testing_support/factories/taxon_factory.rb +13 -0
- data/lib/spree/testing_support/factories/taxon_rule_factory.rb +38 -0
- data/lib/spree/testing_support/factories/theme_factory.rb +14 -0
- data/lib/spree/testing_support/factories/user_factory.rb +13 -11
- data/lib/spree/testing_support/factories/variant_factory.rb +23 -5
- data/lib/spree/testing_support/jobs.rb +1 -7
- data/lib/spree/testing_support/metadata.rb +13 -1
- data/lib/spree/testing_support/order_walkthrough.rb +1 -7
- data/lib/spree/testing_support/preferences.rb +1 -4
- data/lib/spree/testing_support/store.rb +26 -0
- data/lib/spree_core.rb +1 -0
- data/vendor/javascript/@rails--request.js.js +4 -0
- data/vendor/javascript/@stimulus-components--auto-submit.js +4 -0
- data/vendor/javascript/stimulus-reveal-controller.js +4 -0
- data/vendor/javascript/tailwindcss-stimulus-components.js +4 -0
- metadata +340 -197
- data/Gemfile +0 -3
- data/app/finders/spree/cms_pages/find.rb +0 -41
- data/app/finders/spree/menus/find.rb +0 -11
- data/app/models/concerns/spree/display_link.rb +0 -30
- data/app/models/spree/cms/pages/feature_page.rb +0 -7
- data/app/models/spree/cms/pages/homepage.rb +0 -20
- data/app/models/spree/cms/pages/standard_page.rb +0 -4
- data/app/models/spree/cms/sections/featured_article.rb +0 -22
- data/app/models/spree/cms/sections/hero_image.rb +0 -38
- data/app/models/spree/cms/sections/image_gallery.rb +0 -97
- data/app/models/spree/cms/sections/product_carousel.rb +0 -14
- data/app/models/spree/cms/sections/rich_text_content.rb +0 -13
- data/app/models/spree/cms/sections/side_by_side_images.rb +0 -68
- data/app/models/spree/cms_page.rb +0 -70
- data/app/models/spree/cms_section.rb +0 -69
- data/app/models/spree/cms_section_image.rb +0 -9
- data/app/models/spree/cms_section_image_one.rb +0 -4
- data/app/models/spree/cms_section_image_three.rb +0 -4
- data/app/models/spree/cms_section_image_two.rb +0 -4
- data/app/models/spree/icon.rb +0 -7
- data/app/models/spree/linkable/homepage.rb +0 -3
- data/app/models/spree/linkable/uri.rb +0 -3
- data/app/models/spree/menu.rb +0 -66
- data/app/models/spree/menu_item.rb +0 -72
- data/brakeman.ignore +0 -328
- data/db/migrate/20211201202851_update_linkable_resource_types.rb +0 -10
- data/db/migrate/20220329113557_fix_cms_pages_unique_indexes.rb +0 -8
- data/lib/generators/spree/custom_authentication/custom_authentication_generator.rb +0 -23
- data/lib/generators/spree/custom_authentication/templates/authentication_helpers.rb.tt +0 -23
- data/lib/generators/spree/custom_user/custom_user_generator.rb +0 -46
- data/lib/generators/spree/custom_user/templates/current_user_helpers.rb.tt +0 -15
- data/lib/generators/spree/custom_user/templates/initializer.rb.tt +0 -1
- data/lib/generators/spree/custom_user/templates/migration.rb.tt +0 -7
- data/lib/generators/spree/dummy/templates/package.json +0 -12
- data/lib/spree/core/product_duplicator.rb +0 -85
- data/lib/spree/core/runtime_configuration.rb +0 -10
- data/lib/spree/testing_support/factories/cms_page_factory.rb +0 -20
- data/lib/spree/testing_support/factories/cms_section_factory.rb +0 -31
- data/lib/spree/testing_support/factories/icon_factory.rb +0 -9
- data/lib/spree/testing_support/factories/menu_factory.rb +0 -16
- data/lib/spree/testing_support/factories/menu_item_factory.rb +0 -10
- data/script/rails +0 -9
- data/spec/fixtures/favicon.ico +0 -0
- data/spec/fixtures/files/icon_256x256.gif +0 -0
- data/spec/fixtures/files/icon_256x256.png +0 -0
- data/spec/fixtures/files/icon_512x512.png +0 -0
- data/spec/fixtures/files/img_256x128.png +0 -0
- data/spec/fixtures/text-file.txt +0 -1
- data/spec/fixtures/thinking-cat.jpg +0 -0
- data/spree_core.gemspec +0 -62
data/app/models/spree/order.rb
CHANGED
@@ -6,9 +6,10 @@ require_dependency 'spree/order/store_credit'
|
|
6
6
|
require_dependency 'spree/order/emails'
|
7
7
|
|
8
8
|
module Spree
|
9
|
-
class Order < Spree
|
9
|
+
class Order < Spree.base_class
|
10
10
|
PAYMENT_STATES = %w(balance_due credit_owed failed paid void)
|
11
11
|
SHIPMENT_STATES = %w(backorder canceled partial pending ready shipped)
|
12
|
+
LINE_ITEM_REMOVABLE_STATES = %w(cart address delivery payment confirm resumed)
|
12
13
|
|
13
14
|
include Spree::Order::Checkout
|
14
15
|
include Spree::Order::CurrencyUpdater
|
@@ -19,13 +20,13 @@ module Spree
|
|
19
20
|
include Spree::Order::Emails
|
20
21
|
include Spree::Order::Webhooks
|
21
22
|
include Spree::Core::NumberGenerator.new(prefix: 'R')
|
22
|
-
include Spree::Core::TokenGenerator
|
23
23
|
|
24
24
|
include Spree::NumberIdentifier
|
25
25
|
include Spree::NumberAsParam
|
26
26
|
include Spree::SingleStoreResource
|
27
27
|
include Spree::MemoizedData
|
28
28
|
include Spree::Metadata
|
29
|
+
include Spree::MultiSearchable
|
29
30
|
if defined?(Spree::Security::Orders)
|
30
31
|
include Spree::Security::Orders
|
31
32
|
end
|
@@ -33,13 +34,16 @@ module Spree
|
|
33
34
|
include Spree::VendorConcern
|
34
35
|
end
|
35
36
|
|
37
|
+
has_secure_token :token, length: 35
|
38
|
+
|
36
39
|
MEMOIZED_METHODS = %w(tax_zone)
|
37
40
|
|
38
41
|
extend Spree::DisplayMoney
|
39
42
|
money_methods :outstanding_balance, :item_total, :adjustment_total,
|
40
43
|
:included_tax_total, :additional_tax_total, :tax_total,
|
41
44
|
:shipment_total, :promo_total, :total,
|
42
|
-
:cart_promo_total, :pre_tax_item_amount, :pre_tax_total
|
45
|
+
:cart_promo_total, :pre_tax_item_amount, :pre_tax_total,
|
46
|
+
:payment_total
|
43
47
|
|
44
48
|
alias display_ship_total display_shipment_total
|
45
49
|
alias_attribute :ship_total, :shipment_total
|
@@ -75,28 +79,22 @@ module Spree
|
|
75
79
|
self.whitelisted_ransackable_associations = %w[shipments user created_by approver canceler promotions bill_address ship_address line_items store]
|
76
80
|
self.whitelisted_ransackable_attributes = %w[
|
77
81
|
completed_at email number state payment_state shipment_state
|
78
|
-
total item_total considered_risky channel
|
82
|
+
total item_total item_count considered_risky channel
|
79
83
|
]
|
84
|
+
self.whitelisted_ransackable_scopes = %w[refunded partially_refunded multi_search]
|
80
85
|
|
81
86
|
attr_reader :coupon_code
|
82
87
|
attr_accessor :temporary_address, :temporary_credit_card
|
83
88
|
|
84
89
|
attribute :state_machine_resumed, :boolean
|
85
90
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
belongs_to :approver, class_name: "::#{Spree.admin_user_class}", optional: true
|
94
|
-
belongs_to :canceler, class_name: "::#{Spree.admin_user_class}", optional: true
|
95
|
-
else
|
96
|
-
belongs_to :created_by, optional: true
|
97
|
-
belongs_to :approver, optional: true
|
98
|
-
belongs_to :canceler, optional: true
|
99
|
-
end
|
91
|
+
acts_as_taggable_on :tags
|
92
|
+
acts_as_taggable_tenant :store_id
|
93
|
+
|
94
|
+
belongs_to :user, class_name: "::#{Spree.user_class}", optional: true, autosave: true
|
95
|
+
belongs_to :created_by, class_name: "::#{Spree.admin_user_class}", optional: true
|
96
|
+
belongs_to :approver, class_name: "::#{Spree.admin_user_class}", optional: true
|
97
|
+
belongs_to :canceler, class_name: "::#{Spree.admin_user_class}", optional: true
|
100
98
|
|
101
99
|
belongs_to :bill_address, foreign_key: :bill_address_id, class_name: 'Spree::Address',
|
102
100
|
optional: true, dependent: :destroy
|
@@ -118,6 +116,7 @@ module Spree
|
|
118
116
|
has_many :adjustments, -> { order(:created_at) }, as: :adjustable, class_name: 'Spree::Adjustment'
|
119
117
|
end
|
120
118
|
has_many :reimbursements, inverse_of: :order, class_name: 'Spree::Reimbursement'
|
119
|
+
has_many :customer_returns, class_name: 'Spree::CustomerReturn', through: :return_authorizations
|
121
120
|
has_many :line_item_adjustments, through: :line_items, source: :adjustments
|
122
121
|
has_many :inventory_units, inverse_of: :order, class_name: 'Spree::InventoryUnit'
|
123
122
|
has_many :return_items, through: :inventory_units, class_name: 'Spree::ReturnItem'
|
@@ -151,9 +150,9 @@ module Spree
|
|
151
150
|
before_validation :ensure_currency_presence
|
152
151
|
|
153
152
|
before_validation :clone_billing_address, if: :use_billing?
|
154
|
-
|
153
|
+
before_validation :clone_shipping_address, if: :use_shipping?
|
154
|
+
attr_accessor :use_billing, :use_shipping
|
155
155
|
|
156
|
-
before_create :create_token
|
157
156
|
before_create :link_by_email
|
158
157
|
before_update :ensure_updated_shipments, :homogenize_line_item_currencies, if: :currency_changed?
|
159
158
|
|
@@ -187,13 +186,46 @@ module Spree
|
|
187
186
|
scope :completed_between, ->(start_date, end_date) { where(completed_at: start_date..end_date) }
|
188
187
|
scope :complete, -> { where.not(completed_at: nil) }
|
189
188
|
scope :incomplete, -> { where(completed_at: nil) }
|
190
|
-
scope :
|
189
|
+
scope :canceled, -> { where(state: %w[canceled partially_canceled]) }
|
190
|
+
scope :not_canceled, -> { where.not(state: %w[canceled partially_canceled]) }
|
191
|
+
scope :ready_to_ship, -> { where(shipment_state: %w[ready pending]) }
|
192
|
+
scope :partially_shipped, -> { where(shipment_state: %w[partial]) }
|
193
|
+
scope :not_shipped, -> { where(shipment_state: %w[ready pending partial]) }
|
194
|
+
scope :shipped, -> { where(shipment_state: %w[shipped]) }
|
195
|
+
scope :refunded, lambda {
|
196
|
+
joins(:refunds).group(:id).having("sum(#{Spree::Refund.table_name}.amount) = #{Spree::Order.table_name}.total")
|
197
|
+
}
|
198
|
+
scope :partially_refunded, lambda {
|
199
|
+
joins(:refunds).group(:id).having("sum(#{Spree::Refund.table_name}.amount) < #{Spree::Order.table_name}.total")
|
200
|
+
}
|
191
201
|
scope :with_deleted_bill_address, -> { joins(:bill_address).where.not(Address.table_name => { deleted_at: nil }) }
|
192
202
|
scope :with_deleted_ship_address, -> { joins(:ship_address).where.not(Address.table_name => { deleted_at: nil }) }
|
193
203
|
|
194
204
|
# shows completed orders first, by their completed_at date, then uncompleted orders by their created_at
|
195
205
|
scope :reverse_chronological, -> { order(Arel.sql('spree_orders.completed_at IS NULL'), completed_at: :desc, created_at: :desc) }
|
196
206
|
|
207
|
+
def self.multi_search(query)
|
208
|
+
sanitized_query = sanitize_query_for_multi_search(query)
|
209
|
+
return none if query.blank?
|
210
|
+
|
211
|
+
query_pattern = "%#{sanitized_query}%"
|
212
|
+
|
213
|
+
conditions = []
|
214
|
+
conditions << arel_table[:number].lower.matches(query_pattern)
|
215
|
+
|
216
|
+
conditions << multi_search_condition(Spree::Address, :firstname, sanitized_query)
|
217
|
+
conditions << multi_search_condition(Spree::Address, :lastname, sanitized_query)
|
218
|
+
|
219
|
+
full_name = NameOfPerson::PersonName.full(sanitized_query)
|
220
|
+
|
221
|
+
if full_name.first.present? && full_name.last.present?
|
222
|
+
conditions << multi_search_condition(Spree::Address, :firstname, full_name.first)
|
223
|
+
conditions << multi_search_condition(Spree::Address, :lastname, full_name.last)
|
224
|
+
end
|
225
|
+
|
226
|
+
left_joins(:bill_address).where(email: sanitized_query).or(where(conditions.reduce(:or)))
|
227
|
+
end
|
228
|
+
|
197
229
|
# Use this method in other gems that wish to register their own custom logic
|
198
230
|
# that should be called after Order#update
|
199
231
|
def self.register_update_hook(hook)
|
@@ -223,6 +255,19 @@ module Spree
|
|
223
255
|
completed_at.present?
|
224
256
|
end
|
225
257
|
|
258
|
+
def order_refunded?
|
259
|
+
(payment_state == 'void' && refunds.sum(:amount).positive?) || refunds.sum(:amount) == total
|
260
|
+
end
|
261
|
+
|
262
|
+
def partially_refunded?
|
263
|
+
return false if refunds.empty?
|
264
|
+
|
265
|
+
# we must deduct not returned amount, otherwise it can look like order has not been fully refunded
|
266
|
+
amount_not_refunded = additional_tax_total.abs + total_applied_store_credit
|
267
|
+
|
268
|
+
refunds.sum(:amount) < total - amount_not_refunded
|
269
|
+
end
|
270
|
+
|
226
271
|
# Indicates whether or not the user is allowed to proceed to checkout.
|
227
272
|
# Currently this is implemented as a check for whether or not there is at
|
228
273
|
# least one LineItem in the Order. Feel free to override this logic in your
|
@@ -231,9 +276,9 @@ module Spree
|
|
231
276
|
line_items.exists?
|
232
277
|
end
|
233
278
|
|
234
|
-
# Does this order require a physical
|
279
|
+
# Does this order require a delivery (physical or digital).
|
235
280
|
def delivery_required?
|
236
|
-
|
281
|
+
true # true for Spree, can be decorated
|
237
282
|
end
|
238
283
|
|
239
284
|
# Is this a free order in which case the payment step should be skipped
|
@@ -251,10 +296,18 @@ module Spree
|
|
251
296
|
confirm?
|
252
297
|
end
|
253
298
|
|
299
|
+
def email_required?
|
300
|
+
require_email
|
301
|
+
end
|
302
|
+
|
254
303
|
def backordered?
|
255
304
|
shipments.any?(&:backordered?)
|
256
305
|
end
|
257
306
|
|
307
|
+
def quick_checkout?
|
308
|
+
shipping_address.present? && shipping_address.quick_checkout?
|
309
|
+
end
|
310
|
+
|
258
311
|
# Returns the relevant zone (if any) to be used for taxation purposes.
|
259
312
|
# Uses default tax zone unless there is a specific match
|
260
313
|
def tax_zone
|
@@ -285,7 +338,7 @@ module Spree
|
|
285
338
|
def allow_cancel?
|
286
339
|
return false if !completed? || canceled?
|
287
340
|
|
288
|
-
shipment_state.nil? || %w{ready backorder pending}.include?(shipment_state)
|
341
|
+
shipment_state.nil? || %w{ready backorder pending canceled}.include?(shipment_state)
|
289
342
|
end
|
290
343
|
|
291
344
|
def all_inventory_units_returned?
|
@@ -296,15 +349,19 @@ module Spree
|
|
296
349
|
def associate_user!(user, override_email = true)
|
297
350
|
self.user = user
|
298
351
|
self.email = user.email if override_email
|
299
|
-
|
300
|
-
|
301
|
-
self.
|
352
|
+
# we need to check if user is of admin user class to avoid mismatch type error
|
353
|
+
# in a scenario where we have separate classes for admin and regular users
|
354
|
+
self.created_by ||= user if user.is_a?(Spree.admin_user_class)
|
355
|
+
self.bill_address ||= user.bill_address
|
356
|
+
self.ship_address ||= user.ship_address
|
302
357
|
|
303
358
|
changes = slice(:user_id, :email, :created_by_id, :bill_address_id, :ship_address_id)
|
304
359
|
|
305
360
|
# immediately persist the changes we just made, but don't use save
|
306
361
|
# since we might have an invalid address associated
|
307
|
-
|
362
|
+
ActiveRecord::Base.connected_to(role: :writing) do
|
363
|
+
self.class.unscoped.where(id: self).update_all(changes)
|
364
|
+
end
|
308
365
|
end
|
309
366
|
|
310
367
|
def quantity_of(variant, options = {})
|
@@ -359,6 +416,37 @@ module Spree
|
|
359
416
|
end
|
360
417
|
end
|
361
418
|
|
419
|
+
def full_name
|
420
|
+
@full_name ||= if user.present? && user.name.present?
|
421
|
+
user.name.full
|
422
|
+
else
|
423
|
+
billing_address&.full_name || email
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
# Returns the payment method for the order
|
428
|
+
#
|
429
|
+
# @return [Spree::PaymentMethod] the payment method for the order
|
430
|
+
def payment_method
|
431
|
+
payments.valid.not_store_credits.first&.payment_method
|
432
|
+
end
|
433
|
+
|
434
|
+
# Returns the payment source for the order
|
435
|
+
#
|
436
|
+
# @return [Spree::PaymentSource] the payment source for the order
|
437
|
+
def payment_source
|
438
|
+
payments.valid.not_store_credits.first&.source
|
439
|
+
end
|
440
|
+
|
441
|
+
# Returns the backordered variants for the order
|
442
|
+
#
|
443
|
+
# @return [Array<Spree::Variant>] the backordered variants for the order
|
444
|
+
def backordered_variants
|
445
|
+
variants.
|
446
|
+
joins(:stock_items, :product).
|
447
|
+
where(Spree::StockItem.table_name => { count_on_hand: ..0, backorderable: true })
|
448
|
+
end
|
449
|
+
|
362
450
|
def can_ship?
|
363
451
|
complete? || resumed? || awaiting_return? || returned?
|
364
452
|
end
|
@@ -451,17 +539,16 @@ module Spree
|
|
451
539
|
end
|
452
540
|
|
453
541
|
def empty!
|
454
|
-
Spree::Deprecation.warn(<<-DEPRECATION, caller)
|
455
|
-
`Order#empty!` is deprecated and will be removed in Spree 5.0.
|
456
|
-
Please use `Spree::Cart::Empty.call(order: order)` instead.
|
457
|
-
DEPRECATION
|
458
|
-
|
459
542
|
raise Spree.t(:cannot_empty_completed_order) if completed?
|
460
543
|
|
461
544
|
result = Spree::Dependencies.cart_empty_service.constantize.call(order: self)
|
462
545
|
result.value
|
463
546
|
end
|
464
547
|
|
548
|
+
def use_all_coupon_codes
|
549
|
+
Spree::CouponCodes::CouponCodesHandler.new(order: self).use_all_codes
|
550
|
+
end
|
551
|
+
|
465
552
|
def has_step?(step)
|
466
553
|
checkout_steps.include?(step)
|
467
554
|
end
|
@@ -488,10 +575,10 @@ module Spree
|
|
488
575
|
|
489
576
|
def coupon_code=(code)
|
490
577
|
@coupon_code = begin
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
578
|
+
code.strip.downcase
|
579
|
+
rescue StandardError
|
580
|
+
nil
|
581
|
+
end
|
495
582
|
end
|
496
583
|
|
497
584
|
def can_add_coupon?
|
@@ -530,6 +617,22 @@ module Spree
|
|
530
617
|
@total_weight ||= line_items.joins(:variant).includes(:variant).map { |li| li.variant.weight * li.quantity }.sum
|
531
618
|
end
|
532
619
|
|
620
|
+
# Returns line items that have no shipping rates
|
621
|
+
#
|
622
|
+
# @return [Array<Spree::LineItem>]
|
623
|
+
def line_items_without_shipping_rates
|
624
|
+
@line_items_without_shipping_rates ||= shipments.map do |shipment|
|
625
|
+
shipment.manifest.map(&:line_item) if shipment.shipping_rates.blank?
|
626
|
+
end.flatten.compact
|
627
|
+
end
|
628
|
+
|
629
|
+
# Checks if all line items cannot be shipped
|
630
|
+
#
|
631
|
+
# @returns Boolean
|
632
|
+
def all_line_items_invalid?
|
633
|
+
line_items_without_shipping_rates.size == line_items.count
|
634
|
+
end
|
635
|
+
|
533
636
|
def apply_free_shipping_promotions
|
534
637
|
Spree::PromotionHandler::FreeShipping.new(self).activate
|
535
638
|
shipments.each { |shipment| Spree::Adjustable::AdjustmentsUpdater.update(shipment) }
|
@@ -578,17 +681,28 @@ module Spree
|
|
578
681
|
persist_totals
|
579
682
|
end
|
580
683
|
|
684
|
+
def shipping_method
|
685
|
+
# This query will select the first available shipping method from the shipments.
|
686
|
+
# It will use subquery to first select the shipping method id from the shipments' selected_shipping_rate.
|
687
|
+
Spree::ShippingMethod.
|
688
|
+
where(id: shipments.with_selected_shipping_method.limit(1).pluck(:shipping_method_id)).
|
689
|
+
limit(1).
|
690
|
+
first
|
691
|
+
end
|
692
|
+
|
581
693
|
def is_risky?
|
582
694
|
!payments.risky.empty?
|
583
695
|
end
|
584
696
|
|
585
|
-
def canceled_by(user)
|
697
|
+
def canceled_by(user, canceled_at = nil)
|
698
|
+
canceled_at ||= Time.current
|
699
|
+
|
586
700
|
transaction do
|
587
|
-
cancel!
|
588
701
|
update_columns(
|
589
702
|
canceler_id: user.id,
|
590
|
-
canceled_at:
|
703
|
+
canceled_at: canceled_at
|
591
704
|
)
|
705
|
+
cancel!
|
592
706
|
end
|
593
707
|
end
|
594
708
|
|
@@ -640,7 +754,7 @@ module Spree
|
|
640
754
|
end
|
641
755
|
|
642
756
|
def collect_backend_payment_methods
|
643
|
-
PaymentMethod.available_on_back_end.select { |pm| pm.available_for_order?(self) }
|
757
|
+
PaymentMethod.active.available_on_back_end.select { |pm| pm.available_for_order?(self) }
|
644
758
|
end
|
645
759
|
|
646
760
|
# determines whether the inventory is fully discounted
|
@@ -654,7 +768,7 @@ module Spree
|
|
654
768
|
alias fully_discounted fully_discounted?
|
655
769
|
|
656
770
|
def promo_code
|
657
|
-
promotions.pluck(:code).compact.first
|
771
|
+
Spree::CouponCode.find_by(order: self, promotion: promotions).try(:code) || promotions.pluck(:code).compact.first
|
658
772
|
end
|
659
773
|
|
660
774
|
def validate_payments_attributes(attributes)
|
@@ -700,6 +814,14 @@ module Spree
|
|
700
814
|
spree_promotion_actions: { type: 'Spree::Promotion::Actions::FreeShipping' }).exists?
|
701
815
|
end
|
702
816
|
|
817
|
+
def to_csv(_store = nil)
|
818
|
+
csv_lines = []
|
819
|
+
all_line_items.each_with_index do |line_item, index|
|
820
|
+
csv_lines << Spree::CSV::OrderLineItemPresenter.new(self, line_item, index).call
|
821
|
+
end
|
822
|
+
csv_lines
|
823
|
+
end
|
824
|
+
|
703
825
|
private
|
704
826
|
|
705
827
|
def link_by_email
|
@@ -707,8 +829,9 @@ module Spree
|
|
707
829
|
end
|
708
830
|
|
709
831
|
# Determine if email is required (we don't want validation errors before we hit the checkout)
|
832
|
+
# we need to add delivery to the list for quick checkouts
|
710
833
|
def require_email
|
711
|
-
true unless new_record? || ['cart', 'address'].include?(state)
|
834
|
+
true unless new_record? || ['cart', 'address', 'delivery'].include?(state)
|
712
835
|
end
|
713
836
|
|
714
837
|
def ensure_line_items_present
|
@@ -718,11 +841,18 @@ module Spree
|
|
718
841
|
end
|
719
842
|
|
720
843
|
def ensure_available_shipping_rates
|
721
|
-
if shipments.empty? ||
|
844
|
+
if shipments.empty? || line_items_without_shipping_rates.present?
|
722
845
|
# After this point, order redirects back to 'address' state and asks user to pick a proper address
|
723
846
|
# Therefore, shipments are not necessary at this point.
|
724
847
|
shipments.destroy_all
|
725
|
-
|
848
|
+
|
849
|
+
if line_items_without_shipping_rates.present?
|
850
|
+
errors.add(:base, Spree.t(:products_cannot_be_shipped, product_names: line_items_without_shipping_rates.map(&:name).to_sentence))
|
851
|
+
else
|
852
|
+
errors.add(:base, Spree.t(:items_cannot_be_shipped))
|
853
|
+
end
|
854
|
+
|
855
|
+
return false
|
726
856
|
end
|
727
857
|
end
|
728
858
|
|
@@ -748,12 +878,12 @@ module Spree
|
|
748
878
|
use_billing.in?([true, 'true', '1'])
|
749
879
|
end
|
750
880
|
|
751
|
-
def
|
752
|
-
|
881
|
+
def use_shipping?
|
882
|
+
use_shipping.in?([true, 'true', '1'])
|
753
883
|
end
|
754
884
|
|
755
|
-
def
|
756
|
-
self.
|
885
|
+
def ensure_currency_presence
|
886
|
+
self.currency ||= store.default_currency
|
757
887
|
end
|
758
888
|
|
759
889
|
def collect_payment_methods(store = nil)
|
@@ -133,10 +133,16 @@ module Spree
|
|
133
133
|
order.shipment_state = 'backorder'
|
134
134
|
else
|
135
135
|
# get all the shipment states for this order
|
136
|
-
shipment_states = shipments.states
|
136
|
+
shipment_states = shipments.states.uniq
|
137
|
+
|
137
138
|
order.shipment_state = if shipment_states.size > 1
|
138
|
-
|
139
|
-
|
139
|
+
if shipment_states.include?('shipped')
|
140
|
+
'partial'
|
141
|
+
elsif shipment_states.include?('pending')
|
142
|
+
'pending'
|
143
|
+
else
|
144
|
+
'ready'
|
145
|
+
end
|
140
146
|
else
|
141
147
|
# will return nil if no shipments are found
|
142
148
|
shipment_states.first
|
@@ -0,0 +1,184 @@
|
|
1
|
+
module Spree
|
2
|
+
class Page < Spree.base_class
|
3
|
+
include Spree::Previewable
|
4
|
+
|
5
|
+
#
|
6
|
+
# Magic methods
|
7
|
+
#
|
8
|
+
extend FriendlyId
|
9
|
+
friendly_id :slug_candidates, use: [:slugged, :scoped, :history], scope: :pageable
|
10
|
+
acts_as_paranoid
|
11
|
+
|
12
|
+
#
|
13
|
+
# Associations
|
14
|
+
#
|
15
|
+
belongs_to :pageable, polymorphic: true # this can be either Store or Theme
|
16
|
+
has_many :sections, -> { order(position: :asc) }, class_name: 'Spree::PageSection', dependent: :destroy_async, as: :pageable
|
17
|
+
has_many :page_links, as: :linkable, class_name: 'Spree::PageLink', dependent: :destroy
|
18
|
+
alias page_sections sections
|
19
|
+
|
20
|
+
#
|
21
|
+
# Validations
|
22
|
+
#
|
23
|
+
validates :name, presence: true
|
24
|
+
validates :pageable, presence: true
|
25
|
+
validates :slug, uniqueness: { scope: :pageable, conditions: -> { where(deleted_at: nil).where.not(slug: nil) } }
|
26
|
+
|
27
|
+
#
|
28
|
+
# Callbacks
|
29
|
+
#
|
30
|
+
before_validation :set_name
|
31
|
+
after_create :create_default_sections, unless: :duplicating
|
32
|
+
|
33
|
+
#
|
34
|
+
# Scopes
|
35
|
+
#
|
36
|
+
scope :linkable, lambda {
|
37
|
+
where(type: [
|
38
|
+
'Spree::Pages::Homepage',
|
39
|
+
'Spree::Pages::ShopAll',
|
40
|
+
'Spree::Pages::PostList',
|
41
|
+
'Spree::Pages::Custom',
|
42
|
+
'Spree::Pages::Account',
|
43
|
+
'Spree::Pages::Login'
|
44
|
+
])
|
45
|
+
}
|
46
|
+
scope :product_details, -> { where(type: 'Spree::Pages::ProductDetails') }
|
47
|
+
scope :standard, -> { where.not(type: 'Spree::Pages::Custom') }
|
48
|
+
scope :custom, -> { where(type: 'Spree::Pages::Custom') }
|
49
|
+
|
50
|
+
#
|
51
|
+
# Virtual attributes
|
52
|
+
#
|
53
|
+
attribute :duplicating, :boolean, default: false
|
54
|
+
|
55
|
+
def icon_name
|
56
|
+
'file-earmark-richtext'
|
57
|
+
end
|
58
|
+
|
59
|
+
def store
|
60
|
+
if pageable.is_a?(Spree::Store)
|
61
|
+
pageable
|
62
|
+
else
|
63
|
+
pageable.store
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_preview
|
68
|
+
return self if preview? # no need to create a preview for the preview
|
69
|
+
|
70
|
+
ActiveRecord::Base.connected_to(role: :writing) do
|
71
|
+
ApplicationRecord.transaction do
|
72
|
+
new_preview = dup
|
73
|
+
new_preview.parent = self
|
74
|
+
new_preview.duplicating = true
|
75
|
+
new_preview.save!
|
76
|
+
|
77
|
+
sections.includes(:links, { asset_attachment: :blob }, { blocks: [:rich_text_text, :links] }).each do |section|
|
78
|
+
section.deep_clone(new_preview)
|
79
|
+
end
|
80
|
+
|
81
|
+
new_preview
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Promotes the page preview to the main page
|
87
|
+
def promote
|
88
|
+
return unless preview?
|
89
|
+
|
90
|
+
ApplicationRecord.transaction do
|
91
|
+
old_page = parent
|
92
|
+
old_page.page_links.update_all(linkable_id: id)
|
93
|
+
update(parent: nil) # clear reference to the old page
|
94
|
+
Spree::Page.find(old_page.id).destroy # destroy the old page with their other previews, etc.
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def default_sections
|
99
|
+
[]
|
100
|
+
end
|
101
|
+
|
102
|
+
def customizable?
|
103
|
+
false
|
104
|
+
end
|
105
|
+
|
106
|
+
def layout_sections?
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
def preview_url(theme_preview = nil, page_preview = nil)
|
111
|
+
return if page_builder_url.blank?
|
112
|
+
|
113
|
+
"#{page_builder_url}?#{url_query_params(theme_preview, page_preview).to_query}"
|
114
|
+
end
|
115
|
+
|
116
|
+
def display_name
|
117
|
+
if custom?
|
118
|
+
name
|
119
|
+
else
|
120
|
+
name.titleize
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def custom?
|
125
|
+
type == 'Spree::Pages::Custom'
|
126
|
+
end
|
127
|
+
|
128
|
+
def duplicate(target_pageable)
|
129
|
+
duplicated_page = dup
|
130
|
+
duplicated_page.duplicating = true
|
131
|
+
duplicated_page.pageable = target_pageable
|
132
|
+
duplicated_page.save!
|
133
|
+
|
134
|
+
sections_scope = sections.includes(:links, :blocks, { asset_attachment: :blob },
|
135
|
+
{ blocks: [:rich_text_text, :links, { asset_attachment: :blob }] })
|
136
|
+
sections_scope.each { |section| section.deep_clone(duplicated_page) }
|
137
|
+
|
138
|
+
duplicated_page
|
139
|
+
end
|
140
|
+
|
141
|
+
def theme
|
142
|
+
@theme ||= if pageable.is_a?(Spree::Theme)
|
143
|
+
pageable
|
144
|
+
else
|
145
|
+
pageable.default_theme
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def create_default_sections
|
152
|
+
default_sections.each do |section|
|
153
|
+
section.pageable = self
|
154
|
+
section.save!
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def url_query_params(theme_preview, page_preview)
|
159
|
+
theme_preview_cache = theme_preview.updated_at.to_i.to_s + rand(999_999).to_s if theme_preview
|
160
|
+
|
161
|
+
{
|
162
|
+
theme_id: theme.id,
|
163
|
+
page_preview_id: page_preview&.id,
|
164
|
+
theme_preview_id: theme_preview&.id,
|
165
|
+
theme_preview_cache: theme_preview_cache
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def set_name
|
170
|
+
return if custom?
|
171
|
+
return if name.present?
|
172
|
+
|
173
|
+
self.name = self.class.name.demodulize
|
174
|
+
end
|
175
|
+
|
176
|
+
def should_generate_new_friendly_id?
|
177
|
+
name_changed? && custom?
|
178
|
+
end
|
179
|
+
|
180
|
+
def page_builder_url_exists?(path)
|
181
|
+
Spree::Core::Engine.routes.url_helpers.respond_to?(path)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|