feat(sp33): fix resubmit CLI session reuse + mismatch skip
- payer-mismatch files are now skipped instead of uploaded - SFTP session persists across files (was reopened and leaked per file) - --reconnect-every now counts successful uploads, after increment - drop unused SftpClient instantiation; read each file once - apply_999_rejections docstring: R/E/X, not R/E Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+23
-22
@@ -577,7 +577,6 @@ def resubmit_rejected_claims(
|
||||
|
||||
from cyclone import db as db_mod
|
||||
from cyclone.audit_log import AuditEvent, append_event
|
||||
from cyclone.clearhouse import SftpClient
|
||||
from cyclone.parsers.parse_837 import parse as parse_837_text
|
||||
from cyclone.parsers.payer import PayerConfig
|
||||
from cyclone.store import store as cycl_store
|
||||
@@ -614,7 +613,6 @@ def resubmit_rejected_claims(
|
||||
failed = 0
|
||||
validated = 0
|
||||
payer_cfg = PayerConfig.co_medicaid()
|
||||
sftp_client = SftpClient(sftp_block)
|
||||
start = time.monotonic()
|
||||
last_progress = start
|
||||
|
||||
@@ -641,36 +639,39 @@ def resubmit_rejected_claims(
|
||||
try: ssh.close()
|
||||
except Exception: pass
|
||||
|
||||
ssh: paramiko.SSHClient | None = None
|
||||
sftp: paramiko.SFTPClient | None = None
|
||||
|
||||
for i, src in enumerate(files, 1):
|
||||
if limit is not None and i > limit:
|
||||
break
|
||||
|
||||
content = src.read_bytes()
|
||||
|
||||
# Validate: parse must succeed AND payer_id must match the
|
||||
# companion-guide CO_TXIX (catches a bad byte-fix early).
|
||||
if validate:
|
||||
try:
|
||||
parsed = parse_837_text(src.read_text(), payer_cfg)
|
||||
parsed = parse_837_text(content.decode(), payer_cfg)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
failed += 1
|
||||
click.echo(f"PARSE FAIL {src.name}: {exc.__class__.__name__}: {exc}", err=True)
|
||||
continue
|
||||
for c in parsed.claims:
|
||||
if c.payer.id != "CO_TXIX":
|
||||
failed += 1
|
||||
click.echo(
|
||||
f"PAYER MISMATCH {src.name}: payer.id={c.payer.id!r} "
|
||||
f"(expected 'CO_TXIX')", err=True,
|
||||
)
|
||||
break
|
||||
else:
|
||||
validated += 1
|
||||
mismatch = next(
|
||||
(c for c in parsed.claims if c.payer.id != "CO_TXIX"), None
|
||||
)
|
||||
if mismatch is not None:
|
||||
failed += 1
|
||||
click.echo(
|
||||
f"PAYER MISMATCH {src.name}: payer.id={mismatch.payer.id!r} "
|
||||
f"(expected 'CO_TXIX')", err=True,
|
||||
)
|
||||
continue
|
||||
validated += 1
|
||||
|
||||
content = src.read_bytes()
|
||||
local_size = len(content)
|
||||
remote_path = f"{remote_root}/{src.name}"
|
||||
|
||||
ssh: paramiko.SSHClient | None = None
|
||||
sftp: paramiko.SFTPClient | None = None
|
||||
attempts = 0
|
||||
ok = False
|
||||
while attempts < 3:
|
||||
@@ -713,12 +714,6 @@ def resubmit_rejected_claims(
|
||||
failed += 1
|
||||
continue
|
||||
|
||||
# Reconnect periodically to dodge MOVEit's per-session cap.
|
||||
if uploaded > 0 and uploaded % reconnect_every == 0:
|
||||
click.echo(f"reconnecting (after {uploaded} uploads)", err=True)
|
||||
_close_session(ssh)
|
||||
ssh, sftp = None, None
|
||||
|
||||
# Audit (best-effort; if the DB is unavailable we still keep
|
||||
# the file on the wire).
|
||||
try:
|
||||
@@ -741,6 +736,12 @@ def resubmit_rejected_claims(
|
||||
|
||||
uploaded += 1
|
||||
|
||||
# Reconnect periodically to dodge MOVEit's per-session cap.
|
||||
if uploaded % reconnect_every == 0:
|
||||
click.echo(f"reconnecting (after {uploaded} uploads)", err=True)
|
||||
_close_session(ssh)
|
||||
ssh, sftp = None, None
|
||||
|
||||
# Progress every 10s of wall-clock (or at end).
|
||||
now = time.monotonic()
|
||||
if now - last_progress >= 10 or i == len(files):
|
||||
|
||||
@@ -35,7 +35,7 @@ def apply_999_rejections(
|
||||
claim_lookup: Callable[[str], Claim | None],
|
||||
batch_envelope_index: dict[str, list[str]] | None = None,
|
||||
) -> Apply999Result:
|
||||
"""For each set response with code R or E, look up the matching claim and
|
||||
"""For each set response with code R, E, or X, look up the matching claim and
|
||||
move it to REJECTED. Idempotent on already-rejected claims.
|
||||
|
||||
Args:
|
||||
|
||||
Reference in New Issue
Block a user