fix: only mark overlapping statement periods as duplicate (#2569)

* fix: only mark overlapping statement periods as duplicate

* fix: treat non-overlapping statement periods as covered
This commit is contained in:
Maxence C.
2026-07-04 03:27:59 +02:00
committed by GitHub
parent e38d552c15
commit 9d8b953c8e
2 changed files with 64 additions and 2 deletions

View File

@@ -130,11 +130,11 @@ class AccountStatement::Coverage
linked_statements = statements_covering(linked_statement_scope, month)
ambiguous_statements = statements_covering(ambiguous_statement_scope, month)
status = if linked_statements.size > 1
status = if linked_statements.many? && overlapping_statements?(linked_statements)
"duplicate"
elsif linked_statements.any? { |statement| statement.reconciliation_mismatched?(balance_lookup: balance_lookup) }
"mismatched"
elsif linked_statements.one?
elsif linked_statements.any?
"covered"
elsif ambiguous_statements.any?
"ambiguous"
@@ -177,6 +177,13 @@ class AccountStatement::Coverage
end
end
def overlapping_statements?(statements)
statements.combination(2).any? do |a, b|
a.period_start_on <= b.period_end_on &&
b.period_start_on <= a.period_end_on
end
end
def balance_lookup
@balance_lookup ||= begin
currencies = linked_statement_scope.map(&:statement_currency).compact.uniq

View File

@@ -756,6 +756,41 @@ class AccountStatementTest < ActiveSupport::TestCase
assert_equal "mismatched", statuses[mismatched_month]
end
test "coverage does not mark adjacent statements as duplicate when they only share a calendar month" do
account = Account.create!(
family: @family,
owner: users(:family_admin),
name: "Adjacent Statement Checking",
balance: 0,
currency: "USD",
accountable: Depository.new
)
march = Date.new(2026, 3, 1)
create_statement_with_period(
account: account,
period_start_on: Date.new(2026, 1, 8),
period_end_on: Date.new(2026, 3, 6),
content: "adjacent-a"
)
create_statement_with_period(
account: account,
period_start_on: Date.new(2026, 3, 7),
period_end_on: Date.new(2026, 4, 7),
content: "adjacent-b"
)
coverage = AccountStatement::Coverage.new(
account,
start_month: march,
end_month: march
)
assert_equal "covered", coverage.months.first.status
end
private
def create_statement(account:, month:, content:, suggested_account: nil, closing_balance: nil)
@@ -776,4 +811,24 @@ class AccountStatementTest < ActiveSupport::TestCase
)
statement
end
def create_statement_with_period(account:, period_start_on:, period_end_on:, content:, suggested_account: nil)
statement = AccountStatement.create_from_upload!(
family: @family,
account: account,
file: uploaded_file(
filename: "statement_#{content}_#{period_start_on}_#{period_end_on}.csv",
content_type: "text/csv",
content: "date,amount\n#{period_start_on},1\n#{period_end_on},2\n#{content}\n"
)
)
statement.update!(
suggested_account: suggested_account,
period_start_on: period_start_on,
period_end_on: period_end_on
)
statement
end
end