WP Manifestindependent plugin directory
manifest / utilities / employee-time-tracking

Employee Time Tracking

WordPress plugin: REST API for employee time tracking with cron-style recurring rules and CSV payroll export.

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/bigberryj/employee-time-tracking/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

A WordPress plugin that exposes a REST API for tracking employee time entries against projects, with cron-style recurring rules and CSV payroll export.

What you get

  • Four custom tables under the WP prefix: wp_ett_employees, wp_ett_projects, wp_ett_time_entries, wp_ett_recurring_rules.
  • REST namespace employee-time-tracking/v1 with full CRUD on employees, projects, and time entries, plus list/create/update/delete on recurring rules and a POST /recurring-rules/run endpoint that manually fires the cron.
  • Recurring rules (daily / weekly / biweekly / monthly) that generate time entries automatically via wp_schedule_event(..., hourly, 'ett_run_recurring_rules').
  • CSV payroll export at GET /export?from=YYYY-MM-DD&to=YYYY-MM-DD returning a header row plus one row per time entry, with gross_pay computed from hours × hourly_rate (only when both entry and project are billable).
  • Admin settings page under Settings → Time Tracking for default cadence, max hours per day, CSV buffer days, and toggle for CSV export.
  • Strict sanitiser for every payload — mode whitelists for status, literal === 1 for booleans, > 0 for ID arrays, hours clamped to 0–24, hourly rate clamped to 0–9999.99.

REST endpoints

All write routes require a valid WP REST nonce in the X-WP-Nonce header and a manage_options (or edit_posts for own-employee POST/PUT) capability.

Method Path Capability Purpose
GET /employees read List employees
POST /employees manage_options Create employee
PUT /employees/{id} manage_options Update employee
DELETE /employees/{id} manage_options Delete employee
GET /projects read List projects
POST /projects manage_options Create project
PUT /projects/{id} manage_options Update project
DELETE /projects/{id} manage_options Delete project
GET /time-entries read List time entries (filters: employee_id, project_id, from, to, limit, offset)
POST /time-entries manage_options / edit_posts Create time entry
PUT /time-entries/{id} manage_options / edit_posts Update time entry
DELETE /time-entries/{id} manage_options Delete time entry
GET /recurring-rules read List recurring rules
POST /recurring-rules manage_options Create rule
PUT /recurring-rules/{id} manage_options Update rule
DELETE /recurring-rules/{id} manage_options Delete rule
POST /recurring-rules/run manage_options Manually trigger generation (optional ?today=YYYY-MM-DD)
GET /export?from=…&to=… manage_options JSON wrapper around the CSV body

Installation

  1. Copy the employee-time-tracking/ folder into wp-content/plugins/.
  2. Activate the plugin under Plugins → Installed Plugins. The activation hook creates the four tables and schedules the hourly cron.
  3. (Optional) Grant editors edit_posts if you want them to log their own time entries through POST /time-entries.
  4. Test with curl or the WordPress REST console under Tools → REST API.

Quick smoke test

# Get a nonce (replace /wp-login.php + creds as needed).
NONCE=$(curl -s -c cookies.txt http://example.com/wp-login.php \
    -d 'log=admin&pwd=password&wp-submit=Log+In' \
    -b cookies.txt | grep wp-rest | head -1)

# Create an employee.
curl -X POST -H "X-WP-Nonce: $NONCE" \
     -H 'Content-Type: application/json' \
     -d '{"full_name":"Alice","email":"alice@example.com","hourly_rate":60}' \
     http://example.com/wp-json/employee-time-tracking/v1/employees

Local development

cd /home/byron/projects/employee-time-tracking
php qa/lint.php        # php -l on every PHP file (14 files, all OK)
php tests/run-tests.php  # 72 assertions across CRUD, sanitiser, CSV, recurring

The test runner is plain PHP — no PHPUnit, no MySQL, no WordPress required. It loads qa/phpstan-wordpress-stubs.php which provides minimal add_action/get_option/$wpdb/etc. stubs that keep enough state to assert behaviour.

CSV export format

entry_id,employee_name,employee_email,project_name,client_name,work_date,hours,billable,hourly_rate,gross_pay,notes
1,Alice,alice@example.com,Website Redesign,Acme,2026-09-13,8.00,1,60.00,480.00,"first ""half"" of the day"

Comma, double-quote, and newline characters in any cell are properly escaped per RFC 4180 (double-quote wrap + double-up internal quotes). gross_pay is hours × hourly_rate only when both the time entry and the project are billable; otherwise it's 0.00.

Recurring rules

A rule has: hours, cadence (daily / weekly / biweekly / monthly), optional weekday (0–6, used with weekly / biweekly), start_date, optional end_date, and last_generated_date (managed internally).

When the cron fires (every hour) the engine walks each active rule and inserts a time entry for every due date after last_generated_date (or start_date on first run) up to today (or end_date if earlier). The generator is idempotent: re-running it produces no duplicates.

Manual run:

curl -X POST -H "X-WP-Nonce: $NONCE" \
     http://example.com/wp-json/employee-time-tracking/v1/recurring-rules/run

Uninstall

Drop the four wp_ett_* tables and the ett_settings option. The uninstall.php script runs only when the user deletes the plugin from the Plugins screen (not on simple deactivate).

License

MIT — see LICENSE.