Back to Documentation

missed clockout

# Missed Clock-Out Management

Detects when employees forget to clock out and provides a workflow for resolution.

## Overview

When enabled, if an employee forgets to clock out and attempts to login again, the system:
1. Detects the open session (any open session, same-day or previous)
2. Redirects employee to submit a claim with actual logout time and reason
3. Creates an incident for admin review
4. Automatically logs the employee in for the new day
5. Admin sees warning banner in dashboard if pending incidents exist

**Note:** This feature is disabled by default. Enable it in Settings → Missed Clock-Out Management.

## Employee Flow

1. Employee tries to clock in with an open session (any open session, same-day or previous)
2. System redirects to `/{company}/missed-clockout` form
3. Employee provides:
   - Actual clock-out time (datetime picker)
   - Reason: Forgot, Closed tab by accident, System issue, Emergency, Internet lost, Device died
4. Claim submitted → employee is automatically logged in for today → redirected to logged-in page

## Admin Flow

1. Admin sees warning banner in dashboard: "X Unresolved Missed Clock-Outs"
2. Click "Review Now" or navigate to `Admin Dashboard → ⏰ Missed Clock-Outs`
3. Review employee's claimed time and reason
4. Resolution options:
   - **Approve** - Accept employee's claimed logout time
   - **Reject** - Set different logout time (override)
5. Add notes for audit trail
6. Resolution updates the actual work log in database

## Settings

Located in Settings → Missed Clock-Out Management:

| Setting | Default | Description |
|---------|---------|-------------|
| `missed_clockout_enabled` | Disabled | Enable/disable the entire feature |
| `block_reports_on_pending` | Disabled | Block scheduled reports until all incidents resolved |

## Database Schema

```sql
-- companies table additions
missed_clockout_enabled BOOLEAN DEFAULT FALSE
block_reports_on_pending BOOLEAN DEFAULT FALSE

-- Table: missed_clockout_incidents
CREATE TABLE missed_clockout_incidents (
    id SERIAL PRIMARY KEY,
    company_slug VARCHAR(255),
    log_id INTEGER,
    employee_id INTEGER,
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    login_time TIMESTAMP,
    employee_claimed_logout_time TIMESTAMP,
    employee_reason TEXT,
    employee_claimed_at TIMESTAMP,
    status VARCHAR(20) DEFAULT 'pending',
    admin_set_logout_time TIMESTAMP,
    admin_notes TEXT,
    resolved_at TIMESTAMP,
    resolved_by VARCHAR(100)
);
```

## Status Values

- `pending` - Incident created, awaiting employee claim
- `employee_claimed` - Employee submitted claim, awaiting admin review
- `approved` - Admin approved employee's claimed time
- `rejected` - Admin rejected and set different time

## API Functions

| Function | Description |
|----------|-------------|
| `check_open_sessions_by_employee_id` | Check for open sessions from previous days |
| `create_and_submit_clockout_claim` | Create incident and submit claim in one call |
| `get_missed_clockout_incidents` | List all incidents for company |
| `get_missed_clockout_incident` | Get single incident details |
| `resolve_missed_clockout` | Admin approves/rejects with final time |
| `get_missed_clockout_settings` | Get feature settings |
| `update_missed_clockout_enabled` | Enable/disable feature |
| `update_block_reports_on_pending` | Enable/disable report blocking |
| `get_pending_clockout_count` | Get count of unresolved incidents |

## Routes

| Route | Method | Description |
|-------|--------|-------------|
| `/{company}/missed-clockout` | GET | Show employee claim form |
| `/{company}/missed-clockout` | POST | Submit employee claim |
| `/{company}/admin/missed-clockouts` | GET | Admin incident list |
| `/{company}/admin/resolve-clockout/{id}` | GET | Admin resolution form |
| `/{company}/admin/resolve-clockout/{id}` | POST | Submit resolution |

## Detection Logic

Open session detection occurs in `face_verify_server.py`:
```python
# Check for ANY open session (same-day or previous)
SELECT id, login_time FROM {company}_employees_logs
WHERE employee_id = %s 
AND logout_time IS NULL
ORDER BY login_time DESC LIMIT 1
```

## Email Notification

Admin receives email when employee submits claim:
- Subject: `[Company Name] Missed Clock-Out Requires Review`
- Contains: Employee name, original login time, link to admin dashboard