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).
49 lines
2.8 KiB
SQL
49 lines
2.8 KiB
SQL
-- 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;
|