Date-Parser Consolidation
Shipped: 2026-08-05 (entirely-api 875e5a5, deployed). Second deliverable of
the ML/workflow-intelligence plan — the mixed date formats were a blocking
prerequisite for process mining on the new status-event-log.
The canonical family (config.py)
extract_date_str(raw)— YYYY-MM-DD from any of the 3 raw_data formats (dict blob / plain ISO / stringified JSON). Pre-existing; already widespread.extract_datetime(raw)— tz-aware UTC for timed values, naive midnight for date-only. The blob’sinclude_timeflag decides; unflagged exact-midnight-Z counts as date-only (that’s the storage convention for plain dates — treating it as timed would shift every plain date a day back in ET).extract_date_et(raw)— correct Eastern calendar day for timed values.ss_date_field(value, include_time=False)— write-side builder; routes no longer hand-assemble{"date": ..., "include_time": ...}.
Rule going forward: never hand-parse or hand-build raw_data dates.
The sweep
Three parallel agents, ~50 sites across 23 files, behavior-preserving.
Deliberately left: smartsuite_helpers.extract_date (returns full timestamps
its consumers rely on), payment-recon’s _clean_date* (handles slash formats
the helper doesn’t), full-timestamp API-payload echoes, sites with stricter
malformed-JSON handling than the helper. Notable enabled-by-fix behavior:
same-day approval alert can now fire for dict-format dates (was dead);
field arrival/completion matching now handles ‘on’-key and stringified blobs;
calendar revenue no longer shifts date-only values to the prior ET day.
Data normalization (prod, same day)
projects.date_invoice_sent held 3 formats; one transactional SQL update
(pre-checked: 0 malformed) → 2,459 plain dates, 4,694 honest NULLs, zero blobs.
raw_data originals untouched. Field map now applies extract_date_str on write.
triage_assigned_date/hold_since NOT truncated — real timestamps, and the
column is their only storage.
Follow-up
~16 flagged ET day-boundary sites (UTC day vs ET “today”, off-by-one after
8 PM ET) — enumerated in memory project_et_day_boundary_fixes, fix pass with
extract_date_et pending. Highest operational impact: field arrival/completion
matching, visit-completion prompt, SLA deadline start, intake next-visit
annotation.