Backend Aug 22-25: AI analysis, welcome-packet templating, LetterStream, DocuSeal, staff RBAC + tier gate
- analysis.py: deterministic claim scorer + /analyze /approve /letter /advance-tier endpoints (auto-runs on intake) - packet.py + packet_fields.json: welcome-packet templating engine (6 onboarding docs, field catalog) - letterstream.py + letters.py: certified-mail send pipeline + letter lifecycle (webhook verified) - docuseal.py: DocuSeal signing integration - staff.py/models.py/schema.sql/auth.py: approval actor from staff key, tier gate (APPROVED+ACTIVE+onboarding docs), onboarding_docs table - frontend/: dependency-free static portal (intake, magic-link login/verify, dashboard) - landing-mockups/: 4 design-stance mockups + favicons - legal/: aup/privacy/sms-terms/terms HTML - docs/: letter-queue scope, letterstream API contract, 6 welcome-packet templates - review-dre-landing-2026-08-21.md: 3-variant landing feedback sprint - compliance/DRE_Compliance_Manual.md: updated Source synced from deployed /opt/dre-portal/app/ (was 4 days ahead of git).
This commit is contained in:
+15
-3
@@ -11,6 +11,7 @@ from pydantic import ValidationError
|
||||
from . import auth as authmod
|
||||
from . import db
|
||||
from . import dreemail
|
||||
from . import analysis
|
||||
from .db import get_conn, new_uuid, next_sequence_number, utcnow_iso
|
||||
from .models import IntakeRequest
|
||||
|
||||
@@ -93,10 +94,12 @@ async def intake(request: Request):
|
||||
claim_id = new_uuid()
|
||||
claim_number = next_sequence_number(conn, "DRE")
|
||||
conn.execute(
|
||||
"INSERT INTO claims (id, claim_number, client_id, debtor_id, amount_cents, currency, status, tier, description, client_reference, invoice_date, date_assigned, date_resolved, twentycrm_id, created_at, updated_at) "
|
||||
"VALUES (?, ?, ?, ?, ?, 'USD', 'NEW', 'TIER_1', ?, ?, ?, NULL, NULL, NULL, ?, ?)",
|
||||
"INSERT INTO claims (id, claim_number, client_id, debtor_id, amount_cents, currency, status, tier, description, client_reference, invoice_date, date_assigned, date_resolved, no_other_agency_at, no_prior_action_at, twentycrm_id, created_at, updated_at) "
|
||||
"VALUES (?, ?, ?, ?, ?, 'USD', 'NEW', 'TIER_1', ?, ?, ?, NULL, NULL, ?, ?, NULL, ?, ?)",
|
||||
(claim_id, claim_number, client_id, debtor_id, claim_in.amount_cents,
|
||||
claim_in.description, claim_in.client_reference, claim_in.invoice_date, now, now),
|
||||
claim_in.description, claim_in.client_reference, claim_in.invoice_date,
|
||||
now if req.no_other_agency_accepted else None,
|
||||
now if req.no_prior_action_accepted else None, now, now),
|
||||
)
|
||||
conn.execute(
|
||||
"INSERT INTO audit_log (id, entity_type, entity_id, action, old_value, new_value, actor, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
@@ -114,6 +117,15 @@ async def intake(request: Request):
|
||||
"INSERT INTO audit_log (id, entity_type, entity_id, action, actor, created_at) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
(new_uuid(), "note", note_id, "note_add", "system", now),
|
||||
)
|
||||
|
||||
# Auto-run AI analysis on submission (score + recommended tier + approval=PENDING).
|
||||
# Deterministic rules engine; no external call. Best-effort: a failure must not
|
||||
# block intake, so we guard and let the claim persist without a score if it errors.
|
||||
try:
|
||||
analysis.analyze_and_store(conn, claim_id, actor="system")
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.error("auto-analysis failed for claim %s: %s", claim_number, exc)
|
||||
|
||||
conn.commit()
|
||||
|
||||
# Best-effort team notification
|
||||
|
||||
Reference in New Issue
Block a user