healthcare: daily batched paper-filing fulfillment
Standard (no-login) CMS filings are mailed in one Priority Mail envelope per destination agency, batched each postal working-day morning to save postage. - migration 089: paper_filing_batches table + esign_records.paper_batch_id / filing_destination_key (idempotent: a filing is batched at most once). - batch_cover_sheet.py: per-agency cover sheet (sender/dest/date/manifest) + merged print-job PDF (cover + all enclosed signed filings). - daily_paper_batch.py worker: gather signed+unbatched cms855/cms10114 filings, group by destination (MAC by state via mac_routing; Fargo for CMS-10114), build cover+merged PDF per agency, persist batch, mark filings batched. Self-gates on postal working days (skips weekends + federal/USPS holidays). Phase 1 = human prints+mails; phase 2 = wire print-mail API. - worker-crons: pw-paper-batch systemd timer (Mon-Fri 13:30 UTC, self-gated). - test_paper_batch.py: 15/15 pass (working-day gating, routing, cover+merge).
This commit is contained in:
parent
258d23bdc6
commit
138fec17e9
5 changed files with 542 additions and 0 deletions
49
api/migrations/089_paper_filing_batches.sql
Normal file
49
api/migrations/089_paper_filing_batches.sql
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
-- 089: Daily paper-filing batch tracking for the Standard (no-login) CMS filing path.
|
||||
--
|
||||
-- When a provider e-signs a CMS-855 (or CMS-10114), the signed PDF is mailed to
|
||||
-- the destination agency (the provider's MAC for 855s; the NPI Enumerator in
|
||||
-- Fargo for NPPES updates). To save postage and handling we batch all signed,
|
||||
-- not-yet-mailed filings each postal working-day morning, group them by
|
||||
-- destination agency, and mail one Priority Mail envelope per agency.
|
||||
--
|
||||
-- This migration records, per signed filing, which daily batch it went out in,
|
||||
-- so the batch worker is idempotent (never re-mails) and we can audit/track.
|
||||
|
||||
-- A paper-filing batch = one Priority Mail envelope to one destination agency
|
||||
-- on one mailing day.
|
||||
CREATE TABLE IF NOT EXISTS paper_filing_batches (
|
||||
id SERIAL PRIMARY KEY,
|
||||
batch_date DATE NOT NULL, -- the postal working day mailed
|
||||
destination_key TEXT NOT NULL, -- mac_routing key, e.g. noridian_je / npi_enumerator
|
||||
destination_name TEXT NOT NULL DEFAULT '', -- human-readable MAC/agency name
|
||||
destination_address TEXT NOT NULL DEFAULT '', -- full mailing address block
|
||||
item_count INTEGER NOT NULL DEFAULT 0, -- number of filings enclosed
|
||||
cover_sheet_key TEXT, -- MinIO key for the batch cover sheet
|
||||
merged_pdf_key TEXT, -- MinIO key for the merged print job
|
||||
tracking_number TEXT, -- USPS tracking, filled when mailed
|
||||
status TEXT NOT NULL DEFAULT 'prepared'
|
||||
CHECK (status IN ('prepared', 'mailed', 'cancelled')),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
mailed_at TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_paper_batch_date ON paper_filing_batches(batch_date);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_paper_batch_day_dest
|
||||
ON paper_filing_batches(batch_date, destination_key);
|
||||
|
||||
-- Link each signed esign filing to the batch it shipped in. NULL = not yet
|
||||
-- batched (the worker picks these up). Set once -> idempotent (worker skips
|
||||
-- anything already assigned a batch).
|
||||
ALTER TABLE esign_records
|
||||
ADD COLUMN IF NOT EXISTS paper_batch_id INTEGER REFERENCES paper_filing_batches(id);
|
||||
|
||||
-- The destination MAC/agency for this filing, derived from the provider's
|
||||
-- practice state at sign time (snapshot so later routing-table changes don't
|
||||
-- retroactively move historical filings).
|
||||
ALTER TABLE esign_records
|
||||
ADD COLUMN IF NOT EXISTS filing_destination_key TEXT;
|
||||
|
||||
-- Index the work queue: signed, paper-path filings not yet batched.
|
||||
CREATE INDEX IF NOT EXISTS idx_esign_unbatched_signed
|
||||
ON esign_records(status)
|
||||
WHERE status = 'signed' AND paper_batch_id IS NULL;
|
||||
Loading…
Add table
Add a link
Reference in a new issue