- <%= f.field_container :name do %>
- <%= f.label :name, class: 'required' %>
- <%= f.text_field :name, required: true, class: 'fullwidth' %>
- <%= f.error_message_on :name %>
- <% end %>
+
+
+
<%= t('.store_settings') %>
+
+
+ <%= f.field_container :name do %>
+ <%= f.label :name, class: 'required' %>
+ <%= f.text_field :name, required: true, class: 'fullwidth' %>
+ <%= f.error_message_on :name %>
+ <% end %>
+
- <%= f.field_container :code do %>
- <%= f.label :code, class: 'required' %>
- <%= f.field_hint :code %>
- <%= f.text_field :code, required: true, class: 'fullwidth' %>
- <%= f.error_message_on :code %>
- <% end %>
+
+ <%= f.field_container :url do %>
+ <%= f.label :url, class: 'required' %>
+ <%= f.text_field :url, required: true, class: 'fullwidth' %>
+ <%= f.error_message_on :url %>
+ <% end %>
+
- <%= f.field_container :seo_title do %>
- <%= f.label :seo_title %>
- <%= f.text_field :seo_title, class: 'fullwidth' %>
- <%= f.error_message_on :seo_title %>
- <% end %>
-
- <%= f.field_container :meta_keywords do %>
- <%= f.label :meta_keywords %>
- <%= f.text_field :meta_keywords, class: 'fullwidth' %>
- <%= f.error_message_on :meta_keywords %>
- <% end %>
-
- <%= f.field_container :meta_description do %>
- <%= f.label :meta_description %>
- <%= f.text_area :meta_description, class: 'fullwidth' %>
- <%= f.error_message_on :meta_description %>
- <% end %>
+
+ <%= f.field_container :code do %>
+ <%= f.label :code, class: 'required' %>
+ <%= f.field_hint :code %>
+ <%= f.text_field :code, required: true, class: 'fullwidth' %>
+ <%= f.error_message_on :code %>
+ <% end %>
+
-
- <%= f.field_container :url do %>
- <%= f.label :url, class: 'required' %>
- <%= f.text_field :url, required: true, class: 'fullwidth' %>
- <%= f.error_message_on :url %>
- <% end %>
- <%= f.field_container :mail_from_address do %>
- <%= f.label :mail_from_address, class: 'required' %>
- <%= f.text_field :mail_from_address, required: true, class: 'fullwidth' %>
- <%= f.error_message_on :mail_from_address %>
- <% end %>
+
+
<%= t('.regional_settings') %>
+
+
+ <%= f.field_container :default_currency do %>
+ <%= f.label :default_currency %>
+ <%= f.field_hint :default_currency %>
+ <%= f.select :default_currency,
+ Spree::Config.available_currencies.map(&:iso_code),
+ { include_blank: true },
+ { class: 'custom-select fullwidth' } %>
+ <%= f.error_message_on :default_currency %>
+ <% end %>
+
+
+ <%= f.field_container :cart_tax_country_iso do %>
+ <%= f.label :cart_tax_country_iso %>
+ <%= f.field_hint :cart_tax_country_iso %>
+ <%= f.collection_select :cart_tax_country_iso,
+ available_countries(restrict_to_zone: nil), :iso, :name,
+ { include_blank: t(".no_cart_tax_country") },
+ { class: "custom-select fullwidth" } %>
+ <%= f.error_message_on :cart_tax_country_iso %>
+ <% end %>
+
+
+ <%= f.field_container :available_locales do %>
+ <%= f.label :available_locales %>
+ <%= f.field_hint :available_locales %>
+ <%= f.select :available_locales,
+ Spree.i18n_available_locales.map { |locale|
+ [I18n.t('spree.i18n.this_file_language', locale: locale, default: locale.to_s, fallback: false), locale]
+ }.sort,
+ { },
+ { class: 'select2 fullwidth', multiple: true } %>
+ <%= f.error_message_on :default_currency %>
+ <% end %>
+
+
- <%= f.field_container :bcc_email do %>
- <%= f.label :bcc_email %>
- <%= f.text_field :bcc_email, class: 'fullwidth' %>
- <%= f.error_message_on :bcc_email %>
- <% end %>
+
+
<%= t('.email_settings') %>
+
+
+ <%= f.field_container :mail_from_address do %>
+ <%= f.label :mail_from_address, class: 'required' %>
+ <%= f.text_field :mail_from_address, required: true, class: 'fullwidth' %>
+ <%= f.error_message_on :mail_from_address %>
+ <% end %>
+
+
+ <%= f.field_container :bcc_email do %>
+ <%= f.label :bcc_email %>
+ <%= f.text_field :bcc_email, class: 'fullwidth' %>
+ <%= f.error_message_on :bcc_email %>
+ <% end %>
+
+
- <%= f.field_container :default_currency do %>
- <%= f.label :default_currency %>
- <%= f.field_hint :default_currency %>
- <%= f.select :default_currency,
- Spree::Config.available_currencies.map(&:iso_code),
- { include_blank: true },
- { class: 'custom-select fullwidth' } %>
- <%= f.error_message_on :default_currency %>
- <% end %>
+
+
<%= t('.store_legal_addres') %>
+
+ <%= render partial: 'address_form', locals: { f: f, type: 'store' } %>
+
- <%= f.field_container :cart_tax_country_iso do %>
- <%= f.label :cart_tax_country_iso %>
- <%= f.field_hint :cart_tax_country_iso %>
- <%= f.collection_select :cart_tax_country_iso,
- available_countries(restrict_to_zone: nil), :iso, :name,
- { include_blank: t(".no_cart_tax_country") },
- { class: "custom-select fullwidth" } %>
- <%= f.error_message_on :cart_tax_country_iso %>
- <% end %>
+
+
<%= t('.contact_options') %>
+
+
+ <%= f.field_container :contact_phone do %>
+ <%= f.label :contact_phone %>
+ <%= f.phone_field :contact_phone, class: 'fullwidth' %>
+ <%= f.error_message_on :contact_phone %>
+ <% end %>
+
+
+ <%= f.field_container :contact_email do %>
+ <%= f.label :contact_email %>
+ <%= f.email_field :contact_email, class: 'form-control' %>
+ <%= f.error_message_on :contact_email %>
+ <% end %>
+
+
- <%= f.field_container :available_locales do %>
- <%= f.label :available_locales %>
- <%= f.field_hint :available_locales %>
- <%= f.select :available_locales,
- Spree.i18n_available_locales.map { |locale|
- [I18n.t('spree.i18n.this_file_language', locale: locale, default: locale.to_s, fallback: false), locale]
- }.sort,
- { },
- { class: 'select2 fullwidth', multiple: true } %>
- <%= f.error_message_on :default_currency %>
- <% end %>
+
+
<%= t('.content_on_storefront') %>
+
+
+ <%= f.field_container :seo_title do %>
+ <%= f.label :seo_title %>
+ <%= f.text_field :seo_title, class: 'fullwidth' %>
+ <%= f.error_message_on :seo_title %>
+ <% end %>
+
+
+ <%= f.field_container :meta_keywords do %>
+ <%= f.label :meta_keywords %>
+ <%= f.text_field :meta_keywords, class: 'fullwidth' %>
+ <%= f.error_message_on :meta_keywords %>
+ <% end %>
+
+
+ <%= f.field_container :description do %>
+ <%= f.label :description, class: 'form-label' %>
+ <%= f.text_area :description, class: 'form-control' %>
+ <% end %>
+
+
+ <%= f.field_container :meta_description do %>
+ <%= f.label :meta_description %>
+ <%= f.text_area :meta_description, class: 'fullwidth' %>
+ <%= f.error_message_on :meta_description %>
+ <% end %>
+
diff --git a/core/app/models/spree/store.rb b/core/app/models/spree/store.rb
index 9350fb0a2b8..462c55682cd 100644
--- a/core/app/models/spree/store.rb
+++ b/core/app/models/spree/store.rb
@@ -15,12 +15,16 @@ class Store < Spree::Base
has_many :store_shipping_methods, inverse_of: :store
has_many :shipping_methods, through: :store_shipping_methods
+ belongs_to :state, class_name: 'Spree::State', optional: true
+ belongs_to :country, class_name: 'Spree::Country', optional: true
+
has_many :orders, class_name: "Spree::Order"
validates :code, presence: true, uniqueness: { allow_blank: true, case_sensitive: true }
validates :name, presence: true
validates :url, presence: true
validates :mail_from_address, presence: true
+ validates :state, presence: true, if: -> { country&.states_required }
self.allowed_ransackable_attributes = %w[name url code]
diff --git a/core/config/locales/en.yml b/core/config/locales/en.yml
index 0dd3145a750..b66e0c6dc2c 100644
--- a/core/config/locales/en.yml
+++ b/core/config/locales/en.yml
@@ -354,18 +354,32 @@ en:
quantity: Quantity
variant: Variant
spree/store:
- available_locales: Locales Available in the Storefront
+ address: Address
+ address1: Street Address
+ address2: Street Address (cont'd)
+ available_locales: Languages Available in the Storefront
bcc_email: BCC Email
cart_tax_country_iso: Tax Country for Empty Carts
+ city: City
code: Slug
+ contact_email: Contact Email
+ contact_phone: Contact Phone
+ country_id: Country
default: Default
default_currency: Default Currency
+ description: Store Description
+ legal_name: Legal Name
mail_from_address: Mail From Address
meta_description: Meta Description
meta_keywords: Meta Keywords
name: Site Name
+ postal_code: Postal Code
seo_title: Seo Title
+ state_id: State
+ tax_id: Tax-ID
url: Site URL
+ vat_id: VAT-ID
+ zipcode: Zip Code
spree/store_credit:
amount: Amount
amount_authorized: Amount Authorized
@@ -939,7 +953,13 @@ en:
view: View store credit
stores:
form:
+ contact_options: Contact Options
+ content_on_storefront: Content on Storefront
+ email_settings: Email Settings
no_cart_tax_country: No taxes on carts without address
+ regional_settings: Regional Settings
+ store_legal_addres: Store Legal Address
+ store_settings: Store Name & URL / URI Settings
tab:
checkout: Refunds and Returns
configuration: Configuration
@@ -1629,6 +1649,7 @@ en:
cart_tax_country_iso: 'This determines which country is used for taxes on carts (orders which don''t yet have an address).
Default: None.'
code: An identifier for your store. Developers may need this value if you operate multiple storefronts.
default_currency: This determines which currency will be used for the storefront's product prices. Please, be aware that changing this configuration, only products that have prices in the selected currency will be listed on your storefront.
This setting won't change the default currency used when you create a product. For that, only the global `Spree::Config.currency` is taken into account.
+ vat_id: Enter your VAT-ID without the Country Prefix (eg IT for Italy or DE for Germany) but solely the identification string.
spree/tax_category:
is_default: When checked, this tax category will be selected by default when creating new products or variants.
spree/tax_rate:
diff --git a/core/db/migrate/20250202173007_add_store_attributes_to_spree_stores.rb b/core/db/migrate/20250202173007_add_store_attributes_to_spree_stores.rb
new file mode 100644
index 00000000000..f1a854f2b7b
--- /dev/null
+++ b/core/db/migrate/20250202173007_add_store_attributes_to_spree_stores.rb
@@ -0,0 +1,19 @@
+class AddStoreAttributesToSpreeStores < ActiveRecord::Migration[7.2]
+ def change
+ add_column :spree_stores, :legal_name, :string
+ add_column :spree_stores, :contact_email, :string
+ add_column :spree_stores, :description, :text
+ add_column :spree_stores, :vat_id, :string
+ add_column :spree_stores, :tax_id, :string
+ add_column :spree_stores, :address1, :string
+ add_column :spree_stores, :address2, :string
+ add_column :spree_stores, :city, :string
+ add_column :spree_stores, :zipcode, :string
+ add_column :spree_stores, :state_name, :string
+ add_column :spree_stores, :contact_phone, :string
+ add_column :spree_stores, :country_id, :integer
+ add_column :spree_stores, :state_id, :integer
+ add_index :spree_stores, :country_id
+ add_index :spree_stores, :state_id
+ end
+end
diff --git a/core/lib/spree/permitted_attributes.rb b/core/lib/spree/permitted_attributes.rb
index cd59e762e21..eecb914fd57 100644
--- a/core/lib/spree/permitted_attributes.rb
+++ b/core/lib/spree/permitted_attributes.rb
@@ -121,10 +121,12 @@ module PermittedAttributes
:quantity, :stock_item, :stock_item_id, :originator, :action
]
- @@store_attributes = [:name, :url, :seo_title, :meta_keywords,
+ @@store_attributes = [:name, :legal_name, :url, :seo_title, :meta_keywords,
:meta_description, :default_currency,
:mail_from_address, :cart_tax_country_iso,
- :bcc_email]
+ :bcc_email, :contact_email, :contact_phone, :code,
+ :tax_id, :vat_id, :description, :address1, :address2,
+ :city, :zipcode, :country_id, :state_id, :state_name]
@@taxonomy_attributes = [:name]