Back to ProjectsWeb App + IoT (Biometric)
Attendance Management System
Track employee hours, manage leaves and overtime, and sync attendance from ZKTeco biometric devices — all from a single Laravel-powered dashboard.
Overview
The Attendance Management System was built to digitize employee time tracking for small-to-medium organizations. It replaces paper logs and standalone biometric machines with a unified web dashboard that combines manual entry, hardware sync, and automated lateness/overtime tracking.
Problem
- ▸Organizations using ZKTeco fingerprint scanners had no centralized view of attendance data — each device operated in isolation
- ▸Managers struggled to track who was late or worked overtime across departments
- ▸Monthly payroll preparation required manually cross-referencing device logs with paper records
- ▸No simple way for employees to check their own attendance history or for admins to generate monthly reports
Solution
- ▸A Laravel 8 MVC application with a MySQL backend, served via Blade templates with Bootstrap 4
- ▸ZKTeco integration via the rats/zkteco PHP library communicating over TCP (port 4370) to pull attendance records and push employee registrations to devices
- ▸Automatic lateness/overtime calculation based on scheduled shifts — the system compares check-in time against schedule.time_in and logs duration to latetimes / overtimes tables
- ▸A monthly calendar-sheet interface where admins can view/edit attendance day-by-day, with a color-coded read-only report view
- ▸Sanctum-based API for mobile or terminal-based check-in/out using email + PIN authentication
Architecture Flow
┌───────────────────────────────────────────────────────────┐
│ Web Browser (Admin) │
│ ┌──────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ Dashboard │ │ Monthly │ │ Employee/Schedule │ │
│ │ (Stats) │ │ Sheet/Report │ │ CRUD │ │
│ └──────────┘ └──────┬───────┘ └────────────────────┘ │
└────────────────────────┼───────────────────────────────────┘
│ HTTP
▼
┌───────────────────────────────────────────────────────────┐
│ Laravel 8 (Web) │
│ ┌──────────┐ ┌──────────────┐ ┌────────────────────┐ │
│ │ Routes │─▶│ Controllers │─▶│ Models/Eloquent │ │
│ │ web.php │ │ (Auth'd) │ │ Employee,Attendance│ │
│ │ api.php │ │ │ │ Leave, Schedule │ │
│ └──────────┘ └──────┬───────┘ └──────────┬─────────┘ │
│ │ │ │
│ ┌────────────────────▼─────────────────────▼──────────┐ │
│ │ BiometricDeviceController │ │
│ │ ┌────────────────┐ ┌──────────────────────────┐ │ │
│ │ │ addEmployee() │ │ getAttendance() │ │ │
│ │ │ Push to ZKTeco │ │ Pull → auto-calc │ │ │
│ │ └───────┬────────┘ │ lateness / overtime │ │ │
│ │ │ └────────────┬─────────────┘ │ │
│ └──────────┼────────────────────────┼─────────────────┘ │
└─────────────┼────────────────────────┼───────────────────┘
│ │
▼ ▼
┌───────────────┐ ┌──────────────────────────┐
│ ZKTeco Device │ │ MySQL Database │
│ (TCP :4370) │ │ attendances │
│ Fingerprint │ │ latetimes / overtimes │
│ Scanner │ │ leaves / schedules │
└───────────────┘ │ employees / checks │
└──────────────────────────┘
┌───────────────────────────────────────────────────────────┐
│ Mobile / Terminal (API Client) │
│ POST /api/check {email, pin_code} │
│ POST /api/attendance {email, pin_code} │
│ POST /api/leave {email, pin_code} │
│ ↕ Sanctum Token Auth │
└───────────────────────────────────────────────────────────┘Key Features
- ▸Employee & Schedule CRUD — manage employee profiles (name, position, email, PIN) and shift schedules (time_in, time_out)
- ▸Biometric Device Management — add ZKTeco devices by IP, check connection status, push employee records to devices, and pull attendance logs on demand
- ▸Monthly Attendance Sheet — full calendar grid per month with checkboxes for manual check-in/leave entry; read-only report with color-coded status icons
- ▸Automated Lateness & Overtime — when attendance is pulled from devices or entered manually, duration of lateness/overtime is calculated and stored separately for reporting
- ▸Dashboard Analytics — real-time stats (total employees, on-time %, today's counts), Chartist.js line chart for monthly trends, and Peity donut charts
- ▸Role-Based Access — admin-only middleware gate; no public registration
Technology Stack
Backend
PHP 8.0Laravel 8.65
Database
MySQL
Authentication
Laravel Sanctum (API)Laravel UI (web session)
Biometric SDK
rats/zkteco (ZKTeco TCP/IP, port 4370)
Frontend
BladeBootstrap 4jQuerySass
Charts
Chartist.jsPeity
Build Tooling
Laravel Mix (Webpack)npm
Notifications
SweetAlert2Flash session messaging
Notable Design Decisions
- ▸Custom roles over Spatie — a lightweight roles table + pivot (role_users) with hasAnyRole() / hasRole() methods on the User model, avoiding the dependency weight of spatie/laravel-permission while keeping admin gates simple
- ▸Controller helpers as domain logic — lateness and overtime calculation live in static methods on AttendanceController and LeaveController, called from BiometricDeviceController — a pragmatic way to share logic without a service layer
- ▸Duplicate-safe attendance import — both the biometric pull and the manual sheet check for existing records (whereAttendance_date()->whereEmp_id()->whereType()->first()) before inserting, preventing duplicate entries from repeated device syncs
- ▸Timezone-locked to Asia/Kabul — all timestamps are scoped to Afghanistan timezone, reflecting the original deployment context
- ▸Employee IDs start at 111 — a small UX detail that visually distinguishes employee records from user accounts