Merge branch 'master' into fix-#13264

This commit is contained in:
Jordan Mock
2025-04-24 13:13:37 +01:00
committed by GitHub
14 changed files with 77 additions and 162 deletions

View File

@@ -1,3 +0,0 @@
= t('spree.payment_mailer.authorization_required.message', order_number: @order.number)
= link_to spree.edit_admin_order_url(@order), spree.edit_admin_order_url(@order)

View File

@@ -1,3 +0,0 @@
= t('spree.payment_mailer.authorize_payment.instructions', distributor: @payment.order.distributor.name, amount: @payment.display_amount)
= link_to main_app.authorize_payment_url(@payment), main_app.authorize_payment_url(@payment)

View File

@@ -1,36 +0,0 @@
#{t :producer_mail_greeting} #{raw(@producer.name)},
\
= t :producer_mail_text_before
\
- @distributors_pickup_times.each do |distributor_name, pickup_time|
\- #{raw(distributor_name)} (#{pickup_time})
\
- if @receival_instructions
= t :producer_mail_delivery_instructions
= raw(@receival_instructions)
\
Orders summary
================
\
= t :producer_mail_order_text
\
- @grouped_line_items.each_pair do |product_and_full_name, line_items|
#{line_items.first.variant.sku} - #{raw(line_items.first.variant.supplier.name)} - #{raw(product_and_full_name)} (#{t(:producer_mail_qty)}: #{line_items.sum(&:quantity)}) @ #{line_items.first.single_money} = #{Spree::Money.new(line_items.sum(&:total), currency: line_items.first.currency)} (#{t(:with_tax_incl, amount: Spree::Money.new(line_items.sum(&:included_tax), currency: line_items.first.currency))})
\
\
#{t :total}: #{@total} (#{t(:with_tax_incl, amount: @tax_total)})
\
- if @customer_line_items
= t :producer_mail_order_customer_text
\
- @customer_line_items.each do |line_item|
#{line_item[:sku]} - #{raw(line_item[:supplier_name])} - #{raw(line_item[:product_and_full_name])} (#{t(:producer_mail_qty)}: #{line_item[:quantity]}) - #{raw(line_item[:first_name])} #{raw(line_item[:last_name])} #{raw(line_item[:business_name])}
\
\
= t :producer_mail_text_after
#{t :producer_mail_signoff},
#{raw(@coordinator.name)}
#{raw(@coordinator.address.address1)}, #{raw(@coordinator.address.city)}, #{raw(@coordinator.address.zipcode)}
#{@coordinator.phone}
#{@coordinator.contact.email}

View File

@@ -1,9 +0,0 @@
<%= t(:email_signup_greeting) %>
<%= t(:email_signup_welcome, sitename: Spree::Config[:site_name]) %>
<%= t(:email_confirmation_activate_account) %>
<%= t(:email_confirmation_click_link) %>
<%= link_to t(:email_confirmation_link_label), spree.spree_user_confirmation_url(confirmation_token: @user.confirmation_token) %>

View File

@@ -1,7 +0,0 @@
<%= t('.request_sent_text') %>
<%= t('.link_text') %>
<%= @edit_password_reset_url %>
<%= t('.issue_text') %>

View File

@@ -1,14 +0,0 @@
Hello,
Welcome to Open Food Network UK! Your login email is <%= @user.email %>
You can go online and start shopping through food hubs and local producers you like at http://openfoodnetwork.org.uk
We welcome all your questions and feedback; you can use the Send Feedback button on the site or email us at hello@openfoodnetwork.org.
Thanks for getting on board and we look forward to introducing you to many more great farmers, food hubs and food!
Cheers,
The Open Food Network UK team

View File

@@ -783,9 +783,18 @@ en_FR:
connection_invalid_html: |
Connecting with your OIDC account failed.
Please refresh your OIDC connection at: %{oidc_settings_link}
absent_variant:
reset: "Reset stock"
index:
title: "DFC product catalog"
catalog_url: "%{count} products to be imported from: %{catalog_url}"
absent_products:
one: |
One product is no longer in the catalog.
It will be marked as unavailable by resetting stock to zero.
other: |
%{count} products are no longer in the catalog.
They will be marked as unavailable by resetting stock to zero.
enterprise: "Import to enterprise: %{enterprise_name}"
select_all: "Select/deselect all"
update: Update
@@ -798,6 +807,8 @@ en_FR:
invalid_url: This catalog URL is not valid.
import:
title: "DFC product catalog import"
imported_products: "Imported products: %{count}"
reset_products: "Stock reset for absent products: %{count}"
enterprise_fees:
index:
title: "Enterprise Fees"
@@ -1274,6 +1285,8 @@ en_FR:
enable_subscriptions_true: "Enabled"
customer_names_in_reports: "Customer Names in Reports"
customer_names_tip: "Enable your suppliers to see your customers names in reports"
producers_to_edit_orders: "Ability for producers to edit orders"
producers_to_edit_orders_tip: "Enable your suppliers to see orders containing their products, and edit quantity and weight for their own products only."
customer_names_false: "Disabled"
customer_names_true: "Enabled"
customer_contacts_in_reports: "Customer contact details in reports"
@@ -1693,6 +1706,7 @@ en_FR:
email_confirmation: "Email confirmation is pending. We've sent a confirmation email to %{email}."
not_visible: "%{enterprise} is not visible and so cannot be found on the map or in searches"
reports:
none: none
deprecated: "This report is deprecated and will be removed in a future release."
hidden_field: "< Hidden >"
unitsize: UNITSIZE

View File

@@ -145,6 +145,10 @@ es:
title: "El cambio deseado ha sido rechazado (422)"
general_error:
message: "Lo sentimos, pero algo ha ido mal.\n\nPuede que se trate de un problema temporal, así que inténtalo de nuevo o recarga la página.\nRegistramos todos los errores y es posible que estemos trabajando en una solución.\nSi el problema persiste o es urgente, póngase en contacto con nosotras."
unauthorized:
message: "No tiene autorización para realizar esta acción."
network_error:
message: "Error en la red: intentalo más tarde"
stripe:
error_code:
incorrect_number: "El número de tarjeta es incorrecto."
@@ -760,9 +764,15 @@ es:
user_guide: Manual de Usuario
map: Mapa
dfc_product_imports:
absent_variant:
reset: "Restablecer stock"
index:
update: Actualizar
new: Nuevo
selected:
zero: "0 seleccionados"
one: "1 seleccionados"
other: "%{count} seleccionados"
import: Importar
enterprise_fees:
index:
@@ -879,6 +889,7 @@ es:
category_field_name: "Categoría"
tax_category_field_name: "Categoría de impuestos"
producer_field_name: "Productora"
select_unit_scale: Seleccionar escala de la unidad
clone:
success: Se ha clonado el producto
error: No se ha podido clonar el producto
@@ -1177,6 +1188,7 @@ es:
visible: Pública
not_visible: Oculto
hidden: Ocultar todas las referencias
admin_only_legend: Solo administradores
properties:
legend: "Propiedades"
permalink:
@@ -3695,6 +3707,7 @@ es:
last: "Último"
spree:
order_updated: "Pedido actualizado"
cannot_perform_operation: "No se puede realizar esta operación."
add_country: "Agregar pais"
add_state: "Agregar estado"
adjustment: "Ajuste"
@@ -4207,6 +4220,9 @@ es:
title: "Nuevo producto"
new_product: "Nuevo producto"
supplier: "Proveedora"
supplier_select_placeholder: "Seleccionar proveedora"
search_for_suppliers: "Buscar proveedoras"
search_for_units: "Buscar unidades"
product_name: "nombre del producto"
units: "Unidad de medida"
value: "Valor"
@@ -4247,9 +4263,12 @@ es:
bulk_unit_size: Tamaño de la unidad a granel
display_as:
display_as: Mostrar como
clone:
success: Producto clonado
reports:
table:
select_and_search: "Seleccione filtros y haga clic en %{option} para acceder a sus datos."
hidden_customer_details_tip: "Si los nombres y/o los datos de contacto de las consumidoras están ocultos, puede solicitar a la distribuidora que actualice las preferencias de su tienda para permitir que sus proveedores vean los datos de las consumidoras en los informes."
users:
index:
listing_users: "Listado de Usuarias"
@@ -4408,6 +4427,7 @@ es:
invoice_attached_text: Adjunta una factura para su pedido reciente de
user_mailer:
reset_password_instructions:
dear_customer: "Estimada consumidora,"
request_sent_text: |
Se ha solicitado el cambio de tu contraseña.
Si tu no lo has solicitado simplemente ignora este email.
@@ -4483,6 +4503,7 @@ es:
users:
api_keys:
regenerate_key: "Regenerar llave"
title: API key
webhook_endpoints:
description: Los eventos del sistema pueden desencadenar webhooks a sistemas externos.
event_types:
@@ -4618,6 +4639,7 @@ es:
search_input:
placeholder: Buscar
selector_with_filter:
selected_items: "%{count} seleccionados"
search_placeholder: Buscar
pagination:
next: Siguiente

View File

@@ -782,9 +782,18 @@ fr:
connection_invalid_html: |
La connexion avec votre compte OIDC a échoué.
Merci de rafraîchir votre connexion OIDC à : %{oidc_settings_link}
absent_variant:
reset: "Réinitialiser le stock"
index:
title: "Catalogue produit DFC"
catalog_url: "%{count} produits à importer de : %{catalog_url}"
absent_products:
one: |
Un produit n'est plus dans le catalogue produits.
Il sera marqué indisponible quand vous remettrez votre stock à zéro.
other: |
%{count} produits ne sont plus dans votre catalogue produits.
Ils seront marqués indisponibles quand vous remettrez votre stock à zéro.
enterprise: "Import vers l'entreprise : %{enterprise_name}"
select_all: "Sélectionner / désélectionner tout"
update: Mettre à jour
@@ -797,6 +806,8 @@ fr:
invalid_url: L'URL de ce catalogue n'est pas valide.
import:
title: "Import du catalogue produit DFC"
imported_products: "Produits importés : %{count}"
reset_products: "Réinitialiser le stock pour les produits absents : %{count}"
enterprise_fees:
index:
title: "Marges et Commissions"
@@ -1276,6 +1287,8 @@ fr:
enable_subscriptions_true: "Activé"
customer_names_in_reports: "Affichage du nom des acheteurs"
customer_names_tip: "Permettre aux producteurs de voir les noms de vos acheteurs"
producers_to_edit_orders: "Possibilité pour les producteurs de modifier les commandes"
producers_to_edit_orders_tip: "Permettre à vos fournisseurs de visualiser les commandes comprenant leurs produits et de modifier la quantité et le poids de leurs produits seulement."
customer_names_false: "Désactivé"
customer_names_true: "Activé"
customer_contacts_in_reports: "Affichage des contacts clients"
@@ -1695,6 +1708,7 @@ fr:
email_confirmation: "L'adresse e-mail doit être confirmée. Nous avons envoyé un lien de confirmation à %{email}."
not_visible: "%{enterprise} n'est pas visible et ne peut être trouvé sur la carte ou dans les recherches sur le site."
reports:
none: aucun
deprecated: "Ce rapport est obsolète et ne sera bientôt plus disponible (sera supprimé dans une prochaine mise à jour)."
hidden_field: "< Masqué >"
unitsize: Unité de mesure

View File

@@ -265,7 +265,6 @@ RSpec.configure do |config|
config.include OpenFoodNetwork::PerformanceHelper
config.include ActiveJob::TestHelper
config.include ReportsHelper
config.include MailersHelper, type: :mailer
config.include TomSelectHelper, type: :system
config.include ViewComponent::TestHelpers, type: :component

View File

@@ -26,8 +26,7 @@ RSpec.describe PaymentMailer do
it "includes a link to authorize the payment" do
link = "http://test.host/payments/#{payment.id}/authorize"
expect(email.text_part.body).to match link
expect(html_body(email)).to have_link link, href: link
expect(email.body).to have_link link, href: link
end
end

View File

@@ -60,6 +60,7 @@ RSpec.describe ProducerMailer, type: :mailer do
end
let(:mail) { ProducerMailer.order_cycle_report(s1, order_cycle) }
let(:parsed_email) { Capybara::Node::Simple.new(mail.body.encoded) }
it "sets a reply-to of the oc coordinator's email" do
expect(mail.reply_to).to eq [order_cycle.coordinator.contact.email]
@@ -78,22 +79,21 @@ RSpec.describe ProducerMailer, type: :mailer do
end
it "contains an aggregated list of produce in alphabetical order" do
expect(mail.body.encoded).to match(/coffee.+\n.+Zebra/)
body_lines_including(mail, p1.name).each do |line|
expect(line).to include 'QTY: 3'
expect(line).to include '@ $10.00 = $30.00'
rows = parsed_email.all('table.order-summary tbody tr:not(.total-row)')
actual = rows.map do |row|
row.all('td').map { |td| td.text.strip }
end
expect(html_body(mail).find("table.order-summary tr", text: p1.name))
.to have_selector("td", text: "$30.00")
expected = [
['', 'coffee - 1g', '2', '$10.00', '$20.00', '$0.00'],
['', 'Zebra - 1g', '3', '$10.00', '$30.00', '$2.73']
]
expect(actual).to eq(expected)
end
it "displays tax totals for each product" do
# Tax for p1 line items
expect(html_body(mail).find("table.order-summary tr", text: p1.name))
expect(parsed_email.find("table.order-summary tr", text: p1.name))
.to have_selector("td.tax", text: "$2.73")
expect(
product_line_from_order_summary_text(mail, p1.name)
).to include("($2.73 tax incl.)")
end
it "does not include incomplete orders" do
@@ -121,9 +121,7 @@ RSpec.describe ProducerMailer, type: :mailer do
end
it "includes the total" do
expect(mail.body.encoded).to include 'Total: $50.00'
expect(html_body(mail).find("tr.total-row"))
.to have_selector("td", text: "$50.00")
expect(parsed_email.find("tr.total-row")).to have_selector("td", text: "$50.00")
end
it "sends no mail when the producer has no orders" do
@@ -151,28 +149,16 @@ RSpec.describe ProducerMailer, type: :mailer do
end
it "adds customer names table" do
expect(html_body(mail).find(".order-summary.customer-order")).not_to be_nil
expect(customer_details_summary_text(mail)).to be_present
expect(parsed_email).to have_selector(".order-summary.customer-order")
end
it "displays last name for each order" do
it "displays last name and first name for each order" do
product_name = order.line_items.first.product.name
last_name = order.billing_address.lastname
expect(html_body(mail).find("table.order-summary.customer-order tr",
text: product_name)).to have_selector("td", text: last_name)
expect(
product_line_from_details_summary_text(mail, product_name)
).to include(last_name)
end
it "displays first name for each order" do
product_name = order.line_items.first.product.name
first_name = order.billing_address.firstname
expect(html_body(mail).find("table.order-summary.customer-order tr",
text: product_name)).to have_selector("td", text: first_name)
expect(
product_line_from_details_summary_text(mail, product_name)
).to include(first_name)
row = parsed_email.find("table.order-summary.customer-order tbody tr")
expect(row).to have_selector("td", text: last_name)
expect(row).to have_selector("td", text: first_name)
end
it "it orders list via last name" do
@@ -181,18 +167,16 @@ RSpec.describe ProducerMailer, type: :mailer do
create(:order, :with_line_item, distributor: d1, order_cycle:, state: 'complete',
bill_address: FactoryBot.create(:address, last_name: "smith"))
expect(mail.body.encoded).to match(/.*Abby.*Doe.*smith/m)
expect(customer_details_summary_text(mail)).to include('Abby', 'Doe', 'smith')
end
context "validate business name" do
let(:table_header) do
html_body(mail).find("table.order-summary.customer-order thead")
parsed_email.find("table.order-summary.customer-order thead")
end
context "when no customer has customer code" do
it 'should not displays business name column' do
it 'should not display business name column' do
expect(table_header).not_to have_selector("th", text: 'Business Name')
expect(customer_details_summary_text(mail)).not_to include('Test Business Name')
end
end
@@ -201,10 +185,8 @@ RSpec.describe ProducerMailer, type: :mailer do
it 'displays business name for the customer' do
expect(table_header).to have_selector("th", text: 'Business Name')
expect(
html_body(mail).find("table.order-summary.customer-order tbody tr")
).to have_selector("td", text: 'Test Business Name')
expect(customer_details_summary_text(mail)).to include('Test Business Name')
expect(parsed_email.find("table.order-summary.customer-order tbody tr"))
.to have_selector("td", text: 'Test Business Name')
end
end
end
@@ -217,9 +199,8 @@ RSpec.describe ProducerMailer, type: :mailer do
it "does not add customer names table" do
expect {
html_body(mail).find(".order-summary.customer-order")
parsed_email.find(".order-summary.customer-order")
}.to raise_error(Capybara::ElementNotFound)
expect(customer_details_summary_text(mail)).to be_nil
end
end
@@ -236,7 +217,7 @@ RSpec.describe ProducerMailer, type: :mailer do
end
it "displays a supplier column" do
expect(html_body(mail).find(".order-summary"))
expect(parsed_email.find(".order-summary"))
.to have_selector("th", text: "Supplier")
end
@@ -244,7 +225,7 @@ RSpec.describe ProducerMailer, type: :mailer do
before { order_cycle.coordinator.update!(show_customer_names_to_suppliers: true) }
it "displays a supplier column in the summary of orders grouped by customer" do
expect(html_body(mail).find(".customer-order"))
expect(parsed_email.find(".customer-order"))
.to have_selector("th", text: "Supplier")
end
end
@@ -252,7 +233,7 @@ RSpec.describe ProducerMailer, type: :mailer do
context "products from only one supplier" do
it "doesn't display a supplier column" do
expect(html_body(mail).find(".order-summary"))
expect(parsed_email.find(".order-summary"))
.not_to have_selector("th", text: "Supplier")
end
@@ -260,43 +241,9 @@ RSpec.describe ProducerMailer, type: :mailer do
before { order_cycle.coordinator.update!(show_customer_names_to_suppliers: true) }
it "doesn't display a supplier column in the summary of orders grouped by customer" do
expect(html_body(mail).find(".customer-order"))
expect(parsed_email.find(".customer-order"))
.not_to have_selector("th", text: "Supplier")
end
end
end
private
def body_lines_including(mail, str)
mail.body.to_s.lines.select { |line| line.include? str }
end
def body_as_text(mail)
mail.text_part.body.decoded
end
def customer_details_summary_text(mail)
body_as_text(mail)
.split(I18n.t(:producer_mail_order_customer_text))
.second
end
def product_line_from_details_summary_text(mail, product_name)
summary = customer_details_summary_text(mail)
product_line_by_summary(summary, product_name)
end
def product_line_from_order_summary_text(mail, product_name)
summary = body_as_text(mail)
.split(I18n.t(:producer_mail_order_customer_text))
.first
product_line_by_summary(summary, product_name)
end
def product_line_by_summary(summary, product_name)
return '' unless summary
summary.lines.find { |line| line.include?(product_name) } || ''
end
end

View File

@@ -81,8 +81,7 @@ RSpec.describe Spree::UserMailer do
context 'body includes' do
it 'password reset url' do
expect(mail.text_part.body).to include spree.edit_spree_user_password_url
expect(mail.html_part.body).to include spree.edit_spree_user_password_url
expect(mail.body).to include spree.edit_spree_user_password_url
end
end

View File

@@ -1,7 +0,0 @@
# frozen_string_literal: true
module MailersHelper
def html_body(mail)
Capybara.string(mail.html_part.body.to_s)
end
end