Automated system that pulls voter data from state election systems every 4 hours, detects changes, updates database, and logs everything in admin dashboard. Designed to support multiple states with pluggable state-specific adapters.
┌─────────────────────────────────────────┐
│ Auto Update Orchestrator │
│ (deploy/auto_update_orchestrator.py) │
└──────────────┬──────────────────────────┘
│
├─► State Adapter: Texas
│ └─► EVR Scraper
│ └─► Election Day Scraper
│
├─► State Adapter: [Future State]
│ └─► State-specific scrapers
│
└─► State Adapter: [Future State]
└─► State-specific scrapers
{
"states": {
"TX": {
"enabled": true,
"name": "Texas",
"adapter": "texas_adapter",
"update_interval_hours": 4,
"data_sources": ["EVR", "ELECTION_DAY"],
"api_config": {
"base_url": "https://goelect.txelections.civixapps.com",
"endpoints": {
"evr": "/api-ivis-system/api/v1/getFile?type=EVR_STATEWIDE",
"election_day": "/api-ivis-system/api/v1/getFile?type=EVR_STATEWIDE_ELECTIONDAY"
}
}
}
}
}- Loads state configurations
- Manages update schedule per state
- Coordinates state adapters
- Handles errors and retries
- Logs all operations
class StateAdapter:
def fetch_data(self, data_source, election_id, election_date)
def parse_data(self, raw_data)
def detect_changes(self, new_data, existing_data)
def update_database(self, changes)
def verify_data_quality(self)- Implements StateAdapter interface
- Texas-specific API calls
- Texas data format parsing
- Texas-specific validation
CREATE TABLE data_update_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
run_timestamp TEXT NOT NULL,
state_code TEXT NOT NULL, -- 'TX', 'CA', etc.
data_source TEXT NOT NULL, -- 'EVR', 'ELECTION_DAY', etc.
election_id TEXT,
election_date TEXT,
records_before INTEGER,
records_after INTEGER,
records_added INTEGER,
records_updated INTEGER,
records_verified INTEGER, -- County-verified count
changes_detected INTEGER, -- 0 or 1
summary TEXT,
details TEXT, -- JSON with detailed changes
error_message TEXT,
duration_seconds REAL,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX idx_update_log_state ON data_update_log(state_code, created_at);
CREATE INDEX idx_update_log_election ON data_update_log(election_id, election_date);Runs every 4 hours: 0 */4 * * *
- New "Data Updates" section showing:
- Last update time
- Changes detected
- Records added/updated
- Full change log with details
deploy/auto_update_scraper.py- Main scraper with change detectionbackend/data_updates.py- API endpoints for admin dashboardbackend/admin/data-updates.html- Admin UI for viewing logsbackend/admin/data-updates.js- Frontend logicdeploy/setup_cron.sh- Cron job setup script
- Cron triggers scraper every 4 hours
- Scraper fetches latest data from Texas SOS
- Compares with database (record counts, VUIDs, etc.)
- If changes detected:
- Updates database
- Marks county data as verified
- Regenerates district caches
- Logs detailed changes
- Admin can view all changes in dashboard
- Create data_update_log table
- Build auto_update_scraper.py
- Add API endpoints
- Create admin UI
- Setup cron job
- Test end-to-end
- New "Data Updates" section showing:
- Per-state update status
- Last update time per state
- Changes detected
- Records added/updated/verified
- Full change log with filtering by state/date
- Error tracking and alerts
- Centralized state configuration
- Easy to add new states
- Per-state settings and API endpoints
deploy/
├── auto_update_orchestrator.py # Main coordinator
├── adapters/
│ ├── base_adapter.py # Abstract base class
│ ├── texas_adapter.py # Texas implementation
│ └── [future_state]_adapter.py # Future state adapters
├── config/
│ └── states.json # State configurations
└── utils/
├── change_detector.py # Generic change detection
├── data_validator.py # Data quality checks
└── cache_regenerator.py # Cache rebuild logic
backend/
├── data_updates.py # API endpoints
└── admin/
├── data-updates.html # Admin UI
└── data-updates.js # Frontend logic
- Cron triggers orchestrator every 4 hours (configurable per state)
- Orchestrator loads enabled states from config
- For each state:
- Load state adapter
- Fetch latest data from state API
- Detect changes (new records, updates)
- If changes detected:
- Update database
- Mark county data as verified
- Regenerate district caches
- Log detailed changes
- Admin dashboard shows real-time status
- Create new adapter:
deploy/adapters/newstate_adapter.py - Implement StateAdapter interface
- Add state config to
config/states.json - Test adapter independently
- Enable in production
- ✓ Design multi-state architecture
- Create base adapter interface
- Implement Texas adapter (refactor existing code)
- Build orchestrator
- Create data_update_log table
- Add API endpoints
- Build admin UI
- Setup cron job
- Test end-to-end
- Document for future states
- California: Different API, different data format
- Florida: County-level APIs, aggregation needed
- Georgia: PDF parsing required
- etc.
Each state adapter handles its unique requirements while the orchestrator provides consistent logging, scheduling, and admin interface.