Merge branch 'master' into 12620-fix-rubocop-rails-response-parse-body

This commit is contained in:
Hartani Yassir
2025-01-31 11:23:15 +01:00
committed by GitHub
50 changed files with 346 additions and 413 deletions

View File

@@ -20,17 +20,9 @@ module Spree
end
def create
if params[:user]
roles = params[:user].delete("spree_role_ids")
end
@user = Spree::User.new(user_params)
if @user.save
if roles
@user.spree_roles = roles.compact_blank.collect{ |r| Spree::Role.find(r) }
end
flash[:success] = Spree.t(:created_successfully)
redirect_to edit_admin_user_path(@user)
else
@@ -39,15 +31,7 @@ module Spree
end
def update
if params[:user]
roles = params[:user].delete("spree_role_ids")
end
if @user.update(user_params)
if roles
@user.spree_roles = roles.compact_blank.collect{ |r| Spree::Role.find(r) }
end
flash[:success] = update_message
redirect_to edit_admin_user_path(@user)
else
@@ -131,7 +115,7 @@ module Spree
def user_params
::PermittedAttributes::User.new(params).call(
%i[enterprise_limit show_api_key_view]
%i[admin enterprise_limit show_api_key_view]
)
end
end

View File

@@ -37,7 +37,6 @@ module Spree
preference :currency_symbol_position, :string, default: "before"
preference :currency_thousands_separator, :string, default: ","
preference :display_currency, :boolean, default: false
preference :default_country_id, :integer
preference :default_meta_description, :string, default: 'OFN demo site'
preference :default_meta_keywords, :string, default: 'ofn, demo'
preference :default_seo_title, :string, default: ''

View File

@@ -1,13 +0,0 @@
# frozen_string_literal: true
module Spree
class Role < ApplicationRecord
has_and_belongs_to_many :users, join_table: 'spree_roles_users',
class_name: "Spree::User"
# The only role we have at the moment:
def self.admin
Spree::Role.find_or_create_by(name: 'admin')
end
end
end

View File

@@ -105,16 +105,7 @@ module Spree
if default_zone_or_zone_match?(item.order)
calculator.compute(item)
else
# Tax refund should not be possible with the way our production server are configured
Alert.raise(
"Notice: Tax refund should not be possible, please check the default zone and " \
"the tax rate zone configuration"
) do |payload|
payload.add_metadata :order_tax_zone, item.order.tax_zone
payload.add_metadata :tax_rate_zone, zone
payload.add_metadata :default_zone, Zone.default_tax
end
# In this case, it's a refund.
# In this case, it's a refund (for instance offering a manual discount via an adjustment)
calculator.compute(item) * - 1
end
else

View File

@@ -18,15 +18,11 @@ module Spree
belongs_to :ship_address, class_name: 'Spree::Address'
belongs_to :bill_address, class_name: 'Spree::Address'
has_and_belongs_to_many :spree_roles,
join_table: 'spree_roles_users',
class_name: "Spree::Role"
before_validation :set_login
after_create :associate_customers, :associate_orders
before_destroy :check_completed_orders
scope :admin, lambda { includes(:spree_roles).where("spree_roles.name" => "admin") }
scope :admin, -> { where(admin: true) }
has_many :enterprise_roles, dependent: :destroy
has_many :enterprises, through: :enterprise_roles
@@ -58,11 +54,6 @@ module Spree
User.admin.count > 0
end
# Checks whether the specified user is a superadmin, with full control of the instance
def admin?
spree_roles.any? { |role| role.name == "admin" }
end
# Send devise-based user emails asyncronously via ActiveJob
# See: https://github.com/heartcombo/devise/tree/v3.5.10#activejob-integration
def send_devise_notification(notification, *args)

View File

@@ -7,6 +7,8 @@ module Spree
has_and_belongs_to_many :shipping_methods, join_table: 'spree_shipping_methods_zones'
validates :name, presence: true, uniqueness: true
validates :zone_members, presence: true
after_save :remove_defunct_members
after_save :remove_previous_default

View File

@@ -5,13 +5,8 @@
= f.email_field :email, class: "fullwidth"
= error_message_on :user, :email
.field
= label_tag nil, t(".roles")
%ul
- [Spree::Role.admin].each do |role|
%li
= check_box_tag "user[spree_role_ids][]", role.id, @user.spree_roles.include?(role), id: "user_spree_role_#{role.name}"
= label_tag role.name
= hidden_field_tag "user[spree_role_ids][]", ""
= f.label :admin, t(".admin")
= f.check_box :admin
= f.field_container :locale do
= f.label :locale, t(".locale")
= f.select :locale, locale_options, class: "fullwidth"

View File

@@ -22,7 +22,7 @@
%tr
%th= sort_link [:spree, @search], :name, t("spree.name"), title: 'zones_order_by_name_title'
%th
= sort_link [:spree, @search], :description, t("spree.description"), {}, {title: 'zones_order_by_description_title'}
= sort_link [:spree, @search], :description, t("spree.description"), {title: 'zones_order_by_description_title'}
%th= t("spree.default_tax")
%th.actions
%tbody

View File

@@ -11,5 +11,7 @@
= form_for [:admin, @zone] do |zone_form|
= render partial: 'form', locals: { zone_form: zone_form }
= render partial: 'member_type', locals: { type: 'country', zone_form: zone_form }
= render partial: 'member_type', locals: { type: 'state', zone_form: zone_form }
.clear
= render partial: 'spree/admin/shared/new_resource_links'

View File

@@ -0,0 +1,7 @@
# https://github.com/zombocom/rack-timeout/blob/main/doc/logging.md
# state changes into timed_out and expired are logged at the ERROR level
# Log ready and completed messages in DEBUG mode only (instead of default INFO)
Rack::Timeout::StateChangeLoggingObserver::STATE_LOG_LEVEL[:ready] = :debug
Rack::Timeout::StateChangeLoggingObserver::STATE_LOG_LEVEL[:completed] = :debug

View File

@@ -61,7 +61,7 @@ el:
order_cycle:
orders_close_at: Ημερομηνία Κλεισίματος
variant_override:
count_on_hand: "Στο χέρι"
count_on_hand: "Διαθέσιμο απόθεμα"
spree/payment_method/calculator:
preferred_flat_percent: "Υπολογιστής Σταθερού Ποσοστού:"
preferred_amount: "Υπολογιστής Ποσού: "
@@ -433,7 +433,7 @@ el:
show_all_with_more: "Εμφάνιση όλων"
cancel: Ακύρωση
edit: Επεξεργασία
clone: Κλώνος
clone: Κλωνοποίηση
distributors: Διανομείς
distribution: Κατανομή
order_cycles: Κύκλοι παραγγελιών
@@ -488,8 +488,8 @@ el:
back_to_payments_list: "Επιστροφή στη λίστα πληρωμών"
maestro_or_solo_cards: "Κάρτα Maestro/Sola"
backordered: "Σε εκκρεμότητα"
on_hand: "Στο χέρι"
on hand: "Στο χέρι"
on_hand: "Διαθέσιμο απόθεμα"
on hand: "Διαθέσιμο απόθεμα"
ship: "Αποστολή"
shipping_category: "Κατηγορία μεταφορικών"
height: "Ύψος"
@@ -534,26 +534,26 @@ el:
producer: Παραγωγός
category: Κατηγορία
sku: SKU
on_hand: "Στο χέρι"
on_hand: "Διαθέσιμο απόθεμα"
on_demand: "Κατά παραγγελία"
tax_category: "Φορολογική Κατηγορία"
inherits_properties: "Διατήρηση Ιδιοτήτων"
import_date: "Ημερομηνία καταχώρησης"
actions: Δράση
actions: Ενέργειες
columns_selector:
unit: Μονάδα
price: Τιμή
producer: Παραγωγός
category: Κατηγορία
sku: SKU
on_hand: "Στο χέρι"
on_hand: "Διαθέσιμο απόθεμα"
on_demand: "Κατά παραγγελία"
tax_category: "Φορολογική Κατηγορία"
inherits_properties: "Διατήρηση Ιδιοτήτων"
import_date: "Ημερομηνία καταχώρησης"
actions:
edit: Επεξεργασία
clone: Κλώνος
clone: Κλωνοποίηση
delete: Διαγραφή
remove: Αφαίρεση
image:
@@ -574,7 +574,7 @@ el:
name: Όνομα
first_name: Όνομα
last_name: Επίθετο
on_hand: Στο χέρι
on_hand: Διαθέσιμο απόθεμα
on_demand: Κατά παραγγελία
on_demand?: Κατά παραγγελία?
order_cycle: Κύκλος Παραγγελειών
@@ -615,7 +615,7 @@ el:
please_select: Παρακαλώ επιλέξτε...
column_save_as_default: Αποθήκευση ως πρότυπο
columns: Στήλες
actions: Δράση
actions: Ενέργειες
viewing: "Προβολή : %{current_view_name}"
description: Περιγραφή
whats_this: Τι είναι αυτό?
@@ -725,7 +725,7 @@ el:
index:
title: "Τέλη επιχείρησης"
enterprise: "Επιχείρηση"
fee_type: "Κατηγορίες αμοιβών"
fee_type: "Κατηγορίες τελών"
name: "Όνομα"
tax_category: "Φορολογική Κατηγορία"
calculator: "Υπολογισμός"
@@ -769,7 +769,7 @@ el:
seo_tip: "Χρησιμοποιήστε λέξεις - κλειδιά για να βοηθήσετε στην αναζήτηση των προϊόντων σας στο διαδίκτυο. Χρησιμοποιήστε κενό για να διαχωρίσετε κάθε λέξη -κλειδί."
search: "Αναζήτηση"
properties:
property_name: "Όνομα Ιδιοκτησίας"
property_name: "Όνομα ιδιότητας"
inherited_property: "Επίκτητη ιδιότητα"
variants:
infinity: "Άπειρο"
@@ -962,7 +962,7 @@ el:
unit_type: Τύπος μονάδας
variant_unit_name: Όνομα μεταβλητής
price: Τιμή
on_hand: Στο χέρι
on_hand: Διαθέσιμο απόθεμα
on_demand: Κατά παραγγελία
shipping_category: Κατηγορία μεταφορικών
tax_category: Φορολογική Κατηγορία
@@ -1089,12 +1089,12 @@ el:
enterprise_fees:
legend: "Τέλη επιχείρησης"
name: Όνομα
fee_type: Κατηγορίες αμοιβών
fee_type: Κατηγορίες τελών
manage_fees: Διαχείριση τελών επιχείρησης
no_fees_yet: Δεν έχετε τέλη επιχείρησης ακόμα.
create_button: Δημιούργησε έναν τώρα
enterprise_permissions:
legend: "Δικαιώματα Επιχείρησης "
legend: "Άδειες επιχείρησης"
enterprise_relationships: Σχέσεις Επιχειρήσεων
images:
legend: "Εικόνες"
@@ -1341,7 +1341,7 @@ el:
hub_shop_text: Πούλα προιόντα άλλων
hub_shop_description_text: Η επιχείρησή σας είναι η ραχοκοκαλιά του τοπικού σας συστήματος τροφίμων. Συγκεντρώνετε προϊόντα από άλλες επιχειρήσεις και μπορείτε να τα πουλήσετε μέσω του καταστήματός σας στο Open Food Network.
choose_option: Επιλέξτε μία από τις παραπάνω επιλογές.
change_now: Άλαξέ το τώρα
change_now: Εφαρμογή αλλαγής
enterprise_user_index:
loading_enterprises: ΦΌΡΤΩΣΕ ΤΙΣ ΕΠΙΧΕΙΡΉΣΕΙΣ
no_enterprises_found: Δεν βρέθηκε επιχείρηση.
@@ -1550,7 +1550,7 @@ el:
shipping_methods: "Τρόποι αποστολής"
payment_methods: "Τρόποι πληρωμής"
enterprise_fees: "Τέλη επιχείρησης"
enterprise_permissions: "Δικαιώματα Επιχείρησης "
enterprise_permissions: "Άδειες επιχείρησης"
inventory_settings: "Ρυθμίσεις Αποθεμάτων"
tag_rules: "Κανόνες ετικετών"
shop_preferences: "Επιλογές καταστήματος"
@@ -1585,7 +1585,7 @@ el:
totals_by_supplier: Παραγγείλετε συνολικά διανομέας κύκλου ανά προμηθευτή
customer_totals: Σύνολο κύκλου παραγγελιών για τον πελάτη
all_products: Ολα τα προϊόντα
inventory: Απογραφή (στο χέρι)
inventory: 'Απόθεμα (Διαθέσιμο) '
lettuce_share: Μαρούλι
payment_methods: Αναφορά μεθόδων πληρωμής
delivery: Αναφορά παράδοσης
@@ -2307,7 +2307,7 @@ el:
shopping_oc_last_closed: "Ο τελευταίος κύκλος έκλεισε %{distance_of_time} πριν"
shopping_oc_next_open: "Ο επόμενος κύκλος ανοίγει σε %{distance_of_time}"
shopping_oc_select: "Επιλέγω..."
shopping_tabs_home: "Home"
shopping_tabs_home: "Αρχική"
shopping_tabs_shop: "Κατάστημα"
shopping_tabs_about: "Σχετικά"
shopping_tabs_producers: "Παραγωγοί"
@@ -2336,7 +2336,7 @@ el:
hubs_filter_by: "Φιλτράρισμα κατά"
hubs_filter_type: "Τύπος"
hubs_filter_delivery: "Διανομή"
hubs_filter_property: "Ιδιοκτησία"
hubs_filter_property: "Ιδιότητα"
hubs_matches: "Εννοείς?"
hubs_intro: Ψώνισε στην περιοχή σου
hubs_distance: Πιο κοντά στο
@@ -2418,7 +2418,7 @@ el:
producers_buy_at_html: "Αγοράστε προϊόντα %{enterprise} στη διεύθυνση:"
producers_filter: Φιλτράρισμα κατά
producers_filter_type: Τύπος
producers_filter_property: Ιδιοκτησία
producers_filter_property: Ιδιότητα
producers_title: Παραγωγοί
producers_headline: Βρες τοπικούς παραγωγούς
producers_signup_title: Εγγραφείτε ως παραγωγός
@@ -2689,9 +2689,9 @@ el:
text: "Έχετε συμπληρώσει το όριο για τον αριθμό των επιχειρήσεων που επιτρέπεται να έχετε στην ιδιοκτησία σας"
action: "Επιστροφή στην αρχική σελίδα"
finished:
headline: "Πεπερασμένος!"
headline: "Η διαδικασία ολοκληρώθηκε!"
thanks: "Ευχαριστούμε για τη συμπλήρωση των στοιχείων για το %{enterprise}."
login: "Μπορείτε να αλλάξετε ή να ενημερώσετε την επιχείρησή σας σε οποιοδήποτε στάδιο, συνδεθείτε στο Open Food Network και μεταβείτε στον Διαχειριστή."
login: "Μπορείτε να αλλάξετε ή να ενημερώσετε την επιχείρησή σας σε οποιοδήποτε στάδιο, συνδεθείτε στο Open Food Network και μεταβείτε στον πίνακα διαχείρισης."
action: "Μεταβείτε στον Πίνακα Επιχειρήσεων"
back: "Πίσω"
continue: "Συνέχεια"
@@ -2779,7 +2779,7 @@ el:
process_my_order: "Επεξεργασία της παραγγελίας μου"
delivery_instructions: Οδηγίες παράδοσης
delivery_method: Μέθοδος παράδοσης
fee_type: "Κατηγορίες αμοιβών"
fee_type: "Κατηγορίες τελών"
tax_category: "Φορολογική κατηγορία"
display: "Εμφάνιση"
tags: "Ετικέτες"
@@ -2802,7 +2802,7 @@ el:
roles: "Ρόλοι"
update: "Ανανέωση"
delete: Διαγραφή
add_producer_property: "Προσθήκη ιδιοκτησίας παραγωγού"
add_producer_property: "Προσθήκη ιδιότητας παραγωγού"
in_progress: "Σε εξέλιξη"
started_at: "Ξεκίνησε στις"
queued: "Ουρά"
@@ -2832,7 +2832,7 @@ el:
spree_admin_enterprises_create_new_product: "ΔΗΜΙΟΥΡΓΗΣΤΕ ΝΕΟ ΠΡΟDΟΝ"
spree_admin_single_enterprise_alert_mail_confirmation: "Παρακαλώ επιβεβαιώστε τη διεύθυνση email για"
spree_admin_single_enterprise_alert_mail_sent: "Έχουμε στείλει ένα email στο"
spree_admin_overview_action_required: "Απαιτείται δράση"
spree_admin_overview_action_required: "Απαιτείται Ενέργεια"
spree_admin_overview_check_your_inbox: "Ελέγξτε τα εισερχόμενά σας για περισσότερες οδηγίες. Ευχαριστώ!"
spree_admin_unit_value: Αξία μονάδας
spree_admin_unit_description: Περιγραφή μονάδας
@@ -2854,7 +2854,7 @@ el:
spree_user_enterprise_limit_error: "^%{email} δεν επιτρέπεται να κατέχει άλλες επιχειρήσεις (το όριο είναι %{enterprise_limit})."
spree_variant_product_error: πρέπει να έχει τουλάχιστον μία παραλλαγή
your_profil_live: "Προφίλ καταστήματος"
see: "ΕΜΦΑΝΙΣΗ"
see: "Εμφάνιση"
live: " "
manage: "Διαχείριση"
resend: "Ξαναστείλτε"
@@ -2865,7 +2865,7 @@ el:
edit_profile_details: "Επεξεργασία στοιχείων προφίλ"
edit_profile_details_etc: "Αλλάξτε την περιγραφή του καταστήματός σας, εικόνες κ.λ.π."
order_cycle: "Κύκλος Παραγγελειών"
enterprise_relationships: "Δικαιώματα επιχείρησης"
enterprise_relationships: "Άδειες επιχείρησης"
first_name_begins_with: "Το όνομα αρχίζει με"
last_name_begins_with: "Το επώνυμο αρχίζει με"
shipping_method: "Μέθοδος αποστολής"
@@ -3114,7 +3114,7 @@ el:
payment_method_not_supported: "Αυτός ο τρόπος πληρωμής δεν υποστηρίζεται. Παρακαλώ επιλέξτε ένα άλλο."
payment_updated: "Η πληρωμή ενημερώθηκε"
cannot_perform_operation: "Δεν ήταν δυνατή η ενημέρωση της πληρωμής"
action_required: "Απαιτείται δράση"
action_required: "Απαιτείται Ενέργεια"
tag_rules: "Κανόνες ετικετών"
enterprise_fee_whole_order: Ολόκληρη παραγγελία
enterprise_fee_by_name: "%{name} κρατήσεις απο %{role} %{enterprise_name}"
@@ -3458,6 +3458,7 @@ el:
add_to_cart: "Προσθήκη"
in_cart: "στο καλάθι"
quantity_in_cart: "%{quantity} στο καλάθι"
remaining_in_stock: "Έχουν απομείνει %{quantity}"
bulk_buy_modal:
min_quantity: "Ελάχιστη ποσότητα"
max_quantity: "Μέγιστη ποσότητα"
@@ -3648,7 +3649,7 @@ el:
formats:
csv:
header:
fee_type: "Κατηγορίες αμοιβών"
fee_type: "Κατηγορίες τελών"
enterprise_name: "Ιδιοκτήτης Επιχειρήσεων"
fee_name: "Όνομα τέλους"
customer_name: "Πελάτης"
@@ -3658,7 +3659,7 @@ el:
total_amount: "$ $ SUM"
html:
header:
fee_type: "Κατηγορίες αμοιβών"
fee_type: "Κατηγορίες τελών"
enterprise_name: "Ιδιοκτήτης Επιχειρήσεων"
fee_name: "Όνομα τέλους"
customer_name: "Πελάτης"
@@ -3767,7 +3768,7 @@ el:
count_on_hand: "Μετρήστε στο χέρι"
quantity: "Ποσότητα"
on_demand: "Κατά παραγγελία"
on_hand: "Στο χέρι"
on_hand: "Διαθέσιμο απόθεμα"
package_from: "πακέτο από"
item_description: "περιγραφή αντικειμένου"
price: "Τιμή"
@@ -3861,7 +3862,7 @@ el:
iso_name: "Όνομα ISO"
states_required: "Απαιτούνται κράτη"
editing_country: "Χώρα επεξεργασίας"
states: "Κρατών"
states: "Γεωγραφικά διαμερίσματα"
abbreviation: "Συντομογραφία"
new_state: "Νέα Πολιτεία"
payment_methods: "τρόποι πληρωμής"
@@ -3902,7 +3903,7 @@ el:
new_image: "Νέα εικόνα"
filename: "Ονομα αρχείου"
alt_text: "Εναλλακτικό Κείμενο"
thumbnail: "Ονυξ του αντίχειρος"
thumbnail: "Μικρογραφία (Thumnail) "
back_to_images_list: "Επιστροφή στη λίστα εικόνων"
email: ΗΛΕΚΤΡΟΝΙΚΗ ΔΙΕΥΘΥΝΣΗ
account_updated: "Ο λογαριασμός ενημερώθηκε!"
@@ -4002,17 +4003,17 @@ el:
properties:
index:
properties: "Ιδιότητες"
new_property: "Νέα ιδιοκτησία"
new_property: "Νέα ιδιότητα"
name: "Όνομα"
presentation: αρουσίαση"
presentation: εριγραφή"
new:
new_property: "Νέα ιδιοκτησία"
new_property: "Νέα ιδιότητα"
edit:
editing_property: "Επεξεργασία ιδιοκτησίας"
editing_property: "Επεξεργασία ιδιότητας"
back_to_properties_list: "Επιστροφή στη λίστα ιδιοτήτων"
form:
name: "Όνομα"
presentation: αρουσίαση"
presentation: εριγραφή"
return_authorizations:
index:
new_return_authorization: "Νέα εξουσιοδότηση επιστροφής"
@@ -4244,7 +4245,7 @@ el:
price: "Τιμή"
unit_price: "Τιμή Μονάδας"
unit_price_legend: "Υπολογίζεται με βάση την τιμή του προϊόντος"
on_hand: "Στο χέρι"
on_hand: "Διαθέσιμο απόθεμα"
on_demand: "Κατά παραγγελία"
product_description: "περιγραφή προϊόντος"
image: "Εικόνα"
@@ -4274,7 +4275,7 @@ el:
search_for_categories: "Αναζήτηση κατηγοριών"
group_buy_form:
group_buy: "Ομαδική αγορά;"
bulk_unit_size: Μέγεθος μονάδας χύδην
bulk_unit_size: Μέγεθος χονδρικής μονάδας
display_as:
display_as: Εμφάνιση ως
clone:

View File

@@ -4660,7 +4660,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
form:
disabled: "Disabled?"
email: "Email"
roles: "Roles"
admin: "Super admin?"
enterprise_limit: "Enterprise Limit"
confirm_password: "Confirm Password"
password: "Password"

View File

@@ -3753,9 +3753,39 @@ en_CA:
sack:
one: "sack"
other: "sacks"
bucket:
one: "bucket"
other: "buckets"
pail:
one: pail
other: pails
stem:
one: "stem"
other: "stems"
plug:
one: "plug"
other: "plugs"
plant:
one: "plant"
other: "plants"
bundle:
one: "bundle"
other: "bundles"
bulb:
one: "bulb"
other: "bulbs"
root:
one: "root"
other: "roots"
tuber:
one: "tuber"
other: "tubers"
corm:
one: "corm"
other: "corms"
crate:
one: "crate"
other: "crates"
producers:
signup:
start_free_profile: "Start with a free profile, and expand when you're ready!"

View File

@@ -3791,6 +3791,10 @@ fr_CA:
one: "sachet"
many: "sachets"
other: "sachets"
bucket:
one: "bucket"
many: "buckets"
other: "buckets"
bundle:
one: "botte"
many: "bottes"

View File

@@ -60,7 +60,6 @@ def create_admin_user
ValidEmail2::Address.define_method(:valid_mx?) { true }
if admin.save
admin.spree_roles << Spree::Role.admin
say "New admin user persisted!"
else
say "There was some problems with persisting new admin user:"
@@ -81,6 +80,7 @@ def read_user_attributes
end
{
admin: true,
password:,
password_confirmation: password,
email:,

View File

@@ -1,22 +1,25 @@
# frozen_string_literal: true
unless Spree::Zone.find_by(name: "EU_VAT")
eu_vat = Spree::Zone.create!(name: "EU_VAT",
description: "Countries that make up the EU VAT zone.")
eu_vat = Spree::Zone.new(
name: "EU_VAT", description: "Countries that make up the EU VAT zone."
)
["Poland", "Finland", "Portugal", "Romania", "Germany", "France",
"Slovakia", "Hungary", "Slovenia", "Ireland", "Austria", "Spain",
"Italy", "Belgium", "Sweden", "Latvia", "Bulgaria", "United Kingdom",
"Lithuania", "Cyprus", "Luxembourg", "Malta", "Denmark", "Netherlands",
"Estonia"].each do |name|
eu_vat.zone_members.create!(zoneable: Spree::Country.find_by!(name:))
eu_vat.zone_members.new(zoneable: Spree::Country.find_by!(name:))
end
eu_vat.save!
end
unless Spree::Zone.find_by(name: "North America")
north_america = Spree::Zone.create!(name: "North America", description: "USA + Canada")
north_america = Spree::Zone.new(name: "North America", description: "USA + Canada")
["United States", "Canada"].each do |name|
north_america.zone_members.create!(zoneable: Spree::Country.find_by!(name:))
north_america.zone_members.new(zoneable: Spree::Country.find_by!(name:))
end
north_america.save!
end

View File

@@ -0,0 +1,8 @@
# frozen_string_literal: true
# We'll replace our only role "admin" with a simple flag.
class AddAdminToSpreeUsers < ActiveRecord::Migration[7.0]
def change
add_column :spree_users, :admin, :boolean, default: false, null: false
end
end

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
class CopyAdminAttributeToUsers < ActiveRecord::Migration[7.0]
def up
execute <<~SQL.squish
UPDATE spree_users SET admin = true WHERE id IN (
SELECT user_id FROM spree_roles_users WHERE role_id IN (
SELECT id FROM spree_roles WHERE name = 'admin'
)
)
SQL
end
end

View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
class DeleteDefaultCountryIdPreference < ActiveRecord::Migration[7.0]
def up
execute <<~SQL.squish
DELETE FROM spree_preferences
WHERE key = '/spree/app_configuration/default_country_id '
SQL
end
end

View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2025_01_13_055412) do
ActiveRecord::Schema[7.0].define(version: 2025_01_28_031518) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "plpgsql"
@@ -945,6 +945,7 @@ ActiveRecord::Schema[7.0].define(version: 2025_01_13_055412) do
t.string "provider"
t.string "uid"
t.datetime "terms_of_service_accepted_at"
t.boolean "admin", default: false, null: false
t.index ["confirmation_token"], name: "index_spree_users_on_confirmation_token", unique: true
t.index ["email"], name: "email_idx_unique", unique: true
t.index ["persistence_token"], name: "index_users_on_persistence_token"

View File

@@ -16,8 +16,10 @@ module Addressing
end
def zone
zone = Spree::Zone.find_or_create_by!(name: ENV.fetch('CHECKOUT_ZONE'))
zone.members.create!(zoneable: country) unless zone.zoneables.include?(country)
zone = Spree::Zone.find_or_create_by(name: ENV.fetch('CHECKOUT_ZONE'))
zone.members << Spree::ZoneMember.create(zoneable: country) unless
zone.zoneables.include?(country)
zone.save!
zone
end

View File

@@ -31,7 +31,7 @@
"stimulus": "^3.2.2",
"stimulus-flatpickr": "^1.4.0",
"stimulus_reflex": "3.5.3",
"tom-select": "^2.4.1",
"tom-select": "^2.4.2",
"trix": "^2.1.12",
"turbo_power": "^0.7.0",
"webpack": "~4"

View File

@@ -234,12 +234,10 @@ RSpec.configure do |config|
end
end
default_country_id = DefaultCountry.id
# Ensure we start with consistent config settings
config.before(:each) do
reset_spree_preferences do |spree_config|
# These are all settings that differ from Spree's defaults
spree_config.default_country_id = default_country_id
spree_config.shipping_instructions = true
end
CurrentConfig.clear_all

View File

@@ -431,11 +431,7 @@ module Admin
describe "notifying producers" do
let(:user) { create(:user) }
let(:admin_user) do
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin')
user
end
let(:admin_user) { create(:admin_user) }
let(:order_cycle) { create(:simple_order_cycle) }
before do

View File

@@ -235,8 +235,6 @@ module Spree
let(:user) do
new_user = create(:user, email: 'enterprise@hub.com', password: 'blahblah',
password_confirmation: 'blahblah', )
# for some reason unbeknown to me, this new user gets admin permissions by default.
new_user.spree_roles = []
new_user.enterprise_roles.build(enterprise:).save
new_user.save
new_user

View File

@@ -3,37 +3,39 @@
require 'spec_helper'
RSpec.describe Spree::Admin::UsersController do
context '#authorize_admin' do
describe '#authorize_admin' do
let(:user) { create(:user) }
let(:test_user) { create(:user) }
before do
allow(controller).to receive_messages spree_current_user: user
allow(Spree::User).to receive(:find).with(test_user.id.to_s).and_return(test_user)
user.spree_roles.clear
end
it 'should grant access to users with an admin role' do
user.spree_roles << Spree::Role.find_or_create_by(name: 'admin')
spree_post :index
expect(response).to render_template :index
end
context "as a super admin" do
let(:user) { create(:admin_user) }
let(:test_user) { create(:user) }
it "allows admins to update a user's show api key view" do
user.spree_roles << Spree::Role.find_or_create_by(name: 'admin')
spree_put :update, id: test_user.id, user: { show_api_key_view: true }
expect(response).to redirect_to spree.edit_admin_user_path(test_user)
end
before do
allow(Spree::User).to receive(:find).with(test_user.id.to_s).and_return(test_user)
end
it "re-renders the edit form if error" do
user.spree_roles << Spree::Role.find_or_create_by(name: 'admin')
spree_put :update, id: test_user.id, user: { password: "blah", password_confirmation: "" }
it 'should grant access to users with an admin role' do
spree_post :index
expect(response).to render_template :index
end
expect(response).to render_template :edit
it "allows admins to update a user's show api key view" do
spree_put :update, id: test_user.id, user: { show_api_key_view: true }
expect(response).to redirect_to spree.edit_admin_user_path(test_user)
end
it "re-renders the edit form if error" do
spree_put :update, id: test_user.id, user: { password: "blah", password_confirmation: "" }
expect(response).to render_template :edit
end
end
it 'should deny access to users without an admin role' do
allow(user).to receive_messages admin?: false
spree_post :index
expect(response).to redirect_to('/unauthorized')
end

View File

@@ -35,7 +35,7 @@ FactoryBot.define do
end
factory :admin_user do
spree_roles { [Spree::Role.find_or_create_by!(name: 'admin')] }
admin { true }
end
factory :oidc_user do

View File

@@ -1,21 +1,18 @@
# frozen_string_literal: true
FactoryBot.define do
factory :zone, class: Spree::Zone do
factory :zone, aliases: [:zone_with_member], class: Spree::Zone do
sequence(:name) { |n| "#{generate(:random_string)}#{n}" }
description { generate(:random_string) }
end
default_tax { true }
zone_members { [Spree::ZoneMember.new(zoneable: member)] }
factory :zone_with_member, parent: :zone do
transient do
member { Spree::Country.find_by(name: "Australia") }
end
default_tax { true }
zone_members { [Spree::ZoneMember.new(zoneable: member)] }
end
factory :zone_with_state_member, parent: :zone_with_member do
factory :zone_with_state_member, parent: :zone do
member { Spree::State.find_by(name: "Victoria") }
end
end

View File

@@ -26,9 +26,8 @@ RSpec.describe Spree::BaseHelper do
context "with a checkout zone defined" do
context "checkout zone is of type country" do
before do
@country_zone = create(:zone, name: "CountryZone")
@country_zone.members.create(zoneable: country)
allow(ENV).to receive(:fetch).and_return(@country_zone.name)
country_zone = create(:zone, name: "CountryZone", member: country)
allow(ENV).to receive(:fetch).and_return(country_zone.name)
end
it "return only the countries defined by the checkout zone" do

View File

@@ -7,11 +7,7 @@ module Reporting
module Customers
RSpec.describe Base do
context "as a site admin" do
let(:user) do
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin')
user
end
let(:user) { create(:admin_user) }
subject { Base.new user, {} }
describe "addresses report" do
@@ -198,12 +194,7 @@ module Reporting
end
context "as an enterprise user" do
let(:user) do
user = create(:user)
user.spree_roles = []
user.save!
user
end
let(:user) { create(:user) }
subject { Base.new user, {} }

View File

@@ -10,11 +10,7 @@ module Reporting
subject { Base.new(user, params) }
let(:params) { {} }
let(:user) do
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by!(name: "admin")
user
end
let(:user) { create(:admin_user) }
describe "fetching orders" do
it 'calls the OutstandingBalanceQuery query object' do

View File

@@ -7,11 +7,7 @@ module Reporting
module ProductsAndInventory
RSpec.describe Base do
context "As a site admin" do
let(:user) do
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin')
user
end
let(:user) { create(:admin_user) }
subject do
Base.new user, {}
end
@@ -72,7 +68,6 @@ module Reporting
let(:enterprise_user) do
user = create(:user)
user.enterprise_roles.create(enterprise: supplier)
user.spree_roles = []
user.save!
user
end
@@ -259,11 +254,7 @@ module Reporting
end
RSpec.describe AllProducts do
let(:user) do
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin')
user
end
let(:user) { create(:admin_user) }
let(:report) do
AllProducts.new user, { fields_to_hide: [] }
end

View File

@@ -77,7 +77,6 @@ RSpec.describe EnterpriseGroup do
it "finds a user's enterprise groups" do
user = create(:user)
user.spree_roles = []
eg1 = create(:enterprise_group, owner: user)
eg2 = create(:enterprise_group)

View File

@@ -651,7 +651,6 @@ RSpec.describe Enterprise do
describe "managed_by" do
it "shows only enterprises for given user" do
user = create(:user)
user.spree_roles = []
e1 = create(:enterprise)
e2 = create(:enterprise)
e1.enterprise_roles.build(user:).save

View File

@@ -107,11 +107,7 @@ RSpec.describe Exchange do
let(:oc) { create(:simple_order_cycle, coordinator:) }
describe "finding exchanges managed by a particular user" do
let(:user) do
user = create(:user)
user.spree_roles = []
user
end
let(:user) { create(:user) }
before { Exchange.destroy_all }

View File

@@ -61,9 +61,10 @@ RSpec.describe Invoice::DataPresenter do
expect(presenter.display_line_item_tax_rate(taxable_line_item)).to eq "15.0%, 20.0%"
end
context "one of the tax rate is appliable to a different tax zone" do
context "one of the tax rate is applicable to a different tax zone" do
before do
order.line_items.last.tax_category.tax_rates.last.update!(zone: create(:zone))
new_zone = create(:zone, default_tax: false, member: Spree::Country.last)
order.line_items.last.tax_category.tax_rates.last.update!(zone: new_zone)
order.create_tax_charge!
Orders::GenerateInvoiceService.new(order).generate_or_update_latest_invoice
end

View File

@@ -62,8 +62,7 @@ RSpec.describe OrderCycle do
it "finds order cycles accessible by a user" do
e1 = create(:enterprise, is_primary_producer: true, sells: "any")
e2 = create(:enterprise, is_primary_producer: true, sells: "any")
user = create(:user, enterprises: [e2], spree_roles: [])
user.spree_roles = []
user = create(:user, enterprises: [e2])
oc_coordinated = create(:simple_order_cycle, coordinator: e2)
oc_sent = create(:simple_order_cycle, suppliers: [e2])

View File

@@ -9,14 +9,6 @@ RSpec.describe Spree::Ability do
let(:subject) { Spree::Ability.new(user) }
let(:token) { nil }
before do
user.spree_roles.clear
end
after(:each) {
user.spree_roles = []
}
context 'for general resource' do
let(:resource) { Object.new }
@@ -42,8 +34,10 @@ RSpec.describe Spree::Ability do
let(:fakedispatch_ability) { Spree::Ability.new(fakedispatch_user) }
context 'with admin user' do
let(:user) { create(:admin_user) }
it 'should be able to admin' do
user.spree_roles << Spree::Role.find_or_create_by(name: 'admin')
user.update!(admin: true)
expect(subject).to be_able_to :admin, resource
expect(subject).to be_able_to :index, resource_order
expect(subject).to be_able_to :show, resource_product
@@ -303,7 +297,6 @@ RSpec.describe Spree::Ability do
# create supplier_enterprise1 user without full admin access
let(:user) do
user = create(:user)
user.spree_roles = []
s1.enterprise_roles.build(user:).save
user
end
@@ -487,7 +480,6 @@ RSpec.describe Spree::Ability do
context "when is a distributor enterprise user" do
let(:user) do
user = create(:user)
user.spree_roles = []
d1.enterprise_roles.build(user:).save
user
end
@@ -699,7 +691,6 @@ RSpec.describe Spree::Ability do
context 'Order Cycle co-ordinator, distributor enterprise manager' do
let(:user) do
user = create(:user)
user.spree_roles = []
d1.enterprise_roles.build(user:).save
user
end
@@ -738,7 +729,6 @@ RSpec.describe Spree::Ability do
context 'enterprise manager' do
let(:user) do
user = create(:user)
user.spree_roles = []
s1.enterprise_roles.build(user:).save
user
end
@@ -797,7 +787,7 @@ RSpec.describe Spree::Ability do
let(:manage_actions) { [:admin, :index, :read, :update, :bulk_update, :bulk_reset] }
describe "when admin" do
before { user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin') }
let(:user) { create(:admin_user) }
it "should have permission" do
is_expected.to have_ability(manage_actions, for: variant_override)

View File

@@ -508,7 +508,6 @@ module Spree
it "shows only products for given user" do
user = create(:user)
user.spree_roles = []
e1.enterprise_roles.build(user:).save
product = Product.managed_by user

View File

@@ -4,7 +4,7 @@ require 'spec_helper'
module Spree
RSpec.describe TaxRate do
describe "#match" do
describe ".match" do
let!(:zone) { create(:zone_with_member) }
let!(:order) { create(:order, distributor: hub, bill_address: create(:address)) }
let!(:tax_rate) {
@@ -44,7 +44,7 @@ module Spree
let(:tax_category) { create(:tax_category) }
let(:calculator) { ::Calculator::FlatRate.new }
it "should return an empty array when tax_zone is nil" do
it "returns an empty array when tax_zone is nil" do
allow(order).to receive(:tax_zone) { nil }
expect(Spree::TaxRate.match(order)).to eq []
end
@@ -55,79 +55,70 @@ module Spree
end
context "when there is no default tax zone" do
before do
@zone = create(:zone, name: "Country Zone", default_tax: false, zone_members: [])
@zone.zone_members.create(zoneable: country)
end
let(:zone) { create( :zone, name: "Country Zone", default_tax: false, member: country) }
it "should return an empty array" do
allow(order).to receive(:tax_zone) { @zone }
it "returns an empty array" do
allow(order).to receive(:tax_zone).and_return(zone)
expect(Spree::TaxRate.match(order)).to eq []
end
it "should return the rate that matches the rate zone" do
it "returns the rate that matches the rate zone" do
rate = Spree::TaxRate.create(
amount: 1,
zone: @zone,
zone:,
tax_category:,
calculator:
)
allow(order).to receive(:tax_zone) { @zone }
allow(order).to receive(:tax_zone).and_return(zone)
expect(Spree::TaxRate.match(order)).to eq [rate]
end
it "should return all rates that match the rate zone" do
it "returns all rates that match the rate zone" do
rate1 = Spree::TaxRate.create(
amount: 1,
zone: @zone,
zone:,
tax_category:,
calculator:
)
rate2 = Spree::TaxRate.create(
amount: 2,
zone: @zone,
zone:,
tax_category:,
calculator: ::Calculator::FlatRate.new
)
allow(order).to receive(:tax_zone) { @zone }
allow(order).to receive(:tax_zone).and_return(zone)
expect(Spree::TaxRate.match(order)).to eq [rate1, rate2]
end
context "when the tax_zone is contained within a rate zone" do
before do
sub_zone = create(:zone, name: "State Zone", zone_members: [])
sub_zone.zone_members.create(zoneable: create(:state, country:))
allow(order).to receive(:tax_zone) { sub_zone }
let(:sub_zone) { create(:zone, name: "State Zone", member: create(:state, country:)) }
@rate = Spree::TaxRate.create(
it "returns the rate zone" do
allow(order).to receive(:tax_zone).and_return(sub_zone)
rate = Spree::TaxRate.create(
amount: 1,
zone: @zone,
zone:,
tax_category:,
calculator:
)
end
it "should return the rate zone" do
expect(Spree::TaxRate.match(order)).to eq [@rate]
expect(Spree::TaxRate.match(order)).to eq [rate]
end
end
end
context "when there is a default tax zone" do
before do
@zone = create(:zone, name: "Country Zone", default_tax: true, zone_members: [])
@zone.zone_members.create(zoneable: country)
end
let(:zone) { create(:zone, name: "Country Zone", default_tax: true, member: country) }
let(:included_in_price) { false }
let!(:rate) do
Spree::TaxRate.create(amount: 1,
zone: @zone,
zone:,
tax_category:,
calculator:,
included_in_price:)
@@ -137,7 +128,7 @@ module Spree
context "when the order has the same tax zone" do
before do
allow(order).to receive(:tax_zone) { @zone }
allow(order).to receive(:tax_zone) { zone }
allow(order).to receive(:billing_address) { tax_address }
end
@@ -149,12 +140,13 @@ module Spree
context "when the tax is a VAT" do
let(:included_in_price) { true }
it { is_expected.to eq [rate] }
end
end
context "when the order has a different tax zone" do
let(:other_zone) { create(:zone, name: "Other Zone") }
let(:other_zone) { create(:zone, name: "Other Zone", default_tax: false) }
before do
allow(order).to receive(:tax_zone) { other_zone }
@@ -200,47 +192,7 @@ module Spree
end
end
context "adjust" do
let(:order) { create(:order) }
let(:tax_category_1) { build_stubbed(:tax_category) }
let(:tax_category_2) { build_stubbed(:tax_category) }
let(:rate_1) { build_stubbed(:tax_rate, tax_category: tax_category_1) }
let(:rate_2) { build_stubbed(:tax_rate, tax_category: tax_category_2) }
let(:line_items) { [build_stubbed(:line_item)] }
context "with line items" do
let(:line_item) { build_stubbed(:line_item, tax_category: tax_category_1) }
let(:line_items) { [line_item] }
before do
allow(Spree::TaxRate).to receive(:match) { [rate_1, rate_2] }
end
it "should apply adjustments for two tax rates to the order" do
expect(rate_1).to receive(:adjust)
expect(rate_2).not_to receive(:adjust)
Spree::TaxRate.adjust(order, line_items)
end
end
context "with shipments" do
let(:shipment) { build_stubbed(:shipment, order:) }
let(:shipments) { [shipment] }
before do
allow(shipment).to receive(:tax_category) { tax_category_1 }
allow(Spree::TaxRate).to receive(:match) { [rate_1, rate_2] }
end
it "should apply adjustments for two tax rates to the order" do
expect(rate_1).to receive(:adjust)
expect(rate_2).not_to receive(:adjust)
Spree::TaxRate.adjust(order, shipments)
end
end
end
context "default" do
describe ".default" do
let(:tax_category) { create(:tax_category) }
let(:country) { create(:country) }
let(:calculator) { ::Calculator::FlatRate.new }
@@ -248,7 +200,7 @@ module Spree
context "when there is no default tax_category" do
before { tax_category.is_default = false }
it "should return 0" do
it "returns 0" do
expect(Spree::TaxRate.default).to eq 0
end
end
@@ -259,30 +211,29 @@ module Spree
context "when the default category has tax rates in the default tax zone" do
before(:each) do
allow(DefaultCountry).to receive(:id) { country.id }
@zone = create(:zone, name: "Country Zone", default_tax: true)
@zone.zone_members.create(zoneable: country)
zone = create(:zone, name: "Country Zone", default_tax: true, member: country)
rate = Spree::TaxRate.create(
amount: 1,
zone: @zone,
zone:,
tax_category:,
calculator:
)
end
it "should return the correct tax_rate" do
it "returns the correct tax_rate" do
expect(Spree::TaxRate.default.to_f).to eq 1.0
end
end
context "when the default category has no tax rates in the default tax zone" do
it "should return 0" do
it "returns 0" do
expect(Spree::TaxRate.default).to eq 0
end
end
end
end
describe "#adjust" do
describe ".adjust" do
let!(:country) { create(:country, name: "Default Country") }
let!(:state) { create(:state, name: "Default State", country:) }
let!(:zone) { create(:zone_with_member, default_tax: true, member: country ) }
@@ -312,12 +263,12 @@ module Spree
context "not taxable line item " do
let!(:line_item) { order.contents.add(nontaxable, 1) }
it "should not create a tax adjustment" do
it "does not create a tax adjustment" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.tax.charge.count).to eq 0
end
it "should not create a refund" do
it "does not create a refund" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.credit.count).to eq 0
end
@@ -331,14 +282,26 @@ module Spree
rate2.update_column(:included_in_price, true)
end
it "applies adjustments for the matching tax rates to the order" do
line_item = build_stubbed(:line_item, tax_category: category)
rate3 = create(:tax_rate, amount: 0.05, zone:)
allow(Spree::TaxRate).to receive(:match) { [rate1, rate3] }
expect(rate1).to receive(:adjust)
expect(rate3).not_to receive(:adjust)
Spree::TaxRate.adjust(order, [line_item])
end
context "when price includes tax" do
context "when zone is contained by default tax zone" do
it "should create two adjustments, one for each tax rate" do
it "creates two adjustments, one for each tax rate" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.count).to eq 2
end
it "should not create a tax refund" do
it "does not create a tax refund" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.credit.count).to eq 0
end
@@ -347,16 +310,17 @@ module Spree
context "when order's zone is neither the default zone, or included " \
"in the default zone, but matches the rate's zone" do
before do
# With no zone members, this zone will not contain anything
zone.zone_members.delete_all
# Create a new default zone, so the order's zone won't match this new one
create(:zone_with_member, default_tax: true)
end
it "should create an adjustment" do
it "creates an adjustment" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.charge.count).to eq 2
end
it "should not create a tax refund for each tax rate" do
it "does not create a tax refund for each tax rate" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.credit.count).to eq 0
end
@@ -377,25 +341,15 @@ module Spree
order.all_adjustments.delete_all
end
it "should not create positive adjustments" do
it "does not create positive adjustments" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.charge.count).to eq 0
end
it "should create a tax refund for each tax rate" do
it "creates a tax refund for each tax rate" do
Spree::TaxRate.adjust(order, order.line_items)
expect(line_item.adjustments.credit.count).to eq 2
end
it "notifies bugsnag" do
# there are two tax rate
expect(Bugsnag).to receive(:notify).with(
"Notice: Tax refund should not be possible, please check the default zone and " \
"the tax rate zone configuration"
).twice.and_call_original
Spree::TaxRate.adjust(order, order.line_items)
end
end
end
@@ -409,21 +363,21 @@ module Spree
Spree::TaxRate.adjust(order, order.line_items)
end
it "should not delete adjustments for complete order when taxrate is deleted" do
it "does not delete adjustments for complete order when taxrate is deleted" do
rate1.destroy!
rate2.destroy!
expect(line_item.adjustments.count).to eq 2
end
it "should create adjustments" do
it "creates adjustments" do
expect(line_item.adjustments.count).to eq 2
end
it "should not create a tax refund" do
it "does not create a tax refund" do
expect(line_item.adjustments.credit.count).to eq 0
end
it "should remove adjustments when tax_zone is removed" do
it "removes adjustments when tax_zone is removed" do
expect(line_item.adjustments.count).to eq 2
allow(order).to receive(:tax_zone) { nil }
Spree::TaxRate.adjust(order, order.line_items)
@@ -431,6 +385,22 @@ module Spree
end
end
end
context "with shipments" do
let(:shipment) { build_stubbed(:shipment, order:) }
it "applies adjustments for two tax rates to the order" do
rate3 = create(:tax_rate, amount: 0.05, zone:)
allow(shipment).to receive(:tax_category) { category }
allow(Spree::TaxRate).to receive(:match) { [rate1, rate3] }
expect(rate1).to receive(:adjust)
expect(rate3).not_to receive(:adjust)
Spree::TaxRate.adjust(order, [shipment])
end
end
end
end
end

View File

@@ -209,11 +209,11 @@ RSpec.describe Spree::User do
end
describe '#admin?' do
it 'returns true when the user has an admin spree role' do
it 'returns true when the user has an admin role' do
expect(create(:admin_user).admin?).to be_truthy
end
it 'returns false when the user does not have an admin spree role' do
it 'returns false when the user does not have an admin role' do
expect(create(:user).admin?).to eq(false)
end
end

View File

@@ -3,7 +3,13 @@
require 'spec_helper'
RSpec.describe Spree::Zone do
context "#match" do
describe "validations" do
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_uniqueness_of(:name) }
it { is_expected.to validate_presence_of(:zone_members) }
end
describe "#match" do
let(:country_zone) { create(:zone, name: 'CountryZone') }
let(:country) do
country = create(:country)
@@ -63,14 +69,12 @@ RSpec.describe Spree::Zone do
end
end
context "#countries" do
describe "#countries" do
let(:state) { create(:state) }
let(:country) { state.country }
context "when zone consists of countries" do
let(:country_zone) { create(:zone, name: 'CountryZone') }
before { country_zone.members.create(zoneable: country) }
let(:country_zone) { create(:zone, name: 'CountryZone', member: country) }
it 'should return a list of countries' do
expect(country_zone.countries).to eq [country]
@@ -78,17 +82,15 @@ RSpec.describe Spree::Zone do
end
context "when zone consists of states" do
let(:state_zone) { create(:zone, name: 'StateZone') }
before { state_zone.members.create(zoneable: state) }
let(:state_zone) { create(:zone, name: 'StateZone', member: state) }
it 'should return a list of countries' do
expect(state_zone.countries).to eq [state.country]
expect(state_zone.countries).to eq [country]
end
end
end
context "#contains_address?" do
describe "#contains_address?" do
let(:state) { create(:state) }
let(:country) { state.country }
let(:address) { create(:address, country:, state:) }
@@ -112,13 +114,13 @@ RSpec.describe Spree::Zone do
end
end
context ".default_tax" do
describe ".default_tax" do
context "when there is a default tax zone specified" do
before { @foo_zone = create(:zone, name: 'whatever', default_tax: true) }
let!(:default_zone) { create(:zone, name: 'whatever', default_tax: true) }
it "should be the correct zone" do
foo_zone = create(:zone, name: 'foo')
expect(Spree::Zone.default_tax).to eq @foo_zone
create(:zone, name: 'foo', default_tax: false)
expect(Spree::Zone.default_tax).to eq default_zone
end
end
@@ -129,135 +131,122 @@ RSpec.describe Spree::Zone do
end
end
context "#contains?" do
let(:country1) { create(:country) }
let(:country2) { create(:country) }
let(:country3) { create(:country) }
before do
@source = create(:zone, name: 'source', zone_members: [])
@target = create(:zone, name: 'target', zone_members: [])
end
context "when the target has no members" do
before { @source.members.create(zoneable: country1) }
it "should be false" do
expect(@source.contains?(@target)).to be_falsy
end
end
context "when the source has no members" do
before { @target.members.create(zoneable: country1) }
it "should be false" do
expect(@source.contains?(@target)).to be_falsy
end
end
describe "#contains?" do
let(:country_member1) { Spree::ZoneMember.create(zoneable: create(:country)) }
let(:country_member2) { Spree::ZoneMember.create(zoneable: create(:country)) }
let(:country_member3) { Spree::ZoneMember.create(zoneable: create(:country)) }
let(:source) { create(:zone, name: 'source') }
let(:target) { create(:zone, name: 'target') }
context "when both zones are the same zone" do
before do
@source.members.create(zoneable: country1)
@target = @source
source.zone_members = [country_member1]
end
it "should be true" do
expect(@source.contains?(@target)).to be_truthy
target = source
expect(source.contains?(target)).to be_truthy
end
end
context "when both zones are of the same type" do
before do
@source.members.create(zoneable: country1)
@source.members.create(zoneable: country2)
source.zone_members = [country_member1, country_member2]
end
context "when all members are included in the zone we check against" do
before do
@target.members.create(zoneable: country1)
@target.members.create(zoneable: country2)
target.zone_members = [country_member1, country_member2]
end
it "should be true" do
expect(@source.contains?(@target)).to be_truthy
expect(source.contains?(target)).to be_truthy
end
end
context "when some members are included in the zone we check against" do
before do
@target.members.create(zoneable: country1)
@target.members.create(zoneable: country2)
@target.members.create(zoneable: create(:country))
target.zone_members = [
country_member1, country_member2, Spree::ZoneMember.create(zoneable: create(:country))
]
end
it "should be false" do
expect(@source.contains?(@target)).to be_falsy
expect(source.contains?(target)).to be_falsy
end
end
context "when none of the members are included in the zone we check against" do
before do
@target.members.create(zoneable: create(:country))
@target.members.create(zoneable: create(:country))
target.zone_members = [
Spree::ZoneMember.create(zoneable: create(:country)),
Spree::ZoneMember.create(zoneable: create(:country))
]
end
it "should be false" do
expect(@source.contains?(@target)).to be_falsy
expect(source.contains?(target)).to be_falsy
end
end
end
context "when checking country against state" do
before do
@source.members.create(zoneable: create(:state))
@target.members.create(zoneable: country1)
source.zone_members = [Spree::ZoneMember.create(zoneable: create(:state))]
target.zone_members = [country_member1]
end
it "should be false" do
expect(@source.contains?(@target)).to be_falsy
expect(source.contains?(target)).to be_falsy
end
end
context "when checking state against country" do
before { @source.members.create(zoneable: country1) }
before { source.zone_members = [country_member1] }
context "when all states contained in one of the countries we check against" do
before do
state1 = create(:state, country: country1)
@target.members.create(zoneable: state1)
state1 = create(:state, country: country_member1.zoneable)
target.zone_members = [Spree::ZoneMember.create(zoneable: state1)]
end
it "should be true" do
expect(@source.contains?(@target)).to be_truthy
expect(source.contains?(target)).to be_truthy
end
end
context "when some states contained in one of the countries we check against" do
before do
state1 = create(:state, country: country1)
@target.members.create(zoneable: state1)
@target.members.create(zoneable: create(:state, country: country2))
state1 = create(:state, country: country_member1.zoneable)
state2 = create(:state, country: country_member2.zoneable)
target.zone_members = [
Spree::ZoneMember.create(zoneable: state1),
Spree::ZoneMember.create(zoneable: state2)
]
end
it "should be false" do
expect(@source.contains?(@target)).to be_falsy
expect(source.contains?(target)).to be_falsy
end
end
context "when none of the states contained in any of the countries we check against" do
before do
@target.members.create(zoneable: create(:state, country: country2))
@target.members.create(zoneable: create(:state, country: country2))
target.zone_members = [
Spree::ZoneMember.create(zoneable: create(:state, country: country_member2.zoneable)),
Spree::ZoneMember.create(zoneable: create(:state, country: country_member2.zoneable))
]
end
it "should be false" do
expect(@source.contains?(@target)).to be_falsy
expect(source.contains?(target)).to be_falsy
end
end
end
end
context "#save" do
describe "#save" do
context "when default_tax is true" do
it "should clear previous default tax zone" do
zone1 = create(:zone, name: 'foo', default_tax: true)
@@ -268,37 +257,32 @@ RSpec.describe Spree::Zone do
context "when a zone member country is added to an existing zone consisting of state members" do
it "should remove existing state members" do
zone = create(:zone, name: 'foo', zone_members: [])
state = create(:state)
zone = create(:zone, name: 'foo', member: state)
country = create(:country)
zone.members.create(zoneable: state)
country_member = zone.members.create(zoneable: country)
zone.save
expect(zone.reload.members).to eq [country_member]
end
end
end
context "#kind" do
describe "#kind" do
context "when the zone consists of country zone members" do
before do
@zone = create(:zone, name: 'country', zone_members: [])
@zone.members.create(zoneable: create(:country))
end
let!(:zone) { create(:zone, name: 'country', member: create(:country)) }
it "should return the kind of zone member" do
expect(@zone.kind).to eq "country"
expect(zone.kind).to eq "country"
end
end
context "when the zone consists of state zone members" do
before do
@zone = create(:zone, name: 'state', zone_members: [])
@zone.members.create(zoneable: create(:state))
end
let!(:zone) { create(:zone, name: 'country', member: create(:state)) }
it "should return the kind of zone member" do
expect(@zone.kind).to eq "state"
expect(zone.kind).to eq "state"
end
end
end

View File

@@ -3,11 +3,7 @@
module OpenFoodNetwork
module ControllerHelper
def controller_login_as_admin
@admin_user ||= begin
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin')
user
end
@admin_user ||= create(:admin_user)
allow(controller).to receive_messages(spree_current_user: @admin_user)
end
@@ -15,7 +11,6 @@ module OpenFoodNetwork
def controller_login_as_enterprise_user(enterprises)
@enterprise_user ||= begin
user = create(:user)
user.spree_roles = []
enterprises.each do |enterprise|
enterprise.enterprise_roles.create!(user:)
end

View File

@@ -22,8 +22,3 @@ if Spree::Country.where(name: "France").empty?
Spree::State.create!({ "name" => "Alsace", "abbr" => "Als", :country => country })
Spree::State.create!({ "name" => "Aquitaine", "abbr" => "Aq", :country => country })
end
# Since the country seeding differs from other environments, the default
# country id has to be updated here. This line can be removed as soon as the
# default country id is replaced by something database independent.
Spree::Config.default_country_id = Spree::Country.find_by(name: 'Australia').id

View File

@@ -25,7 +25,7 @@ RSpec.describe '
}
let!(:tax_category_included) { create(:tax_category, name: 'TVA 20%', is_default: true) }
let!(:default_tax_zone) { create(:zone, default_tax: true) }
let!(:default_tax_zone) { create(:zone, default_tax: true, member: Spree::Country.last) }
let!(:tax_rate2) {
create(:tax_rate, name: "TVA 20%", amount: 0.2, zone: default_tax_zone, included_in_price: true,
tax_category: tax_category_included, calculator: Calculator::DefaultTax.new )

View File

@@ -5,7 +5,6 @@ require 'system_helper'
RSpec.describe "Shipping Categories" do
include AuthenticationHelper
include WebHelper
let(:admin_role) { Spree::Role.find_or_create_by!(name: 'admin') }
let(:admin_user) { create(:user) }
context 'user visits shipping categories page' do

View File

@@ -6,8 +6,10 @@ RSpec.describe "Tax Rates" do
include AuthenticationHelper
let!(:calculator) { create(:calculator_per_item, calculable: create(:order)) }
let!(:tax_rate) { create(:tax_rate, name: "IVA", calculator:) }
let!(:zone) { create(:zone, name: "Ilhas") }
let!(:tax_rate) {
create(:tax_rate, name: "IVA", calculator:, zone: create(:zone, default_tax: false))
}
let!(:zone) { create(:zone, name: "Ilhas", default_tax: false) }
let!(:tax_category) { create(:tax_category, name: "Full") }
before do

View File

@@ -6,6 +6,10 @@ RSpec.describe "Zones" do
include AuthenticationHelper
include WebHelper
before do
Spree::Zone.delete_all
end
it "list existing zones" do
login_as_admin
visit spree.edit_admin_general_settings_path
@@ -34,6 +38,11 @@ RSpec.describe "Zones" do
fill_in "zone_name", with: "japan"
fill_in "zone_description", with: "japanese time zone"
choose "Country Based"
click_link "Add country"
find('.select2').find(:xpath, 'option[2]').select_option
click_button "Create"
expect(page).to have_content("successfully created!")

View File

@@ -5,11 +5,9 @@ require 'system_helper'
RSpec.describe 'Multilingual' do
include AuthenticationHelper
include WebHelper
let(:admin_role) { Spree::Role.find_or_create_by!(name: 'admin') }
let(:admin_user) { create(:user) }
let(:admin_user) { create(:admin_user) }
before do
admin_user.spree_roles << admin_role
login_as admin_user
visit spree.admin_dashboard_path
end

View File

@@ -8879,10 +8879,10 @@ toidentifier@1.0.1:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
tom-select@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/tom-select/-/tom-select-2.4.1.tgz#6a0b6df8af3df7b09b22dd965eb75ce4d1c547bc"
integrity sha512-adI8H8+wk8RRzHYLQ3bXSk2Q+FAq/kzAATrcWlJ2fbIrEzb0VkwaXzKHTAlBwSJrhqbPJvhV/0eypFkED/nAug==
tom-select@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/tom-select/-/tom-select-2.4.2.tgz#9764faf6cba51f6571d03a79bb7c1cac1cac7a5a"
integrity sha512-2RWjkL3gMDz9E+u8w+tQy9JWsYq8gaSytEVeugKYDeMus6ZtxT1HttLPnXsfHCnBPlsNubVyj5gtUeN+S+bcpA==
dependencies:
"@orchidjs/sifter" "^1.1.0"
"@orchidjs/unicode-variants" "^1.1.2"