Files
openfoodnetwork/lib/open_food_network/address_finder.rb
David Cook 0225db6840 Refactor without setter methods
This class was originally built to flexibly accept paramters in any order. It also allowed you to specify multiple of the same type of parameter, with the later one overriding the earlier.

This is too flexible and likely to cause mistakes. And besides, we don't use that feature!
2025-05-05 12:59:27 +10:00

83 lines
2.4 KiB
Ruby

# frozen_string_literal: true
# Finds an address based on the data provided
# Can take any combination of an email String, Customer or Spree::User as args
# The #bill_address and #ship_address methods automatically return matched addresses
# according to this order: customer addresses, user addresses, addresses from
# completed orders with an email that matches the email string provided.
module OpenFoodNetwork
class AddressFinder
attr_reader :email, :user, :customer
def initialize(email: nil, user: nil, customer: nil)
@email = email
@user = user
@customer = customer
end
def bill_address
customer_preferred_bill_address || user_preferred_bill_address || fallback_bill_address
end
def ship_address
customer_preferred_ship_address || user_preferred_ship_address || fallback_ship_address
end
private
def customer_preferred_bill_address
customer&.bill_address
end
def customer_preferred_ship_address
customer&.ship_address
end
def user_preferred_bill_address
user&.bill_address
end
def user_preferred_ship_address
user&.ship_address
end
def fallback_bill_address
last_used_bill_address&.clone || Spree::Address.default
end
def fallback_ship_address
last_used_ship_address&.clone || Spree::Address.default
end
def last_used_bill_address
return nil unless allow_search_by_email?
Spree::Order.joins(:bill_address).order('id DESC')
.complete.where(email:)
.first&.bill_address
end
def last_used_ship_address
return nil unless allow_search_by_email?
Spree::Order.complete.joins(:ship_address, shipments: :shipping_methods).order('id DESC')
.where(email:, spree_shipping_methods: { require_ship_address: true })
.first&.ship_address
end
# Only allow search for address by email if a customer or user with the
# same address has been provided, otherwise we are providing access to
# addresses with only an email address, which could be problematic.
# Assumption: front-end users can't ask this library for an address using
# a customer or user other than themselves...
def allow_search_by_email?
email.present? && email_matches_customer_or_user?
end
def email_matches_customer_or_user?
email == customer&.email || email == user&.email
end
end
end