Download the PHP package arifur9993/attendance-engine without Composer
On this page you can find all versions of the php package arifur9993/attendance-engine. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download arifur9993/attendance-engine
More information about arifur9993/attendance-engine
Files in arifur9993/attendance-engine
Package attendance-engine
Short Description The attendance brain for PHP apps. Pure-function resolver for shifts, breaks, overtime, overnight, rosters & compliance. Zero deps. PHP 8.2+. PHP twin of @attendance-engine/core.
License MIT
Homepage https://github.com/arifur9993/attendance-engine-php
Informations about the package attendance-engine
Why this exists
"Was this person late?" sounds easy. It isn't.
Overnight shifts that cross midnight. Missing clock-outs. Duplicate biometric reads landing 12 seconds apart. Grace windows that vary by team. Rotating rosters. Unpaid lunch breaks that may or may not be taken. Daylight-saving boundaries. Time-zone drift between the device, the server, and the database.
Every HR/payroll/attendance product in the world re-solves these same dozen edge cases — usually buried in a 4,000-line Laravel controller that nobody dares touch.
attendance-engine is that logic, lifted out, tested to death, and shipped as a pure-function library.
It's the PHP twin of @attendance-engine/core (TypeScript). Same contract, same fixtures, same to-the-minute answers — so your Node frontend and your PHP backend never disagree on whether Rahim was 3 minutes late on Tuesday.
✨ What you get
| ⚡ One function, one answer | Engine::resolveDay() takes raw punches, returns a typed DayResult. No globals, no state, no surprises. |
| 🌙 Overnight-safe | Shifts that cross midnight, punches that bucket onto the right duty-date. We've thought about this so you don't have to. |
| 🧮 Overtime, breaks, lateness | All the math: late-after-grace, unpaid-break deduction, early-out, OT (shift-based / fixed-hours / daily-cap), rounding units. |
| 📅 Ranges + summaries | Engine::resolveRange() for a whole month, Engine::summarize() for the payroll card. |
| 🗓️ Rosters built-in | Engine::generateRoster() expands a weekly pattern into a date-keyed shift map. |
| 🌐 Timezone-safe | The engine never touches date_default_timezone_set(). Every timestamp carries its own offset. No DST drift. |
| 🪶 Zero deps | Pure PHP. No Carbon, no Symfony, no Composer plugins. Drop into Laravel, Symfony, Slim, or vanilla. |
| 🧪 Tested | PHPStan level 8 + Pest. CI matrix on 8.2 / 8.3 / 8.4. |
📦 Install
That's it. The package is namespaced under Arifur9993\AttendanceEngine\ and ships with PSR-4 autoloading.
⚡ 60-second quick start
🧠 Real-world recipes
1. A whole month, one call
2. Rotating roster from a weekly pattern
3. Round noisy biometric punches before resolving
4. Catch a missing-break compliance issue
5. Drop into Laravel — no provider needed
The engine is 100% static & pure — no DI binding required. It plays the same with Symfony, Slim, Mezzio, or plain PHP.
📚 API at a glance
| Function | What it does |
|---|---|
Engine::resolveDay(ResolveDayInput) → DayResult |
One day, in/out punches → status + minutes. |
Engine::resolveRange(ResolveRangeInput) → RangeResult |
A whole [from, to] window resolved at once, with smart punch bucketing. |
Engine::summarize(RangeResult) → RangeSummary |
Aggregate totals: worked / OT / late / absent / status counts. |
Engine::applyRounding(array, unit, strategy) → Punch[] |
Round punches to nearest / up / down by N minutes. |
Engine::evaluateBreakCompliance(DayResult, rule) → string[] |
Returns a list of compliance violations (empty = clean). |
Engine::generateRoster(from, to, weeklyPattern) → array |
Expand a weekly 0..6 pattern into a date → shift map. |
All value objects implement JsonSerializable and ->toArray(), so they round-trip cleanly through HTTP responses, queues, and caches.
⏰ Timezone discipline (read this)
ISO-8601 timestamps must carry an explicit offset:
The engine never calls date_default_timezone_get(). Every calculation is anchored on the offset you provide. This is on purpose — it's the only way to stop "but it worked on staging" timezone bugs from sneaking into payroll.
🆚 Same answers as the TypeScript engine
This is the PHP twin of @attendance-engine/core. The two ports share fixtures and contracts. If your Next.js frontend and your Laravel backend both compute workedMinutes for the same punches, you get the same integer, to the minute.
| Feature | TypeScript (@attendance-engine/core) |
PHP (this package) |
|---|---|---|
resolveDay |
✅ | ✅ |
resolveRange |
✅ | ✅ |
summarize |
✅ | ✅ |
generateRoster |
✅ | ✅ |
applyRounding |
✅ | ✅ |
evaluateBreakCompliance |
✅ | ✅ (generic) |
| Jurisdiction packs (CA, EU) | 🔜 | 🔜 |
| Cross-port fixture parity | partial | partial |
💼 Who's using it
attendance-engine is the calculation core behind production HRMS / payroll setups handling:
- Mixed day/night/rotational rosters across Bangladesh, India, UAE, and SE Asia.
- Multi-tenant SaaS deployments where each tenant brings its own grace window + OT policy.
- Compliance-sensitive sectors (manufacturing, healthcare, retail) where "approximately worked" isn't good enough.
If you ship it in production, open an issue — I'll add your logo here.
🤝 Contributing
PRs welcome. The golden rule: any behavior change comes with a test that locks it in.
- Setup, style, and pull-request checklist →
CONTRIBUTING.md - Releasing / Packagist sync →
PUBLISHING.md - Changelog →
CHANGELOG.md
📦 Compatibility
| PHP | 8.2 · 8.3 · 8.4 |
| Frameworks | Laravel 10/11/12, Symfony 6/7, Slim 4, vanilla PHP |
| Dependencies | none — pure PHP, stdlib only |
👤 Author
Built by Md. Arifur Rahman (@arifur9993) — same author as the TypeScript engine. Comments, bug reports, feature ideas: open an issue or ping me on GitHub.
If this package saved you a week of "but the punches are in two timezones" debugging, ⭐ star the repo — it's the only marketing this library will ever do.
📜 License
MIT — see LICENSE. Use it commercially, fork it, vendor it, ship it.