Biometric Attendance System
ODOO · Python · Raspberry Pi · ZKTeco · Docker · Commercial SaaS

Attendance data lived on hardware. Payroll was calculated on paper. The gap between them was filled by hand.
ZKTeco biometric devices hold accurate, timestamped attendance records. Odoo HR holds the payroll logic. Between them: nothing. Every payroll cycle required manual data export, cross-referencing, and entry — error-prone and completely unauditable.
THE STANDARD APPROACH FAILS BECAUSE:
Devices speak ADMS push and direct polling. Neither is reliable alone. Production architecture handles both, with fallback behavior and no data loss when connectivity drops.
"Offline-first SQLite WAL queue at branch level — events survive connectivity failures before they reach Odoo."
— KEY ARCHITECTURAL DECISION
TECHNICAL DECISIONS // 5 MADE
Multi-channel ingestion (ADMS + Polling) with fallback
SQLite queue in WAL mode for local persistence
Event fingerprinting for robust deduplication
Token-based authentication and IP allowlisting
Full SaaS commercialization strategy

Port-forwarding failure — the naive approach
Odoo Module
6 FEATURE GROUPS- Biometric User Registry — device-to-employee mapping with sync state
- Daily Activity Engine — worked minutes, overtime, shift compliance
- CTO Bank — compensatory time-off accumulation and usage tracking
- Event Deduplication — fingerprint-based rejection of duplicate punches
- HR Review & Adjustments — manager workflow with immutable audit trail
- Payroll Export — structured payroll-ready CSV, zero manual steps
Edge Sync Service
DOCKER + RASPBERRY PI- ADMS push endpoint — ZKTeco device pushes events to edge service
- Direct polling — edge service queries device on schedule
- SQLite WAL queue — events persisted locally before Odoo transmission
- Exponential backoff with jitter on sync failures
- Health endpoint for remote monitoring
- Structured logging and sync metrics
Security
PRODUCTION-GRADE- Token-based authentication on all ingestion endpoints
- IP allowlist enforcement for ADMS push
- Full audit fields on every manual override
- RBAC via Odoo model security and record rules