mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-26 20:56:48 +00:00
87 lines
2.1 KiB
Ruby
87 lines
2.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class OrderInvoiceComparator
|
|
attr_reader :order
|
|
|
|
def initialize(order)
|
|
@order = order
|
|
end
|
|
|
|
def can_generate_new_invoice?
|
|
return true if invoices.empty?
|
|
|
|
# We'll use a recursive BFS algorithm to find if the invoice is outdated
|
|
# the root will be the order
|
|
# On each node, we'll a list of relevant attributes that will be used on the comparison
|
|
different?(current_state_invoice, latest_invoice, invoice_generation_selector)
|
|
end
|
|
|
|
def can_update_latest_invoice?
|
|
return false if invoices.empty?
|
|
|
|
different?(current_state_invoice, latest_invoice, invoice_update_selector)
|
|
end
|
|
|
|
private
|
|
|
|
def different?(node1, node2, attributes_selector)
|
|
simple_values1, presenters1 = attributes_selector.call(node1)
|
|
simple_values2, presenters2 = attributes_selector.call(node2)
|
|
return true if simple_values1 != simple_values2
|
|
|
|
return true if presenters1.size != presenters2.size
|
|
|
|
presenters1.zip(presenters2).any? do |presenter1, presenter2|
|
|
different?(presenter1, presenter2, attributes_selector)
|
|
end
|
|
end
|
|
|
|
def invoice_generation_selector
|
|
values_selector(:invoice_generation_values)
|
|
end
|
|
|
|
def invoice_update_selector
|
|
values_selector(:invoice_update_values)
|
|
end
|
|
|
|
def values_selector(attribute)
|
|
proc do |node|
|
|
return [[], []] unless node.respond_to?(attribute)
|
|
|
|
grouped = node.public_send(attribute).group_by(&grouper)
|
|
[grouped[:simple] || [], grouped[:presenters]&.flatten || []]
|
|
end
|
|
end
|
|
|
|
def grouper
|
|
proc do |value|
|
|
if value.is_a?(Array) || value.class.to_s.starts_with?("Invoice::DataPresenter")
|
|
:presenters
|
|
else
|
|
:simple
|
|
end
|
|
end
|
|
end
|
|
|
|
def current_state_invoice
|
|
@current_state_invoice ||= Invoice.new(
|
|
order: order,
|
|
data: serialize_for_invoice,
|
|
date: Time.zone.today,
|
|
number: invoices.count + 1
|
|
).presenter
|
|
end
|
|
|
|
def invoices
|
|
order.invoices
|
|
end
|
|
|
|
def latest_invoice
|
|
@latest_invoice ||= invoices.last.presenter
|
|
end
|
|
|
|
def serialize_for_invoice
|
|
InvoiceDataGenerator.new(order).serialize_for_invoice
|
|
end
|
|
end
|