diff --git a/Gemfile.lock b/Gemfile.lock
index 6ca2073502..3a1421aaf4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -598,17 +598,17 @@ GEM
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.10.1)
- rswag (2.3.2)
- rswag-api (= 2.3.2)
- rswag-specs (= 2.3.2)
- rswag-ui (= 2.3.2)
- rswag-api (2.3.2)
+ rswag (2.3.3)
+ rswag-api (= 2.3.3)
+ rswag-specs (= 2.3.3)
+ rswag-ui (= 2.3.3)
+ rswag-api (2.3.3)
railties (>= 3.1, < 7.0)
- rswag-specs (2.3.2)
+ rswag-specs (2.3.3)
activesupport (>= 3.1, < 7.0)
json-schema (~> 2.2)
railties (>= 3.1, < 7.0)
- rswag-ui (2.3.2)
+ rswag-ui (2.3.3)
actionpack (>= 3.1, < 7.0)
railties (>= 3.1, < 7.0)
rubocop (1.9.1)
@@ -672,7 +672,7 @@ GEM
activerecord (>= 4.1)
state_machines-activemodel (>= 0.5.0)
stringex (2.8.5)
- stripe (5.29.0)
+ stripe (5.29.1)
temple (0.8.2)
test-prof (0.11.3)
test-unit (3.4.0)
@@ -682,7 +682,7 @@ GEM
thor (0.20.3)
thread_safe (0.3.6)
tilt (1.4.1)
- timecop (0.9.2)
+ timecop (0.9.4)
tzinfo (1.2.9)
thread_safe (~> 0.1)
uglifier (4.2.0)
diff --git a/app/assets/javascripts/darkswarm/darkswarm.js.coffee b/app/assets/javascripts/darkswarm/darkswarm.js.coffee
index 76ecd388d9..453f05a2c3 100644
--- a/app/assets/javascripts/darkswarm/darkswarm.js.coffee
+++ b/app/assets/javascripts/darkswarm/darkswarm.js.coffee
@@ -13,7 +13,7 @@ window.Darkswarm = angular.module("Darkswarm", [
'angularSlideables'
]).config ($httpProvider, $tooltipProvider, $locationProvider, $anchorScrollProvider) ->
$httpProvider.defaults.headers['common']['X-Requested-With'] = 'XMLHttpRequest'
- $httpProvider.defaults.headers.common.Accept = "application/json, text/javascript, */*"
+ $httpProvider.defaults.headers.common['Accept'] = "application/json, text/javascript, */*"
# We manually handle our scrolling
$anchorScrollProvider.disableAutoScrolling()
diff --git a/app/assets/javascripts/templates/bulk_buy_modal.html.haml b/app/assets/javascripts/templates/bulk_buy_modal.html.haml
index 5e26551419..05868dab77 100644
--- a/app/assets/javascripts/templates/bulk_buy_modal.html.haml
+++ b/app/assets/javascripts/templates/bulk_buy_modal.html.haml
@@ -16,10 +16,7 @@
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(-1)", disabled: "!canAdd(-1)"}}>
-# U+FF0D Fullwidth Hyphen-Minus
-
- %input.bulk-buy.variant-quantity{
- type: "number",
- min: "0",
- max: "{{ available() }}",
+ %input.bulk-buy.variant-quantity{type: "number", min: "0", max: "{{ available() }}",
ng: {model: "variant.line_item.quantity", max: "Infinity"}}>
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "add(1)", disabled: "!canAdd(1)"}}
-# U+FF0B Fullwidth Plus Sign
@@ -31,10 +28,7 @@
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(-1)", disabled: "!canAddMax(-1)"}}>
-# U+FF0D Fullwidth Hyphen-Minus
-
- %input.bulk-buy.variant-quantity{
- type: "number",
- min: "0",
- max: "{{ available() }}",
+ %input.bulk-buy.variant-quantity{type: "number", min: "0", max: "{{ available() }}",
ng: {model: "variant.line_item.max_quantity", max: "Infinity"}}>
%button.bulk-buy-add.variant-quantity{type: "button", ng: {click: "addMax(1)", disabled: "!canAddMax(1)"}}
-# U+FF0B Fullwidth Plus Sign
diff --git a/app/assets/javascripts/templates/partials/shop_variant_no_group_buy.html.haml b/app/assets/javascripts/templates/partials/shop_variant_no_group_buy.html.haml
index ad8abdf747..2157f548c7 100644
--- a/app/assets/javascripts/templates/partials/shop_variant_no_group_buy.html.haml
+++ b/app/assets/javascripts/templates/partials/shop_variant_no_group_buy.html.haml
@@ -8,12 +8,8 @@
%button.variant-quantity{type: "button", ng: {click: "add(-1)", disabled: "!canAdd(-1)"}}>
-# U+FF0D Fullwidth Hyphen-Minus
-
- %input.variant-quantity{
- type: "number",
- min: "0",
- max: "{{ available() }}",
- ng: {model: "variant.line_item.quantity", max: "Infinity"}
- }>
+ %input.variant-quantity{ type: "number", min: "0", max: "{{ available() }}",
+ ng: {model: "variant.line_item.quantity", max: "Infinity"}}>
%button.variant-quantity{type: "button", ng: {click: "add(1)", disabled: "!canAdd(1)"}}
-# U+FF0B Fullwidth Plus Sign
+
diff --git a/app/controllers/spree/paypal_controller.rb b/app/controllers/spree/paypal_controller.rb
index 5ca339f52f..f5ef6872e6 100644
--- a/app/controllers/spree/paypal_controller.rb
+++ b/app/controllers/spree/paypal_controller.rb
@@ -15,9 +15,7 @@ module Spree
order = current_order || raise(ActiveRecord::RecordNotFound)
items = order.line_items.map(&method(:line_item))
- tax_adjustments = order.adjustments.tax
- # TODO: Remove in Spree 2.2
- tax_adjustments = tax_adjustments.additional if tax_adjustments.respond_to?(:additional)
+ tax_adjustments = order.adjustments.tax.additional
shipping_adjustments = order.adjustments.shipping
order.adjustments.eligible.each do |adjustment|
@@ -175,12 +173,8 @@ module Spree
def payment_details(items)
item_sum = items.sum { |i| i[:Quantity] * i[:Amount][:value] }
- # Would use tax_total here, but it can include "included" taxes as well.
- # For instance, tax_total would include the 10% GST in Australian stores.
- # A quick sum will get us around that little problem.
- # TODO: Remove additional check in 2.2
- tax_adjustments = current_order.adjustments.tax
- tax_adjustments = tax_adjustments.additional if tax_adjustments.respond_to?(:additional)
+
+ tax_adjustments = current_order.adjustments.tax.additional
tax_adjustments_total = tax_adjustments.sum(:amount)
if item_sum.zero?
diff --git a/app/models/spree/adjustment.rb b/app/models/spree/adjustment.rb
index f256ab108e..3ffd9d8cac 100644
--- a/app/models/spree/adjustment.rb
+++ b/app/models/spree/adjustment.rb
@@ -64,12 +64,14 @@ module Spree
end
end
- scope :tax, -> { where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::Order') }
+ scope :tax, -> { where(originator_type: 'Spree::TaxRate') }
scope :price, -> { where(adjustable_type: 'Spree::LineItem') }
scope :optional, -> { where(mandatory: false) }
scope :charge, -> { where('amount >= 0') }
scope :credit, -> { where('amount < 0') }
scope :return_authorization, -> { where(source_type: "Spree::ReturnAuthorization") }
+ scope :inclusive, -> { where(included: true) }
+ scope :additional, -> { where(included: false) }
scope :enterprise_fee, -> { where(originator_type: 'EnterpriseFee') }
scope :admin, -> { where(source_type: nil, originator_type: nil) }
diff --git a/app/models/spree/order.rb b/app/models/spree/order.rb
index 784c9342d0..64278ed400 100644
--- a/app/models/spree/order.rb
+++ b/app/models/spree/order.rb
@@ -47,6 +47,7 @@ module Spree
dependent: :destroy
has_many :line_item_adjustments, through: :line_items, source: :adjustments
+ has_many :all_adjustments, class_name: 'Spree::Adjustment', dependent: :destroy
has_many :shipments, dependent: :destroy do
def states
diff --git a/app/models/spree/shipment.rb b/app/models/spree/shipment.rb
index 67d8e5e935..239430e07e 100644
--- a/app/models/spree/shipment.rb
+++ b/app/models/spree/shipment.rb
@@ -164,14 +164,6 @@ module Spree
Spree::Money.new(item_cost, currency: currency)
end
- def total_cost
- cost + item_cost
- end
-
- def display_total_cost
- Spree::Money.new(total_cost, currency: currency)
- end
-
def editable_by?(_user)
!shipped?
end
diff --git a/app/models/spree/tax_rate.rb b/app/models/spree/tax_rate.rb
index eeee5673aa..0ea98c9cea 100644
--- a/app/models/spree/tax_rate.rb
+++ b/app/models/spree/tax_rate.rb
@@ -61,7 +61,7 @@ module Spree
def adjust(order)
label = create_label
if included_in_price
- if Zone.default_tax.contains? order.tax_zone
+ if default_zone_or_zone_match? order
order.line_items.each { |line_item| create_adjustment(label, line_item, line_item) }
else
amount = -1 * calculator.compute(order)
@@ -89,6 +89,10 @@ module Spree
end
end
+ def default_zone_or_zone_match?(order)
+ Zone.default_tax.contains?(order.tax_zone) || order.tax_zone == zone
+ end
+
# Manually apply a TaxRate to a particular amount. TaxRates normally compute against
# LineItems or Orders, so we mock out a line item here to fit the interface
# that our calculator (usually DefaultTax) expects.
@@ -114,6 +118,8 @@ module Spree
label = ""
label << (name.presence || tax_category.name) + " "
label << (show_rate_in_label? ? "#{amount * 100}%" : "")
+ label << " (#{I18n.t('models.tax_rate.included_in_price')})" if included_in_price?
+ label
end
def with_tax_included_in_price
diff --git a/app/views/admin/subscriptions/_review.html.haml b/app/views/admin/subscriptions/_review.html.haml
index 0bcaf2eab2..f7b716684a 100644
--- a/app/views/admin/subscriptions/_review.html.haml
+++ b/app/views/admin/subscriptions/_review.html.haml
@@ -3,47 +3,47 @@
.row
.eight.columns.alpha
.row
- .six.columns.alpha
+ .five.columns.alpha
%h3= t('.details')
- .two.columns.omega.text-right
+ .eleven.columns.omega
%input#edit-details{ type: "button", value: t(:edit), ng: { click: "setView('details')" } }
.row
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.customer')
- .five.columns.omega {{ subscription.customer().email }}
+ .eleven.columns.omega {{ subscription.customer().email }}
.row
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.schedule')
- .five.columns.omega {{ subscription.schedule().name }}
+ .eleven.columns.omega {{ subscription.schedule().name }}
.row
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.payment_method')
- .five.columns.omega {{ subscription.paymentMethod().name }}
+ .eleven.columns.omega {{ subscription.paymentMethod().name }}
.row
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.shipping_method')
- .five.columns.omega {{ subscription.shippingMethod().name }}
+ .eleven.columns.omega {{ subscription.shippingMethod().name }}
.row
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.begins_at')
- .five.columns.omega {{ subscription.begins_at }}
+ .eleven.columns.omega {{ subscription.begins_at }}
.row.margin-bottom-30
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.ends_at')
- .five.columns.omega {{ subscription.ends_at || ('ongoing' | t) }}
+ .eleven.columns.omega {{ subscription.ends_at || ('ongoing' | t) }}
.row
- .six.columns.alpha
+ .five.columns.alpha
%h3= t('.address')
- .two.columns.omega.text-right
+ .eleven.columns.omega
%input#edit-address{ type: "button", value: t(:edit), ng: { click: "setView('address')" } }
.row
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.bill_address')
- .five.columns.omega {{ formatAddress(subscription.bill_address) }}
+ .eleven.columns.omega {{ formatAddress(subscription.bill_address) }}
.row
- .three.columns.alpha
+ .five.columns.alpha
%strong= t('admin.ship_address')
- .five.columns.omega {{ formatAddress(subscription.ship_address) }}
+ .eleven.columns.omega {{ formatAddress(subscription.ship_address) }}
.one.column
@@ -52,47 +52,46 @@
.row
.five.columns.alpha
%h3= t('.products')
- .two.columns.omega.text-right
+ .eleven.columns.omega
%input#edit-products{ type: "button", value: t(:edit), ng: { click: "setView('products')" } }
.row
- .seven.columns.alpha.omega
- %table#subscription-line-items.admin-subscription-review-subscription-line-items
- %colgroup
- %col{:style => "width: 62%;"}/
- %col{:style => "width: 14%;"}/
- %col{:style => "width: 10%;"}/
- %col{:style => "width: 14%;"}/
- %thead
- %tr
- %th= t(:item_description)
- %th.price= t(:price)
- %th.quantity= t(:qty)
- %th.total
- %span= t(:total)
- %tbody
- %tr.item{ id: "sli_{{$index}}", ng: { repeat: "item in subscription.subscription_line_items | filter:{ _destroy: '!true' }", class: { even: 'even', odd: 'odd' } } }
- %td
- .description {{ item.description }}
- .not-in-open-and-upcoming-order-cycles-warning{ ng: { if: '!item.in_open_and_upcoming_order_cycles' } }
- = t(".no_open_or_upcoming_order_cycle")
- %td.price.align-center {{ item.price_estimate | localizeCurrency }}
- %td.quantity {{ item.quantity }}
- %td.total.align-center {{ (item.price_estimate * item.quantity) | localizeCurrency }}
- %tbody#subtotal.no-border-top{"data-hook" => "admin_order_form_subtotal"}
- %tr#subtotal-row
- %td{:colspan => "3"}
- %b
- = t(:subtotal)
- \:
- %td.total.align-center
- %span {{ subscription.estimatedSubtotal() | localizeCurrency }}
- %tbody#order-total.grand-total.no-border-top{"data-hook" => "admin_order_form_total"}
- %tr
- %td{:colspan => "3"}
- %b
- = t(:order_total_price)
- \:
- %td.total.align-center
- %span#order_form_total {{ subscription.estimatedTotal() | localizeCurrency }}
- %p.notice
- = t "this_is_an_estimate", scope: 'admin.subscriptions.subscription_line_items'
+ %table#subscription-line-items.admin-subscription-review-subscription-line-items
+ %colgroup
+ %col{:style => "width: 62%;"}/
+ %col{:style => "width: 14%;"}/
+ %col{:style => "width: 10%;"}/
+ %col{:style => "width: 14%;"}/
+ %thead
+ %tr
+ %th= t(:item_description)
+ %th.price= t(:price)
+ %th.quantity= t(:qty)
+ %th.total
+ %span= t(:total)
+ %tbody
+ %tr.item{ id: "sli_{{$index}}", ng: { repeat: "item in subscription.subscription_line_items | filter:{ _destroy: '!true' }", class: { even: 'even', odd: 'odd' } } }
+ %td
+ .description {{ item.description }}
+ .not-in-open-and-upcoming-order-cycles-warning{ ng: { if: '!item.in_open_and_upcoming_order_cycles' } }
+ = t(".no_open_or_upcoming_order_cycle")
+ %td.price.align-center {{ item.price_estimate | localizeCurrency }}
+ %td.quantity {{ item.quantity }}
+ %td.total.align-center {{ (item.price_estimate * item.quantity) | localizeCurrency }}
+ %tbody#subtotal.no-border-top{"data-hook" => "admin_order_form_subtotal"}
+ %tr#subtotal-row
+ %td{:colspan => "3"}
+ %b
+ = t(:subtotal)
+ \:
+ %td.total.align-center
+ %span {{ subscription.estimatedSubtotal() | localizeCurrency }}
+ %tbody#order-total.grand-total.no-border-top{"data-hook" => "admin_order_form_total"}
+ %tr
+ %td{:colspan => "3"}
+ %b
+ = t(:order_total_price)
+ \:
+ %td.total.align-center
+ %span#order_form_total {{ subscription.estimatedTotal() | localizeCurrency }}
+ %p.notice
+ = t "this_is_an_estimate", scope: 'admin.subscriptions.subscription_line_items'
diff --git a/config/initializers/feature_toggles.rb b/config/initializers/feature_toggles.rb
index 13d083979c..9c31940462 100644
--- a/config/initializers/feature_toggles.rb
+++ b/config/initializers/feature_toggles.rb
@@ -1,5 +1,11 @@
require 'open_food_network/feature_toggle'
-beta_testers = ENV['BETA_TESTERS']&.split(/[\s,]+/)
+beta_testers = ENV['BETA_TESTERS']&.split(/[\s,]+/) || []
-OpenFoodNetwork::FeatureToggle.enable(:customer_balance, beta_testers)
+OpenFoodNetwork::FeatureToggle.enable(:customer_balance) do |user|
+ if beta_testers == ['all']
+ true
+ else
+ beta_testers.include?(user.email)
+ end
+end
diff --git a/config/locales/ca.yml b/config/locales/ca.yml
index ed961ce0e5..bf51285cc4 100644
--- a/config/locales/ca.yml
+++ b/config/locales/ca.yml
@@ -117,6 +117,8 @@ ca:
models:
order_cycle:
cloned_order_cycle_name: "CÒPIA DE %{order_cycle}"
+ tax_rate:
+ included_in_price: "Inclòs en el preu"
validators:
date_time_string_validator:
not_string_error: "ha de ser una seqüència"
diff --git a/config/locales/de_DE.yml b/config/locales/de_DE.yml
index 0adcac5365..8b970201b6 100644
--- a/config/locales/de_DE.yml
+++ b/config/locales/de_DE.yml
@@ -117,6 +117,8 @@ de_DE:
models:
order_cycle:
cloned_order_cycle_name: "Kopie von %{order_cycle}"
+ tax_rate:
+ included_in_price: "im Preis inbegriffen"
validators:
date_time_string_validator:
not_string_error: "muss eine Zeichenfolge sein"
@@ -192,7 +194,7 @@ de_DE:
explainer: Die automatische Verarbeitung dieser Bestellungen ist aus einem unbekannten Grund fehlgeschlagen. Dies sollte nicht geschehen, bitte kontaktieren Sie uns, wenn Sie dies sehen.
home: "OFN"
title: "Open Food Network"
- welcome_to: "Willkommen bei"
+ welcome_to: "Willkommen beim"
site_meta_description: "Wir wagen den Neustart. Mit Bauern und Züchtern, die bereit sind, ihre Geschichten stolz und wahrhaftig zu erzählen. Mit Händlern, die bereit sind, Menschen fair und ehrlich mit Produkten zu verbinden. Mit Käufern, die glauben, dass ihr Einkaufsverhalten die Welt wirklich verändern kann."
search_by_name: Suche nach Ort oder Name des Ladens/Produzents...
producers_join: 'Wir laden Produzenten ein, jetzt dem Open Food Network beizutreten. '
@@ -1263,7 +1265,7 @@ de_DE:
ticket_column_item: "Artikel"
ticket_column_unit_price: "Stückpreis"
ticket_column_total_price: "Gesamtpreis"
- menu_1_title: "Läden"
+ menu_1_title: "Einkaufen"
menu_1_url: "/shops"
menu_2_title: "Karte"
menu_2_url: "/map"
@@ -1271,12 +1273,12 @@ de_DE:
menu_3_url: "/producers"
menu_4_title: "Gruppen"
menu_4_url: "/groups"
- menu_5_title: "Über uns"
- menu_5_url: "https://wp.openfoodnetwork.de/"
- menu_6_title: "Support"
- menu_6_url: "https://wp.openfoodnetwork.de/support/"
- menu_7_title: "Mehr erfahren"
- menu_7_url: "https://openfoodnetwork.org/au/learn/"
+ menu_5_title: "Verkaufen"
+ menu_5_url: "https://openfoodnetwork.de/sell"
+ menu_6_title: "Über uns"
+ menu_6_url: "https://wp.openfoodnetwork.de/"
+ menu_7_title: "Hilfe"
+ menu_7_url: "https://wp.openfoodnetwork.de/support/"
logo: "Logo (640x130)"
logo_mobile: "Mobile Logo (75x26)"
logo_mobile_svg: "Mobile Logo (SVG)"
@@ -1407,7 +1409,7 @@ de_DE:
cookies_policy_link_desc: "Wenn Sie mehr erfahren möchten, besuchen Sie unsere"
cookies_policy_link: "Hinweise zu Cookies"
cookies_accept_button: "Cookies akzeptieren"
- home_shop: Jetzt einkaufen
+ home_shop: Jetzt regional einkaufen
brandstory_headline: "Lebensmittel Direktvermarktung"
brandstory_intro: "Manchmal ist der beste Weg, das System zu reparieren, einen Neuanfang zu wagen ..."
brandstory_part1: "Wir wagen den Neuanfang. Mit Bauern und Züchtern, die bereit sind, ihre Geschichten stolz und wahrhaftig zu erzählen. Mit Händlern, die bereit sind, Menschen fair und ehrlich mit Produkten zu verbinden. Mit Käufern, die glauben, dass ihr Einkaufsverhalten die Welt wirklich verändern kann."
@@ -2960,6 +2962,7 @@ de_DE:
display_currency: "Währung anzeigen"
choose_currency: "Währung auswählen"
mail_method_settings: "E-Mail-Methodeneinstellungen"
+ mail_settings_notice_html: "Einige der folgenden Einstellungen können nicht geändert werden und werden hier nur zu Zwecken der Fehlerbehebung aufgeführt. Änderungen können vorgenommen werden, indem die Einstellungen der deutschen Instanz aktualisiert und mithilfe von ofn-install bereitgestellt werden. Wenden Sie sich an das globale OFN-Team, um weitere Informationen zu erhalten."
general: "Allgemeines"
enable_mail_delivery: "E-Mail-Versand aktivieren"
send_mails_as: "E-Mails senden als"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 6cb2b831c8..ba57144201 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -140,6 +140,8 @@ en:
models:
order_cycle:
cloned_order_cycle_name: "COPY OF %{order_cycle}"
+ tax_rate:
+ included_in_price: "Included in price"
validators:
date_time_string_validator:
diff --git a/config/locales/en_CA.yml b/config/locales/en_CA.yml
index 1e12e3931f..5af9f594e3 100644
--- a/config/locales/en_CA.yml
+++ b/config/locales/en_CA.yml
@@ -2950,6 +2950,7 @@ en_CA:
display_currency: "Display currency"
choose_currency: "Choose Currency"
mail_method_settings: "Mail Method Settings"
+ mail_settings_notice_html: "Some of the following settings can't be edited and are listed here just for debugging purposes. Changes can be made by updating the instance's secrets and provisioning them using ofn-install. Reach out to the OFN global team for further details."
general: "General"
enable_mail_delivery: "Enable Mail Delivery"
send_mails_as: "Send Mails As"
@@ -3466,6 +3467,8 @@ en_CA:
cancel_email_for_shop:
greeting: "Dear %{name},"
subject: "Cancellation of Order"
+ intro: "A customer has cancelled ther order #%{number}."
+ view_cancelled_order: "View cancelled order"
confirm_email:
subject: "Order Confirmation"
invoice_email:
diff --git a/config/locales/en_FR.yml b/config/locales/en_FR.yml
index 480eb47e27..262b3b380a 100644
--- a/config/locales/en_FR.yml
+++ b/config/locales/en_FR.yml
@@ -117,6 +117,8 @@ en_FR:
models:
order_cycle:
cloned_order_cycle_name: "COPY OF %{order_cycle}"
+ tax_rate:
+ included_in_price: "Included in price"
validators:
date_time_string_validator:
not_string_error: "must be a string"
diff --git a/config/locales/en_GB.yml b/config/locales/en_GB.yml
index 0768294f71..1a51d91705 100644
--- a/config/locales/en_GB.yml
+++ b/config/locales/en_GB.yml
@@ -117,6 +117,8 @@ en_GB:
models:
order_cycle:
cloned_order_cycle_name: "COPY OF %{order_cycle}"
+ tax_rate:
+ included_in_price: "Included in price"
validators:
date_time_string_validator:
not_string_error: "must be a string"
@@ -2957,6 +2959,7 @@ en_GB:
display_currency: "Display currency"
choose_currency: "Choose Currency"
mail_method_settings: "Mail Method Settings"
+ mail_settings_notice_html: "Some of the following settings can't be edited and are listed here just for debugging purposes. Changes can be made by updating the instance's secrets and provisioning them using ofn-install. Reach out to the OFN global team for further details."
general: "General"
enable_mail_delivery: "Enable Mail Delivery"
send_mails_as: "Send Mails As"
@@ -3473,6 +3476,8 @@ en_GB:
cancel_email_for_shop:
greeting: "Dear %{name},"
subject: "Cancellation of Order"
+ intro: "A customer has cancelled their order #%{number}."
+ view_cancelled_order: "View cancelled order"
confirm_email:
subject: "Order Confirmation"
invoice_email:
diff --git a/config/locales/en_IE.yml b/config/locales/en_IE.yml
index fc80e2ce82..10da03f91a 100644
--- a/config/locales/en_IE.yml
+++ b/config/locales/en_IE.yml
@@ -289,11 +289,16 @@ en_IE:
create_and_add_another: "Create and Add Another"
create: "Create"
cancel: "Cancel"
+ resume: "Resume"
save: "Save"
edit: "Edit"
update: "Update"
delete: "Delete"
add: "Add"
+ cut: "Cut"
+ paste: "Paste"
+ destroy: "Destroy"
+ rename: "Rename"
admin:
begins_at: Begins At
begins_on: Begins On
@@ -352,6 +357,7 @@ en_IE:
has_n_rules: "has %{num} rules"
unsaved_confirm_leave: "There are unsaved changed on this page. Continue without saving?"
unsaved_changes: "You have unsaved changes"
+ available_units: "Available Units"
shopfront_settings:
embedded_shopfront_settings: "Embedded Shopfront Settings"
enable_embedded_shopfronts: "Enable Embedded Shopfronts"
@@ -411,6 +417,7 @@ en_IE:
search_by_email: "Search by email/code..."
guest_label: "Guest checkout"
credit_owed: "Credit Owed"
+ balance_due: "Balance Due"
destroy:
has_associated_orders: "Delete failed: customer has associated orders with this shop"
contents:
@@ -599,6 +606,8 @@ en_IE:
controls:
back_to_my_inventory: Back to my inventory
orders:
+ edit:
+ order_sure_want_to: Are you sure you want to %{event} this order?
invoice_email_sent: 'Invoice email has been sent'
order_email_resent: 'Order email has been resent'
bulk_management:
@@ -647,6 +656,7 @@ en_IE:
invoice_text: Add customized text at the end of invoices
terms_and_conditions: "Terms and Conditions"
remove_terms_and_conditions: "Remove File"
+ uploaded_on: "uploaded on"
contact:
name: Name
name_placeholder: eg. Amanda Plum
@@ -755,6 +765,7 @@ en_IE:
is displayed on your shop only when you have no active order cycles
(ie. shop is closed).
shopfront_category_ordering: "Shopfront Category Ordering"
+ shopfront_category_ordering_note: "(top to bottom)"
open_date: "Open Date"
close_date: "Close Date"
social:
@@ -1164,6 +1175,7 @@ en_IE:
cart: "cart"
message_html: "You have an order for this order cycle already. Check the %{cart} to see the items you ordered before. You can also cancel items as long as the order cycle is open."
terms_and_conditions:
+ message_html: "I agree to the seller's %{terms_and_conditions_link}."
link_text: "Terms and Conditions"
failed: "The checkout failed. Please let us know so that we can process your order."
shops:
@@ -1557,6 +1569,7 @@ en_IE:
shopping_groups_part_of: "is part of:"
shopping_producers_of_hub: "%{hub}'s producers:"
enterprises_next_closing: "Next order closing"
+ enterprises_currently_open: "Orders are currently open"
enterprises_ready_for: "Ready for"
enterprises_choose: "Choose when you want your order:"
maps_open: "Open"
@@ -1578,6 +1591,7 @@ en_IE:
hubs_distance: Closest to
hubs_distance_filter: "Show me shops near %{location}"
shop_changeable_orders_alert_html:
+ one: Your order with %{shop} / %{order} is open for review. You can make changes until %{oc_close}.
few: You have %{count} orders with %{shop} currently open for review. You can make changes until %{oc_close}.
many: You have %{count} orders with %{shop} currently open for review. You can make changes until %{oc_close}.
other: You have %{count} orders with %{shop} currently open for review. You can make changes until %{oc_close}.
@@ -1725,6 +1739,7 @@ en_IE:
orders_could_not_cancel: "Sorry, the order could not be cancelled"
orders_cannot_remove_the_final_item: "Cannot remove the final item from an order, please cancel the order instead."
orders_bought_items_notice:
+ one: An additional item is already confirmed for this order cycle
few: "%{count} additional items already confirmed for this order cycle"
many: "%{count} additional items already confirmed for this order cycle"
other: "%{count} additional items already confirmed for this order cycle"
@@ -2071,6 +2086,7 @@ en_IE:
spree_classification_primary_taxon_error: "Taxon %{taxon} is the primary taxon of %{product} and cannot be deleted"
spree_order_availability_error: "Distributor or order cycle cannot supply the products in your cart"
spree_order_populator_error: "That distributor or order cycle can't supply all the products in your cart. Please choose another."
+ spree_order_cycle_error: "Please choose an order cycle for this order."
spree_order_populator_availability_error: "That product is not available from the chosen distributor or order cycle."
spree_distributors_error: "At least one hub must be selected"
spree_user_enterprise_limit_error: "^%{email} is not permitted to own any more enterprises (limit is %{enterprise_limit})."
@@ -2303,6 +2319,8 @@ en_IE:
payment_processing_failed: "Payment could not be processed, please check the details you entered"
payment_method_not_supported: "That payment method is unsupported. Please choose another one."
payment_updated: "Payment Updated"
+ cannot_perform_operation: "Could not update the payment"
+ action_required: "Action required"
inventory_settings: "Inventory Settings"
tag_rules: "Tag Rules"
shop_preferences: "Shop Preferences"
@@ -2363,6 +2381,7 @@ en_IE:
js:
saving: 'Saving...'
changes_saved: 'Changes saved.'
+ authorising: "Authorising..."
save_changes_first: Save changes first.
all_changes_saved: All changes saved
unsaved_changes: You have unsaved changes
@@ -2378,6 +2397,7 @@ en_IE:
resolve_errors: Please resolve the following errors
more_items: "+ %{count} More"
default_card_updated: Default Card Updated
+ default_card_voids_auth: Changing your default card will remove shops' existing authorizations to charge it. You can re-authorize shops after updating the default card. Do you wish to change the default card?"
cart:
add_to_cart_failed: >
There was a problem adding this product to the cart. Perhaps it has become
@@ -2407,6 +2427,14 @@ en_IE:
By creating rules related to a specific customer tag, you can override
the default behaviour (whether it be to show or to hide items) for customers
with the specified tag.
+ terms_and_conditions_info:
+ title: "Uploading Terms and Conditions"
+ message_1: "Terms and Conditions are the contract between you, the seller, and the shopper. If you upload a file here shoppers must accept your Terms and Conditions in order to complete checkout. For the shopper this will appear as a checkbox at checkout that must be checked in order to proceed with checkout. We highly recommend you upload Terms and Conditions in alignment with national legislation."
+ message_2: "Shoppers will only be required to accept Terms and Conditions once. However if you change you Terms and Conditions shoppers will again be required to accept them before they can checkout."
+ terms_and_conditions_warning:
+ title: "Uploading Terms and Conditions"
+ message_1: "All your buyers will have to agree to them once at checkout. If you update the file, all your buyers will have to agree to them again at checkout."
+ message_2: "For buyers with subscriptions, you need to email them the Terms and Conditions (or the changes to them) for now, nothing will notify them about these new Terms and Conditions."
panels:
save: SAVE
saved: SAVED
@@ -2567,6 +2595,8 @@ en_IE:
processing: "processing"
void: "void"
invalid: "invalid"
+ quantity_adjusted: "Insufficient stock available. Line item updated to maximum available quantity."
+ quantity_unchanged: "Quantity unchanged from previous amount."
resend_user_email_confirmation:
resend: "Resend"
sending: "Resend..."
@@ -2871,6 +2901,8 @@ en_IE:
delete: "Delete"
cannot_set_shipping_method_without_address: "Cannot set shipping method until customer details are provided."
no_tracking_present: "No tracking details provided."
+ tracking: "Tracking"
+ tracking_number: "Tracking Number"
order_total: "Order Total"
customer_details: "Customer Details"
customer_search: "Customer Search"
@@ -2904,6 +2936,8 @@ en_IE:
server: "Server"
test_mode: "Test Mode"
logourl: "Logourl"
+ are_you_sure_delete: "Are you sure you want to delete this record?"
+ confirm_delete: "Confirm Deletion"
configurations: "Configurations"
general_settings: "General Settings"
site_name: "Site Name"
@@ -2923,6 +2957,7 @@ en_IE:
display_currency: "Display currency"
choose_currency: "Choose Currency"
mail_method_settings: "Mail Method Settings"
+ mail_settings_notice_html: "Some of the following settings can't be edited and are listed here just for debugging purposes. Changes can be made by updating the instance's secrets and provisioning them using ofn-install. Reach out to the OFN global team for further details."
general: "General"
enable_mail_delivery: "Enable Mail Delivery"
send_mails_as: "Send Mails As"
@@ -3025,6 +3060,7 @@ en_IE:
shared:
error_messages:
errors_prohibited_this_record_from_being_saved:
+ one: "1 error prohibited this record from being saved:"
few: "%{count} errors prohibited this record from being saved:"
many: "%{count} errors prohibited this record from being saved:"
other: "%{count} errors prohibited this record from being saved:"
@@ -3036,6 +3072,7 @@ en_IE:
payment_state: "Payment County"
errors:
messages:
+ included_price_validation: "cannot be selected unless you have set a Default Tax Zone"
blank: "can't be blank"
layouts:
admin:
@@ -3246,6 +3283,13 @@ en_IE:
deactivation_warning: "De-activating a payment method can make the payment method disappear from your list. Alternatively, you can hide a payment method from the checkout page by setting the option 'Display' to 'back office only'."
providers:
provider: "Provider"
+ check: "Cash/EFT/etc. (payments for which automatic validation is not required)"
+ pin: "Pin Payments"
+ paypalexpress: "PayPal Express"
+ stripeconnect: "Stripe"
+ stripesca: "Stripe SCA"
+ bogus: "Bogus"
+ bogussimple: "BogusSimple"
payments:
source_forms:
stripe:
@@ -3430,6 +3474,8 @@ en_IE:
cancel_email_for_shop:
greeting: "Dear %{name},"
subject: "Cancellation of Order"
+ intro: "A customer has cancelled their order #%{number}."
+ view_cancelled_order: "View cancelled order"
confirm_email:
subject: "Order Confirmation"
invoice_email:
@@ -3448,6 +3494,10 @@ en_IE:
subject: "Reset password instructions"
confirmation_instructions:
subject: "Please confirm your OFN account"
+ payment_mailer:
+ authorize_payment:
+ subject: "Please authorize your payment to %{distributor} on OFN"
+ instructions: "Your payment of %{amount} to %{distributor} requires additional authentication. Please visit the following URL to authorize your payment:"
shipment_mailer:
shipped_email:
dear_customer: "Dear Customer,"
@@ -3484,7 +3534,23 @@ en_IE:
paused: paused
canceled: cancelled
paypal:
+ already_refunded: "This payment has been refunded and no further action can be taken on it."
+ no_payment_via_admin_backend: "You cannot charge PayPal accounts through the admin backend at this time."
+ transaction: "PayPal Transaction"
+ payer_id: "Payer ID"
+ transaction_id: "Transaction ID"
+ token: "Token"
+ refund: "Refund"
refund_amount: "Amount"
+ original_amount: "Original amount: %{amount}"
+ refund_successful: "PayPal refund successful"
+ refund_unsuccessful: "PayPal refund unsuccessful"
+ actions:
+ refund: "Refund"
+ flash:
+ cancel: "Don't want to use PayPal? No problems."
+ connection_failed: "Could not connect to PayPal."
+ generic_error: "PayPal failed. %{reasons}"
users:
form:
account_settings: Account Settings
@@ -3523,9 +3589,11 @@ en_IE:
delete?: Delete?
cards:
authorised_shops: Authorised Shops
+ authorised_shops_agreement: This is the list of shops which are permitted to charge your default credit card for any subscriptions (ie. repeating orders) you may have. Your card details will be kept secure and will not be shared with shop owners. You will always be notified when you are charged. By checking the box for a shop, you are agreeing to authorise that shop to send instructions to the financial institution that issued your card to take payments in accordance with the terms of any subscription you create with that shop.
saved_cards_popover: This is the list of cards you have opted to save for later use. Your 'default' will be selected automatically when you checkout an order, and can be charged by any shops you have allowed to do so (see right).
authorised_shops:
shop_name: "Shop Name"
+ allow_charges?: "Allow Charges to Default Card?"
localized_number:
invalid_format: has an invalid format. Please enter a number.
api:
diff --git a/config/locales/es.yml b/config/locales/es.yml
index d69a28a08f..3ace997748 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -117,6 +117,8 @@ es:
models:
order_cycle:
cloned_order_cycle_name: "COPIA DE %{order_cycle}"
+ tax_rate:
+ included_in_price: "Incluido en el precio"
validators:
date_time_string_validator:
not_string_error: "debe ser una cadena"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index d62630fa2d..87b28906da 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -117,6 +117,8 @@ fr:
models:
order_cycle:
cloned_order_cycle_name: "Copie de %{order_cycle}"
+ tax_rate:
+ included_in_price: "Inclus dans le prix"
validators:
date_time_string_validator:
not_string_error: "doit être une série"
diff --git a/config/locales/fr_CA.yml b/config/locales/fr_CA.yml
index 3eced7a54c..a7af33b68d 100644
--- a/config/locales/fr_CA.yml
+++ b/config/locales/fr_CA.yml
@@ -2321,6 +2321,8 @@ fr_CA:
payment_processing_failed: "Le paiement n'a pas pu être traité, veuillez vérifier les informations saisies"
payment_method_not_supported: "Cette méthode de paiement n'est pas maintenue. Veuillez en sélectionner une autre."
payment_updated: "Paiement mis à jour"
+ cannot_perform_operation: "Le paiement n'a pas pu être mis à jour."
+ action_required: "Une action est requise"
inventory_settings: "Paramètres catalogue boutique"
tag_rules: "Règles de tag"
shop_preferences: "Préférences boutique"
@@ -2599,6 +2601,8 @@ fr_CA:
processing: "en traitement"
void: "faire un avoir"
invalid: "invalide"
+ quantity_adjusted: "Le stock disponible est insuffisant. La quantité a été mise à jour en fonction du stock restant."
+ quantity_unchanged: "La quantité n'a pas été modifiée."
resend_user_email_confirmation:
resend: "Renvoyer"
sending: "Renvoyer"
@@ -2960,6 +2964,7 @@ fr_CA:
display_currency: "Afficher la devise"
choose_currency: "Choisir la devise"
mail_method_settings: "Paramètre méthode mail"
+ mail_settings_notice_html: "Certains champs ne peuvent pas être modifiés car ils sont utilisés uniquement pour déboggage. Les modifications peuvent être réalisées par un développeur via ofn-install."
general: "Général"
enable_mail_delivery: "Permettre distribution des mails"
send_mails_as: "Envoyer les mails en tant que"
@@ -3476,6 +3481,8 @@ fr_CA:
cancel_email_for_shop:
greeting: "Bonjour %{name},"
subject: "Annulation de Commande"
+ intro: "Un acheteur a annulé sa commande # %{number}."
+ view_cancelled_order: "Voir la commande annulée"
confirm_email:
subject: "Confirmation de commande"
invoice_email:
@@ -3495,6 +3502,10 @@ fr_CA:
subject: "Reprendre"
confirmation_instructions:
subject: "Veuillez confirmer votre compte"
+ payment_mailer:
+ authorize_payment:
+ subject: "Veuillez autoriser votre paiement à %{distributor} on OFN."
+ instructions: "Votre paiement de %{amount} to %{distributor} demande une autorisation additionnelle. Veuillez suivre ce lien afin d'autoriser votre paiement:"
shipment_mailer:
shipped_email:
dear_customer: "Cher Acheteur,"
diff --git a/config/locales/it.yml b/config/locales/it.yml
index 564b355612..dbec9ac539 100644
--- a/config/locales/it.yml
+++ b/config/locales/it.yml
@@ -117,6 +117,8 @@ it:
models:
order_cycle:
cloned_order_cycle_name: "COPIA DI %{order_cycle}"
+ tax_rate:
+ included_in_price: "Incluso nel prezzo"
validators:
date_time_string_validator:
not_string_error: "deve essere una stringa"
@@ -2955,6 +2957,7 @@ it:
display_currency: "Visualizza valuta"
choose_currency: "Scegli Valuta"
mail_method_settings: "Impostazioni del metodo di posta"
+ mail_settings_notice_html: "Alcune delle seguenti impostazioni non possono essere modificate e sono elencate qui solo per scopi di debug. È possibile apportare modifiche aggiornando i segreti dell'istanza ed utilizzando ofn-install. Contatta il team globale di OFN per maggiori dettagli. "
general: "Generale"
enable_mail_delivery: "Abilita recapito posta"
send_mails_as: "Invia mail come"
@@ -3471,6 +3474,8 @@ it:
cancel_email_for_shop:
greeting: "Caro %{name},"
subject: "Cancellazione dell'ordine"
+ intro: "Un cliente ha cancellato la sua gentile richiesta #%{number}."
+ view_cancelled_order: "Visualizza richiesta eliminata"
confirm_email:
subject: "Conferma Ordine"
invoice_email:
diff --git a/config/locales/ru.yml b/config/locales/ru.yml
index 0f760cd34d..9b1861f9a0 100644
--- a/config/locales/ru.yml
+++ b/config/locales/ru.yml
@@ -118,6 +118,8 @@ ru:
models:
order_cycle:
cloned_order_cycle_name: "КОПИЯ %{order_cycle}"
+ tax_rate:
+ included_in_price: "Включено в цену"
validators:
date_time_string_validator:
not_string_error: "должно быть строкой"
@@ -3007,6 +3009,7 @@ ru:
display_currency: "Показывать валюту"
choose_currency: "Выбор валюты"
mail_method_settings: "Почтовые Настройки"
+ mail_settings_notice_html: "Некоторые из следующих параметров нельзя редактировать, и они перечислены здесь только для целей отладки. Изменения можно внести, обновив секреты экземпляра и предоставив их с помощью ofn-install . За подробностями обращайтесь к глобальной команде ОСП."
general: "Основные"
enable_mail_delivery: "Включить отправку почты"
send_mails_as: "Отправлять Почту Как"
@@ -3523,6 +3526,8 @@ ru:
cancel_email_for_shop:
greeting: "Уважаемый %{name}!"
subject: "Отмена заказа"
+ intro: "Покупатель отменил заказ № %{number}."
+ view_cancelled_order: "Посмотреть отмененный заказ"
confirm_email:
subject: "Подтверждение заказа"
invoice_email:
diff --git a/db/migrate/20201227122327_add_included_to_adjustments.rb b/db/migrate/20201227122327_add_included_to_adjustments.rb
new file mode 100644
index 0000000000..2ccbeab2a3
--- /dev/null
+++ b/db/migrate/20201227122327_add_included_to_adjustments.rb
@@ -0,0 +1,22 @@
+class AddIncludedToAdjustments < ActiveRecord::Migration
+ class Spree::TaxRate < ActiveRecord::Base; end
+
+ class Spree::Adjustment < ActiveRecord::Base
+ belongs_to :originator, polymorphic: true
+ end
+
+ def up
+ add_column :spree_adjustments, :included, :boolean, default: false
+ Spree::Adjustment.reset_column_information
+
+ inclusive_tax_rates = Spree::TaxRate.where(included_in_price: true)
+
+ # Set included boolean to true on all adjustments based on price-inclusive tax rates
+ Spree::Adjustment.where(originator_type: 'Spree::TaxRate', originator_id: inclusive_tax_rates).
+ update_all(included: true)
+ end
+
+ def down
+ remove_column :spree_adjustments, :included
+ end
+end
diff --git a/db/migrate/20210202052337_migrate_variant_unit_values.rb b/db/migrate/20210202052337_migrate_variant_unit_values.rb
deleted file mode 100644
index 9c6cf46a2e..0000000000
--- a/db/migrate/20210202052337_migrate_variant_unit_values.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-class MigrateVariantUnitValues < ActiveRecord::Migration
- def up
- Spree::Variant.where(unit_value: [nil, Float::NAN]).find_each do |variant|
- variant.unit_value = 1
- variant.save
- end
- Spree::Variant.where(weight: [nil, Float::NAN]).find_each do |variant|
- variant.weight = 0
- variant.save
- end
- change_column_null :spree_variants, :unit_value, false, 1
- change_column_null :spree_variants, :weight, false, 0.0
- change_column_default :spree_variants, :unit_value, 1
- change_column_default :spree_variants, :weight, 0.0
- execute "ALTER TABLE spree_variants ADD CONSTRAINT check_unit_value_for_nan CHECK (unit_value <> 'NaN')"
- execute "ALTER TABLE spree_variants ADD CONSTRAINT check_weight_for_nan CHECK (weight <> 'NaN')"
- end
-
- def down
- change_column_null :spree_variants, :unit_value, true
- change_column_null :spree_variants, :weight, true
- change_column_default :spree_variants, :unit_value, nil
- change_column_default :spree_variants, :weight, nil
- execute "ALTER TABLE spree_variants DROP CONSTRAINT check_unit_value_for_nan"
- execute "ALTER TABLE spree_variants DROP CONSTRAINT check_weight_for_nan"
- end
-end
diff --git a/db/schema.rb b/db/schema.rb
index c71d64ba0d..28b4383de8 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -385,16 +385,17 @@ ActiveRecord::Schema.define(version: 20210203215049) do
t.string "label", limit: 255
t.string "source_type", limit: 255
t.integer "adjustable_id"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
t.boolean "mandatory"
t.integer "originator_id"
t.string "originator_type", limit: 255
t.boolean "eligible", default: true
t.string "adjustable_type", limit: 255
- t.decimal "included_tax", precision: 10, scale: 2, default: 0.0, null: false
+ t.decimal "included_tax", precision: 10, scale: 2, default: 0.0, null: false
t.string "state", limit: 255
t.integer "order_id"
+ t.boolean "included", default: false
end
add_index "spree_adjustments", ["adjustable_id"], name: "index_adjustments_on_order_id", using: :btree
diff --git a/lib/open_food_network/feature_toggle.rb b/lib/open_food_network/feature_toggle.rb
index 5ee51a82f9..f57e740bc4 100644
--- a/lib/open_food_network/feature_toggle.rb
+++ b/lib/open_food_network/feature_toggle.rb
@@ -30,11 +30,9 @@ module OpenFoodNetwork
new.enabled?(feature_name, user)
end
- def self.enable(feature_name, user_emails)
- return unless user_emails.present?
-
+ def self.enable(feature_name, &block)
Thread.current[:features] ||= {}
- Thread.current[:features][feature_name] = Feature.new(user_emails)
+ Thread.current[:features][feature_name] = Feature.new(block)
end
def initialize
@@ -68,17 +66,17 @@ module OpenFoodNetwork
end
class Feature
- def initialize(users = [])
- @users = users
+ def initialize(block)
+ @block = block
end
def enabled?(user)
- users.include?(user.email)
+ block.call(user)
end
private
- attr_reader :users
+ attr_reader :block
end
class NullFeature
diff --git a/lib/spree/core/calculated_adjustments.rb b/lib/spree/core/calculated_adjustments.rb
index 6388369209..301d821642 100644
--- a/lib/spree/core/calculated_adjustments.rb
+++ b/lib/spree/core/calculated_adjustments.rb
@@ -43,7 +43,8 @@ module Spree
order: order_object_for(target),
label: label,
mandatory: mandatory,
- state: state
+ state: state,
+ included: tax_included?(self, target)
)
end
@@ -78,6 +79,15 @@ module Spree
private
+ # Used for setting the #included boolean on tax adjustments. This will be removed in a
+ # later step, as the responsibility for creating all adjustments related to tax will be
+ # moved into the Spree::TaxRate class.
+ def tax_included?(originator, target)
+ originator.is_a?(Spree::TaxRate) &&
+ originator.included_in_price &&
+ originator.default_zone_or_zone_match?(order_object_for(target))
+ end
+
def order_object_for(target)
# Temporary method for adjustments transition.
if target.is_a? Spree::Order
diff --git a/lib/spree/i18n.rb b/lib/spree/i18n.rb
index 39bd4590cd..a1ab621b0d 100644
--- a/lib/spree/i18n.rb
+++ b/lib/spree/i18n.rb
@@ -6,7 +6,7 @@ require 'spree/i18n/base'
module Spree
extend ActionView::Helpers::TranslationHelper
- extend ActionView::Helpers::TagHelper if ENV['DEPENDENCIES_NEXT']
+ extend ActionView::Helpers::TagHelper
class << self
# Add spree namespace and delegate to Rails TranslationHelper for some nice
diff --git a/spec/controllers/admin/enterprises_controller_spec.rb b/spec/controllers/admin/enterprises_controller_spec.rb
index 507f840710..0a4e00b472 100644
--- a/spec/controllers/admin/enterprises_controller_spec.rb
+++ b/spec/controllers/admin/enterprises_controller_spec.rb
@@ -69,7 +69,7 @@ describe Admin::EnterprisesController, type: :controller do
admin_user.enterprises << create(:distributor_enterprise)
allow(controller).to receive_messages spree_current_user: admin_user
- enterprise_params[:enterprise][:owner_id] = admin_user
+ enterprise_params[:enterprise][:owner_id] = admin_user.id
enterprise_params[:enterprise][:sells] = 'none'
spree_put :create, enterprise_params
@@ -91,7 +91,7 @@ describe Admin::EnterprisesController, type: :controller do
it "doesn't affect the hub status for super admins" do
allow(controller).to receive_messages spree_current_user: admin_user
- enterprise_params[:enterprise][:owner_id] = admin_user
+ enterprise_params[:enterprise][:owner_id] = admin_user.id
enterprise_params[:enterprise][:sells] = 'any'
spree_put :create, enterprise_params
@@ -198,7 +198,7 @@ describe Admin::EnterprisesController, type: :controller do
enterprise: {
tag_rules_attributes: {
'0' => {
- id: tag_rule,
+ id: tag_rule.id,
type: "TagRule::DiscountOrder",
preferred_customer_tags: "some,new,tags",
calculator_type: "Calculator::FlatPercentItemTotal",
@@ -246,7 +246,7 @@ describe Admin::EnterprisesController, type: :controller do
it "allows owner to be changed" do
allow(controller).to receive_messages spree_current_user: distributor_owner
- update_params = { id: distributor, enterprise: { owner_id: distributor_manager } }
+ update_params = { id: distributor, enterprise: { owner_id: distributor_manager.id } }
spree_post :update, update_params
distributor.reload
@@ -275,7 +275,7 @@ describe Admin::EnterprisesController, type: :controller do
it "allows owner to be changed" do
allow(controller).to receive_messages spree_current_user: admin_user
- update_params = { id: distributor, enterprise: { owner_id: distributor_manager } }
+ update_params = { id: distributor, enterprise: { owner_id: distributor_manager.id } }
spree_post :update, update_params
distributor.reload
diff --git a/spec/controllers/api/exchange_products_controller_spec.rb b/spec/controllers/api/exchange_products_controller_spec.rb
index d9aa7ce55c..a0ae941c8a 100644
--- a/spec/controllers/api/exchange_products_controller_spec.rb
+++ b/spec/controllers/api/exchange_products_controller_spec.rb
@@ -26,7 +26,7 @@ module Api
let(:products_relation) { Spree::Product.where("1=0") }
it "handles it gracefully" do
- get :index, exchange_id: exchange.id
+ api_get :index, exchange_id: exchange.id
expect(json_response["products"].length).to eq 0
end
end
@@ -36,14 +36,14 @@ module Api
describe "when an exchange id param is provided" do
it "uses exchange order_cycle, incoming and enterprise to fetch products" do
- get :index, exchange_id: exchange.id, order_cycle_id: 666, enterprise_id: 666, incoming: false
+ api_get :index, exchange_id: exchange.id, order_cycle_id: 666, enterprise_id: 666, incoming: false
expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name
end
end
describe "when an exchange id param is not provided" do
it "uses params order_cycle, incoming and enterprise to fetch products" do
- spree_get :index, order_cycle_id: order_cycle.id, enterprise_id: exchange.sender_id, incoming: true
+ api_get :index, order_cycle_id: order_cycle.id, enterprise_id: exchange.sender_id, incoming: true
expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name
end
end
@@ -59,7 +59,7 @@ module Api
describe "when a specific page is requested" do
it "returns the requested page with paginated data" do
- get :index, exchange_id: exchange.id, page: 1
+ api_get :index, exchange_id: exchange.id, page: 1
expect(json_response["products"].size).to eq 1
expect(json_response["pagination"]["results"]).to eq 2
@@ -69,7 +69,7 @@ module Api
describe "when no specific page is requested" do
it "returns all results without paginating" do
- get :index, exchange_id: exchange.id
+ api_get :index, exchange_id: exchange.id
expect(json_response["products"].size).to eq 2
expect(json_response["pagination"]).to be nil
diff --git a/spec/controllers/spree/admin/orders/payments/payments_controller_spec.rb b/spec/controllers/spree/admin/orders/payments/payments_controller_spec.rb
index 1e1437aee2..a6ed887d61 100644
--- a/spec/controllers/spree/admin/orders/payments/payments_controller_spec.rb
+++ b/spec/controllers/spree/admin/orders/payments/payments_controller_spec.rb
@@ -174,7 +174,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
let(:params) { { e: 'credit', order_id: order.number, id: payment.id } }
before do
- allow(request).to receive(:referer) { 'http://foo.com' }
+ request.env["HTTP_REFERER"] = "http://foo.com"
allow(Spree::Payment).to receive(:find).with(payment.id.to_s) { payment }
end
@@ -210,7 +210,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
let(:params) { { e: 'refund', order_id: order.number, id: payment.id } }
before do
- allow(request).to receive(:referer) { 'http://foo.com' }
+ request.env["HTTP_REFERER"] = "http://foo.com"
allow(Spree::Payment).to receive(:find).with(payment.id.to_s) { payment }
end
@@ -248,7 +248,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
before do
allow(PaymentMailer).to receive(:authorize_payment) { mail_mock }
- allow(request).to receive(:referer) { 'http://foo.com' }
+ request.env["HTTP_REFERER"] = "http://foo.com"
allow(Spree::Payment).to receive(:find).with(payment.id.to_s) { payment }
allow(payment).to receive(:cvv_response_message).and_return("https://www.stripe.com/authorize")
end
@@ -266,7 +266,7 @@ describe Spree::Admin::PaymentsController, type: :controller do
let(:params) { { e: 'unrecognized_event', order_id: order.number, id: payment.id } }
before do
- allow(request).to receive(:referer) { 'http://foo.com' }
+ request.env["HTTP_REFERER"] = "http://foo.com"
allow(Spree::Payment).to receive(:find).with(payment.id.to_s) { payment }
end
diff --git a/spec/controllers/spree/admin/tax_rates_controller_spec.rb b/spec/controllers/spree/admin/tax_rates_controller_spec.rb
index 266edc9430..8bef1f2fb1 100644
--- a/spec/controllers/spree/admin/tax_rates_controller_spec.rb
+++ b/spec/controllers/spree/admin/tax_rates_controller_spec.rb
@@ -20,7 +20,7 @@ module Spree
context "when the amount is not changed" do
it "updates the record" do
expect {
- spree_put :update, id: tax_rate.id, tax_rate: { name: "Updated Rate", amount: 0.1 }
+ spree_put :update, id: tax_rate.id, tax_rate: { name: "Updated Rate", amount: "0.1" }
}.to_not change{ Spree::TaxRate.with_deleted.count }
expect(response).to redirect_to spree.admin_tax_rates_url
@@ -32,7 +32,7 @@ module Spree
context "when the amount is changed" do
it "duplicates the record and soft-deletes the duplicate" do
expect {
- spree_put :update, id: tax_rate.id, tax_rate: { name: "Changed Rate", amount: 0.5 }
+ spree_put :update, id: tax_rate.id, tax_rate: { name: "Changed Rate", amount: "0.5" }
}.to change{ Spree::TaxRate.with_deleted.count }.by(1)
expect(response).to redirect_to spree.admin_tax_rates_url
diff --git a/spec/features/admin/enterprise_roles_spec.rb b/spec/features/admin/enterprise_roles_spec.rb
index 0e0cbd5237..4720e36334 100644
--- a/spec/features/admin/enterprise_roles_spec.rb
+++ b/spec/features/admin/enterprise_roles_spec.rb
@@ -117,7 +117,7 @@ feature '
end
end
- it "allows adding new managers" do
+ xit "allows adding new managers" do
within 'table.managers' do
select2_select user3.email, from: 'ignored', search: true
@@ -129,7 +129,7 @@ feature '
end
end
- it "shows changes to enterprise contact or owner" do
+ xit "shows changes to enterprise contact or owner" do
select2_select user2.email, from: 'receives_notifications_dropdown'
within('#save-bar') { click_button 'Update' }
navigate_to_enterprise_users
@@ -146,7 +146,7 @@ feature '
end
end
- it "can invite unregistered users to be managers" do
+ xit "can invite unregistered users to be managers" do
setup_email
find('a.button.help-modal').click
expect(page).to have_css '#invite-manager-modal'
diff --git a/spec/initializers/feature_toggles_spec.rb b/spec/initializers/feature_toggles_spec.rb
new file mode 100644
index 0000000000..0433d4508b
--- /dev/null
+++ b/spec/initializers/feature_toggles_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe 'config/initializers/feature_toggles.rb' do
+ # Executes the initializer's code block by reading the Ruby file. Note that `Kernel#require` would
+ # prevent this from happening twice.
+ subject(:execute_initializer) do
+ load Rails.root.join('config/initializers/feature_toggles.rb')
+ end
+
+ let(:user) { build(:user) }
+
+ around do |example|
+ original = ENV['BETA_TESTERS']
+ example.run
+ ENV['BETA_TESTERS'] = original
+ end
+
+ context 'when beta_testers is ["all"]' do
+ before { ENV['BETA_TESTERS'] = 'all' }
+
+ it 'returns true' do
+ execute_initializer
+
+ enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user)
+ expect(enabled).to eq(true)
+ end
+ end
+
+ context 'when beta_testers is a list of emails' do
+ let(:other_user) { build(:user) }
+
+ context 'and the user is in the list' do
+ before { ENV['BETA_TESTERS'] = "#{user.email}, #{other_user.email}" }
+
+ it 'enables the feature' do
+ execute_initializer
+
+ enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user)
+ expect(enabled).to eq(true)
+ end
+ end
+
+ context 'and the user is not in the list' do
+ before { ENV['BETA_TESTERS'] = "#{other_user.email}" }
+
+ it 'disables the feature' do
+ execute_initializer
+
+ enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user)
+ expect(enabled).to eq(false)
+ end
+ end
+
+ context 'and the list is empty' do
+ before { ENV['BETA_TESTERS'] = '' }
+
+ it 'disables the feature' do
+ execute_initializer
+
+ enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user)
+ expect(enabled).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/open_food_network/feature_toggle_spec.rb b/spec/lib/open_food_network/feature_toggle_spec.rb
index 73407d671d..d9904b0fd6 100644
--- a/spec/lib/open_food_network/feature_toggle_spec.rb
+++ b/spec/lib/open_food_network/feature_toggle_spec.rb
@@ -32,19 +32,25 @@ module OpenFoodNetwork
context 'when specifying users' do
let(:user) { build(:user) }
- context 'and the feature is enabled for them' do
- before { FeatureToggle.enable(:foo, [user.email]) }
+ context 'and the block does not specify arguments' do
+ before do
+ FeatureToggle.enable(:foo) { 'return value' }
+ end
- it 'returns true' do
- expect(FeatureToggle.enabled?(:foo, user)).to eq(true)
+ it "returns the block's return value" do
+ expect(FeatureToggle.enabled?(:foo, user)).to eq('return value')
end
end
- context 'and the feature is disabled for them' do
- before { FeatureToggle.enable(:foo, []) }
+ context 'and the block specifies arguments' do
+ let(:users) { [user.email] }
- it 'returns false' do
- expect(FeatureToggle.enabled?(:foo, user)).to eq(false)
+ before do
+ FeatureToggle.enable(:foo) { |user| users.include?(user.email) }
+ end
+
+ it "returns the block's return value" do
+ expect(FeatureToggle.enabled?(:foo, user)).to eq(true)
end
end
end
diff --git a/spec/models/spree/adjustment_spec.rb b/spec/models/spree/adjustment_spec.rb
index de6bdb1f98..0fab3d3cbd 100644
--- a/spec/models/spree/adjustment_spec.rb
+++ b/spec/models/spree/adjustment_spec.rb
@@ -460,5 +460,65 @@ module Spree
context "extends LocalizedNumber" do
it_behaves_like "a model using the LocalizedNumber module", [:amount]
end
+
+ describe "inclusive and additional taxes" do
+ let!(:zone) { create(:zone_with_member) }
+ let!(:tax_category) { create(:tax_category, name: "Tax Test") }
+ let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) }
+ let(:order) { create(:order, distributor: distributor) }
+ let(:included_in_price) { true }
+ let(:tax_rate) {
+ create(:tax_rate, included_in_price: included_in_price, zone: zone,
+ calculator: ::Calculator::FlatRate.new(preferred_amount: 0.1))
+ }
+ let(:product) { create(:product, tax_category: tax_category) }
+ let(:variant) { product.variants.first }
+
+ describe "tax adjustment creation" do
+ before do
+ tax_category.tax_rates << tax_rate
+ allow(order).to receive(:tax_zone) { zone }
+ order.line_items << create(:line_item, variant: variant, quantity: 5)
+ end
+
+ context "with included taxes" do
+ it "records the tax as included" do
+ expect(order.all_adjustments.tax.count).to eq 1
+ expect(order.all_adjustments.tax.first.included).to be true
+ end
+ end
+
+ context "with additional taxes" do
+ let(:included_in_price) { false }
+
+ it "records the tax as additional" do
+ expect(order.all_adjustments.tax.count).to eq 1
+ expect(order.all_adjustments.tax.first.included).to be false
+ end
+ end
+ end
+
+ describe "inclusive and additional scopes" do
+ let(:included) { true }
+ let(:adjustment) {
+ create(:adjustment, adjustable: order, source: order,
+ originator: tax_rate, included: included)
+ }
+
+ context "when tax is included in price" do
+ it "is returned by the #included scope" do
+ expect(Spree::Adjustment.inclusive).to eq [adjustment]
+ end
+ end
+
+ context "when tax is additional to the price" do
+ let(:included) { false }
+
+ it "is returned by the #additional scope" do
+ expect(Spree::Adjustment.additional).to eq [adjustment]
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/models/spree/shipment_spec.rb b/spec/models/spree/shipment_spec.rb
index f5e846bca6..9fecb237b9 100644
--- a/spec/models/spree/shipment_spec.rb
+++ b/spec/models/spree/shipment_spec.rb
@@ -50,13 +50,6 @@ describe Spree::Shipment do
end
end
- context "display_total_cost" do
- it "retuns a Spree::Money" do
- allow(shipment).to receive(:total_cost) { 21.22 }
- expect(shipment.display_total_cost).to eq Spree::Money.new(21.22)
- end
- end
-
it "#item_cost" do
shipment = Spree::Shipment.new(
order: build_stubbed(:order_with_totals, line_items: [build_stubbed(:line_item)])
@@ -181,12 +174,6 @@ describe Spree::Shipment do
end
end
- it '#total_cost' do
- allow(shipment).to receive_messages cost: 5.0
- allow(shipment).to receive_messages item_cost: 50.0
- expect(shipment.total_cost).to eql(55.0)
- end
-
context "#update!" do
shared_examples_for "immutable once shipped" do
it "should remain in shipped state once shipped" do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 62c67e9417..37fee324a5 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -101,6 +101,10 @@ RSpec.configure do |config|
# Retry
config.verbose_retry = true
+ # Try twice (retry once)
+ config.default_retry_count = 2
+ # Only retry when Selenium raises Net::ReadTimeout
+ config.exceptions_to_retry = [Net::ReadTimeout]
# Force use of expect (over should)
config.expect_with :rspec do |expectations|