Add Employee Timeclock feature with kiosk, attendance report, and payroll CSV export

- New EmployeeClockEntry entity (facility-level attendance, separate from job time entries)
- KioskPin added to ApplicationUser; TimeclockKioskToken added to Company
- TimeclockController: clock in/out, who's in, 14-day history, manager edit/delete,
  tablet kiosk with device-cookie auth, PIN management via Users edit page
- Kiosk UI: employee tile grid + 4-digit PIN pad + auto-detect clock-in vs clock-out
- Attendance report at /Reports/Attendance with weekly subtotal rows
- Payroll CSV export at /Reports/AttendanceCsv (flat, one row per segment)
- AllowCustomFormulas wired through PlatformSubscriptionController + subscription views
- Fix soft-delete bug on CustomItemTemplate (missing HasQueryFilter in OnModelCreating)
- Help article (Help/Timeclock.cshtml) and AI knowledge base updated
- Migrations: AddEmployeeTimeclock, AddTimeclockKioskToken

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 19:53:13 -04:00
parent f625be01a3
commit 6c2fe6e1c4
40 changed files with 24125 additions and 16 deletions
@@ -0,0 +1,173 @@
@{
ViewData["Title"] = "Timeclock";
}
<div class="d-flex align-items-center gap-2 mb-3">
<a asp-controller="Help" asp-action="Index" class="btn btn-sm btn-outline-secondary"><i class="bi bi-arrow-left"></i></a>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a asp-controller="Help" asp-action="Index">Help</a></li>
<li class="breadcrumb-item active">Timeclock</li>
</ol>
</nav>
</div>
<div class="row g-4">
<div class="col-lg-9">
<section id="overview" class="mb-5">
<h2 class="h4 fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-info-circle text-primary me-2"></i>Overview
</h2>
<p>
The Timeclock module tracks facility-level employee attendance &mdash; when workers arrive and
leave the shop each day. It is separate from <em>Job Time Entries</em> (which log hours billed
against a specific job). Timeclock is about payroll and attendance; Job Time Entries are about
job costing.
</p>
<p>
Multiple clock-in/clock-out pairs per day are fully supported. Employees can clock out for
lunch, clock back in, clock out for a break, and so on. Each segment is recorded separately
with its own in/out times and duration. Daily and weekly totals are computed automatically.
</p>
<p>
Find Timeclock under <strong>Shop Floor &rsaquo; Timeclock</strong> in the left sidebar.
</p>
</section>
<section id="clocking-in-out" class="mb-5">
<h2 class="h4 fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-box-arrow-in-right text-success me-2"></i>Clocking In and Out
</h2>
<p>
From the Timeclock dashboard, your current status card shows whether you are clocked in or out
and how long the current segment has been running.
</p>
<ul>
<li><strong>Clock In</strong> &mdash; click the green &ldquo;Clock In&rdquo; button. Your start time is recorded immediately.</li>
<li><strong>Clock Out</strong> &mdash; click the red &ldquo;Clock Out&rdquo; button. Hours worked for that segment are calculated and saved.</li>
<li><strong>Multiple segments per day</strong> &mdash; after clocking out, just clock in again when you return. Each segment is stored separately.</li>
</ul>
<div class="alert alert-info alert-permanent">
<i class="bi bi-info-circle me-2"></i>
You cannot clock in while already clocked in. You will see an error if you try &mdash; clock out first.
</div>
</section>
<section id="whos-in" class="mb-5">
<h2 class="h4 fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-people-fill text-primary me-2"></i>Who&rsquo;s In
</h2>
<p>
The &ldquo;Who&rsquo;s In&rdquo; card on the dashboard shows everyone currently clocked in, with
their start time and elapsed hours. It refreshes automatically every 60&nbsp;seconds &mdash;
no manual reload needed.
</p>
</section>
<section id="kiosk" class="mb-5">
<h2 class="h4 fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-tablet me-2"></i>Shop Floor Kiosk
</h2>
<p>
The Timeclock Kiosk is a tablet-friendly page designed to live on a shared device in the shop.
Employees do not need to log in &mdash; they tap their name tile and enter a 4-digit PIN.
The system automatically clocks them in (if currently out) or out (if currently in). A confirmation
screen shows the time, segment duration, and today&rsquo;s running total, then returns to the
employee grid after 4&nbsp;seconds.
</p>
<h5 class="fw-semibold mt-3">Activating the kiosk</h5>
<ol>
<li>On the tablet, log in as a Manager or Company Admin.</li>
<li>Navigate to <strong>Timeclock &rsaquo; Activate Kiosk</strong> (or go to <code>/Timeclock/Kiosk/Activate</code>).</li>
<li>The system generates a device token and writes a secure cookie to that browser.</li>
<li>From now on, <code>/Timeclock/Kiosk</code> works without login on that device.</li>
</ol>
<p>
If the tablet is lost or replaced, re-visit <strong>Activate Kiosk</strong> on a new device. The
old token is revoked automatically. To deactivate without re-activating, ask a Manager to clear the token from Company Settings.
</p>
<h5 class="fw-semibold mt-3">Setting employee PINs</h5>
<ol>
<li>Go to <strong>Settings &rsaquo; Users</strong> and click the employee&rsquo;s name.</li>
<li>Scroll to the <strong>Timeclock Kiosk PIN</strong> section at the bottom of the Edit User page.</li>
<li>Enter a 4-digit PIN and click <strong>Set PIN</strong>.</li>
<li>To disable an employee on the kiosk, click <strong>Clear</strong>.</li>
</ol>
<p>
Only employees with a PIN set will appear on the kiosk employee grid. Employees without a PIN
cannot use the kiosk tablet.
</p>
</section>
<section id="manager-tools" class="mb-5">
<h2 class="h4 fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-shield-check text-warning me-2"></i>Manager Tools
</h2>
<p>
Managers and Company Admins have additional controls on the Timeclock dashboard.
Workers cannot edit or delete their own entries &mdash; all corrections must go through a Manager or Company Admin.
</p>
<ul>
<li>
<strong>Edit an entry</strong> &mdash; click the pencil icon next to any entry in the
My Recent History table or the Team History table. Adjust clock-in time, clock-out time,
or notes. Hours worked are recalculated automatically on save.
</li>
<li>
<strong>Delete an entry</strong> &mdash; click the trash icon. The entry is soft-deleted
and excluded from all totals and reports.
</li>
<li>
<strong>Team History</strong> &mdash; the manager section at the bottom of the dashboard
lets you load any date range for all employees, with full punch detail and edit/delete controls.
</li>
</ul>
</section>
<section id="reports" class="mb-5">
<h2 class="h4 fw-bold border-bottom pb-2 mb-3">
<i class="bi bi-bar-chart-line text-info me-2"></i>Attendance Report &amp; CSV Export
</h2>
<p>
Go to <strong>Reports &rsaquo; Attendance</strong> for a date-range attendance summary.
Each employee&rsquo;s card shows every daily punch segment and a day total, plus
a weekly subtotal row at the bottom of each ISO week. Managers see all employees;
workers see only their own history.
</p>
<p>
Click <strong>Export CSV (Payroll)</strong> to download a flat CSV file of the same
date range. Each row is one clock segment and includes:
</p>
<ul>
<li>Employee Name</li>
<li>Date and Day of Week</li>
<li>Clock In and Clock Out times</li>
<li>Segment Hours, Day Total Hours, and Week Total Hours</li>
<li>Notes</li>
</ul>
<p>
The CSV is designed to be imported directly into payroll software or handed off to a
payroll provider. Every row is self-contained (no merged cells or subtotal-only rows)
so it works with Excel, Google Sheets, and most payroll import wizards.
</p>
</section>
</div>
<div class="col-lg-3 d-none d-lg-block">
<div class="card shadow-sm sticky-top" style="top:80px;">
<div class="card-body">
<h6 class="fw-bold mb-3">On This Page</h6>
<ul class="list-unstyled small">
<li><a href="#overview" class="text-decoration-none">Overview</a></li>
<li><a href="#clocking-in-out" class="text-decoration-none">Clocking In &amp; Out</a></li>
<li><a href="#whos-in" class="text-decoration-none">Who&rsquo;s In</a></li>
<li><a href="#kiosk" class="text-decoration-none">Shop Floor Kiosk</a></li>
<li><a href="#manager-tools" class="text-decoration-none">Manager Tools</a></li>
<li><a href="#reports" class="text-decoration-none">Attendance Report &amp; CSV</a></li>
</ul>
</div>
</div>
</div>
</div>