Skip to content
Irvs EbajanIrvs
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