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.

by GeekShop Computers (byron@geekshop.ca) · github.com/bigberryj/employee-time-tracking · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/bigberryj/employee-time-tracking/archive/refs/heads/main.zip

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.