Browse Source

fix: handle partial creation date bounds

master
Codex 2 months ago
parent
commit
4701719274
  1. 3
      ingestion/parsers.py
  2. 17
      tests/test_guided_import_workflow.py
  3. 14
      tests/test_import_parsers.py

3
ingestion/parsers.py

@ -155,8 +155,11 @@ def partial_context_from_creation_line(data: bytes) -> dict[str, str]:
creation = _creation_date(lines[20])
start_year = creation.year if creation.month == 12 else creation.year - 1
start_month = creation.month % 12 + 1
try:
start = date(start_year, start_month, 1)
end = date(creation.year, creation.month, monthrange(creation.year, creation.month)[1])
except ValueError:
raise ParseError('INVALID_CREATION_DATE') from None
if (end - start).days > 366:
raise ParseError('INVALID_CREATION_DATE')
return {'start_date': start.isoformat(), 'end_date': end.isoformat()}

17
tests/test_guided_import_workflow.py

@ -254,6 +254,23 @@ def test_partial_missing_context_has_safe_code_and_no_preview(source):
assert not ImportBatch.objects.exists()
def test_partial_context_year_underflow_does_not_interrupt_another_ready_file(source, bank):
card = create_account(name="Synthetic boundary card", kind="CREDIT_CARD", actor=ACTOR)
data = ("\n" * 20 + "Data de emissão: 20/01/0001\n"
+ f"05/01{'Synthetic boundary row':43}BR 12,50 0,00\n").encode()
exceptional = source(data, "partial.txt")
ready = source()
results = [prepare(discovered, account) for discovered, account in ((exceptional, card), (ready, bank))]
assert results[0].state == "NEEDS_ATTENTION"
assert results[0].code == "INVALID_CREATION_DATE"
assert results[0].batch_id is None
assert results[1].state == "READY"
assert commit(results[1]).counts["created"] == 2
assert Transaction.objects.count() == SourceRecord.objects.count() == 2
assert not ImportBatch.objects.filter(profile="OUROCARD_PARTIAL_V1").exists()
assert_no_open_preview()
def test_partial_valid_context_resolves_new_year_and_commits(source):
card = create_account(name="Synthetic partial card", kind="CREDIT_CARD", actor=ACTOR)
data = ("\n" * 20 + "Data de emissão: 20/01/2026\n"

14
tests/test_import_parsers.py

@ -154,6 +154,20 @@ def test_partial_context_resolves_december_rows_to_the_previous_year_after_janua
assert rows[0].posting_date == '2025-12-31'
@pytest.mark.parametrize('creation', ['20/01/0001', '15/11/0001'])
def test_partial_context_rejects_derived_interval_year_underflow(creation):
data = ('\n' * 20 + f'Data de emissão: {creation}\n').encode()
with pytest.raises(ParseError, match='^INVALID_CREATION_DATE$'):
partial_context_from_creation_line(data)
def test_partial_context_accepts_year_one_when_derived_bounds_are_representable():
data = ('\n' * 20 + 'Data de emissão: 15/12/0001\n').encode()
assert partial_context_from_creation_line(data) == {
'start_date': '0001-01-01', 'end_date': '0001-12-31',
}
@pytest.mark.parametrize('filename,profile,amounts', [
('bank.csv', 'BANK_CSV_V1', ['-12.34','100.00']),
('full.txt', 'OUROCARD_FULL_V1', ['-12.34','8.11','33.00']),

Loading…
Cancel
Save