fix(sec): name aged filings in deferred warnings
This commit is contained in:
@@ -71,11 +71,13 @@ class FakeImporter:
|
||||
def __init__(
|
||||
self, revision, *, ok=True, retryable=False, alert_days=None,
|
||||
n_rows=3, raise_in="none",
|
||||
alert_messages=None,
|
||||
):
|
||||
self.revision = revision
|
||||
self.ok = ok
|
||||
self.retryable = retryable
|
||||
self.alert_days = alert_days
|
||||
self.alert_messages = alert_messages or []
|
||||
self.n_rows = n_rows
|
||||
self.raise_in = raise_in
|
||||
self.staged_called = False
|
||||
@@ -102,6 +104,7 @@ class FakeImporter:
|
||||
messages=[] if self.ok else ["coverage below threshold"],
|
||||
retryable=self.retryable,
|
||||
deferred_alert_after_days=self.alert_days,
|
||||
deferred_alert_messages=self.alert_messages,
|
||||
)
|
||||
|
||||
async def promote(self, db, staged, run_id):
|
||||
@@ -231,7 +234,9 @@ async def test_stale_deferred_validation_emits_deduplicated_warning(engine):
|
||||
await s.commit()
|
||||
|
||||
importer = FakeImporter(
|
||||
"rev2", ok=False, retryable=True, alert_days=3, n_rows=5
|
||||
"rev2", ok=False, retryable=True, alert_days=3,
|
||||
alert_messages=["source detail names OLD-ACCESSION"],
|
||||
n_rows=5,
|
||||
)
|
||||
first = await run_import(importer, engine=engine)
|
||||
second = await run_import(importer, engine=engine)
|
||||
@@ -244,6 +249,21 @@ async def test_stale_deferred_validation_emits_deduplicated_warning(engine):
|
||||
assert events[0].severity == "warning"
|
||||
assert events[0].code == "sec_facts_deferred_stale"
|
||||
|
||||
assert "OLD-ACCESSION" in events[0].message
|
||||
assert "aged-out" not in events[0].message
|
||||
|
||||
|
||||
async def test_never_promoted_deferred_warning_says_never(engine):
|
||||
factory = _factory(engine)
|
||||
run = await run_import(
|
||||
FakeImporter("rev1", ok=False, retryable=True, alert_days=3),
|
||||
engine=engine,
|
||||
)
|
||||
|
||||
assert run is not None and run.status == STATUS_DEFERRED
|
||||
async with factory() as s:
|
||||
event = (await s.execute(select(SystemEvent))).scalar_one()
|
||||
assert "has never promoted successfully" in event.message
|
||||
|
||||
async def test_exception_in_promote_rolls_back(engine):
|
||||
factory = _factory(engine)
|
||||
|
||||
@@ -262,6 +262,39 @@ async def test_companyfacts_lag_does_not_mask_second_validation_failure():
|
||||
assert len(result.messages) == 2
|
||||
|
||||
|
||||
async def test_deferred_alert_names_aged_out_accessions_separately():
|
||||
importer = SecFundamentalsImporter(today=date(2026, 5, 6))
|
||||
importer._latest_index_date = date(2026, 5, 5)
|
||||
staged = StagedFundamentals(
|
||||
resolved=ResolvedUniverse(),
|
||||
missing_xbrl=[
|
||||
{
|
||||
"cik": "0000320193",
|
||||
"accession": "YOUNG",
|
||||
"form": "10-Q",
|
||||
"index_date": date(2026, 5, 5),
|
||||
"age_days": 1,
|
||||
"reason": "not_in_companyfacts",
|
||||
},
|
||||
{
|
||||
"cik": "0000789019",
|
||||
"accession": "AGED-OUT",
|
||||
"form": "10-Q",
|
||||
"index_date": date(2026, 5, 1),
|
||||
"age_days": 5,
|
||||
"reason": "not_in_companyfacts",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
result = await importer.validate(None, staged)
|
||||
|
||||
assert result.retryable
|
||||
assert len(result.messages) == 1 and "YOUNG" in result.messages[0]
|
||||
assert len(result.deferred_alert_messages) == 1
|
||||
assert "AGED-OUT" in result.deferred_alert_messages[0]
|
||||
|
||||
|
||||
async def test_gate_separates_missing_submissions_from_missing_facts(engine):
|
||||
"""An index row the issuer's own filing list does not carry is a different
|
||||
failure from a Company-Facts lag, and must not be reported as one."""
|
||||
|
||||
Reference in New Issue
Block a user