This is the technical migration guide for moving from the abandoned WP Human Resource Management plugin (original slug hrm, last shipped around 2019, removed from WordPress.org in 2025) to Punchwell.
The important thing to understand up front: this is a migration, not a rebuild. Punchwell is a maintained fork of the same codebase, so it uses the same data model — your employees are still WordPress users, and your records still live in the same wp_hrm_* database tables. Your employees, attendance, and leave records carry over in place. You are not re-entering staff or rebuilding history.
Most of the schema upgrades itself the moment Punchwell runs. A small number of older tables use different column names than the current code, so the fork ships two SQL files that copy that data into the new columns and confirm the result. That’s the only part that isn’t automatic.
Time: roughly 30–60 minutes on a typical site.
Skill level: comfortable taking a full backup and running a couple of SQL files (phpMyAdmin or WP-CLI).
Current build: Punchwell base 2.14.1, database schema version 3.3.
The single most important step is the backup. With a verified backup in hand, every step below is reversible.
What carries over (and what doesn’t)
Carries over automatically — same lineage, same database:
- Employees — they are WordPress users; nothing to re-import.
- Attendance / punch records (
wp_hrm_attendance). - Leave records (
wp_hrm_leave) — after the column copy in Step 5. - Leave type names, departments, designations/job titles, shifts, work-experience entries (after the copy).
- Roles — the legacy
hrm_employerrole is auto-renamed tohrm_employeeon first admin load.
You must re-enter manually — these can’t be auto-migrated:
- Office IP allowlist — the legacy
wp_hrm_whitelisttable is dropped during migration, and the current code reads office IPs from a different place. Save your existing values first (Step 2), then re-enter them in Punchwell. - Leave-type yearly entitlements — type names survive, but re-enter each type’s annual entitlement under the Leave settings.
- Payroll / salary — the original
wp_hrm_salarystructure is a completely different model. Payroll starts fresh in Punchwell’s payroll engine. (For how Punchwell handles pay, see the Payroll export docs.)
Before you start — read this
- Why a SQL script is needed at all. Most tables upgrade cleanly via Punchwell’s built-in
dbDeltareconcile. But a few legacy tables (Leave and Work-Experience especially) store data under old column names.dbDeltaadds the new columns but cannot rename or copy your data into them — so the script does that copy. Without it, Leave and Work-Experience records would appear blank. - Order is critical. You must let
dbDeltarun (by loading wp-admin once on Punchwell) before you run the migration SQL — otherwise the new columns don’t exist yet and there’s nothing to copy into. - Table prefix. The scripts assume the default
wp_prefix. If your install uses a different prefix (check$table_prefixinwp-config.php), find-and-replacewp_in both SQL files first. - The SQL file headers reference older version numbers (they say “2.4.0” / db version “2.1”). That’s cosmetic — those headers predate the current build. What actually matters is that you load wp-admin once on Punchwell so
dbDeltabrings the schema all the way up to DB 3.3 before you run the migration. Verification (Step 6) confirms you’re stamped at 2.14.1 / 3.3. - Do it on staging first. Strongly recommended: run the whole migration on a staging copy, confirm it works, then repeat on production.
Step 1 — Take a full backup (do not skip)
Back up both the database and the files.
With a backup plugin: UpdraftPlus, BlogVault, Duplicator, or your host’s one-click backup. Take a fresh full backup and confirm it completed.
With WP-CLI:
wp db export pre-punchwell-migration.sql
tar -czf pre-punchwell-files.tgz wp-content/plugins wp-content/uploads
Verify the backup is real — non-zero file size, downloadable, and ideally test-restorable on staging. Do not proceed until you have it.
Step 2 — Record your current state
Before changing anything, write down what you can compare against afterward:
- Your current plugin version (Plugins screen, or
readme.txt). - Approximate counts: number of employees, leave records, attendance rows.
- Your office IP allowlist, if you use the IP/attendance feature — because the legacy whitelist table is dropped during migration. Run this read-only query and save the output:
SELECT id, ip FROM wp_hrm_office_time; -- save these; you'll re-enter them
-- older installs may instead have:
-- SELECT * FROM wp_hrm_whitelist;
You’ll re-enter these IPs later in Punchwell under Punchwell → Structure → Locations and Punchwell → Settings → IP & Geofence. (For how the allowlist works once you’re on Punchwell — exact IPs, CIDR blocks, address ranges, per-office and per-employee scopes — see IP & Geofence settings.)
Step 3 — Swap the plugin
- In Plugins → Installed Plugins, Deactivate the original WP Human Resource Management plugin. Do not delete it yet — keeping it lets you roll back instantly.
- Install Punchwell:
- Upload the Punchwell ZIP via Plugins → Add New → Upload Plugin, or
- copy the plugin folder into
wp-content/plugins/(keep the folder slugwp-hrm).
- Activate Punchwell.
If you used any add-ons (Recruitment, Loan, Attendance Reports, Permission, Front-End), install Punchwell’s matching add-on versions too. The base plugin must be active or add-ons self-deactivate. See Installation for the full add-on list.
Step 4 — Let the database reconcile run (critical ordering)
Simply load wp-admin as an administrator. On the first admin page load, Punchwell runs its idempotent dbDelta reconcile, which adds the new tables and columns — for example, Leave gains status, comments, type, created_at, and updated_at; Work-Experience gains employee_id, title, start, end, and description. It also renames the legacy hrm_employer role to hrm_employee and stamps the version options (hrm_version = 2.14.1, hrm_db_version = 3.3).
(Equivalent alternative: deactivate then reactivate the Punchwell base plugin.)
This step adds, never deletes — no data is touched. But do not run the migration SQL until you have done this, because the script copies into the columns this step creates.
Step 5 — Run UPGRADE-DATA-MIGRATION.sql
Run the file that ships with Punchwell against your database via phpMyAdmin (Import / SQL tab) or WP-CLI:
wp db query < UPGRADE-DATA-MIGRATION.sql
What it does, in order:
- Prints your existing IP-config tables to the output (a reference snapshot, since the legacy whitelist table is dropped in step 5 below).
- Copies Leave data from the old columns into the new ones (
leave_status → status,leave_comments → comments,leave_type_id → type) and seedscreated_at/updated_atfrom each record’s start time. - Copies Work-Experience data from the old OrangeHRM-style
eexp_*columns into the new columns. The raw company, comments, and dates are also preserved indescriptionso nothing is lost even if an old free-text date doesn’t parse cleanly. - Normalizes legacy
0000-00-00timestamps to NULL across several tables — those invalid dates fatal under MySQL 8 strict mode. - Drops three wholly-unused legacy tables:
wp_hrm_education,wp_hrm_skill, andwp_hrm_whitelist.
Do NOT run Section 6 of that file yet. Section 6 is the optional drop of the now-redundant old columns (the ones the script just copied from). It is commented out on purpose. Leave it commented until verification (Step 6) confirms the copy succeeded — that’s what makes the migration reversible.
After this step, three things still need to be re-entered by hand (the script can’t map them): payroll/salary (regenerate in the payroll engine), leave-type yearly entitlements (names survive, entitlements don’t), and your office IPs (you saved them in Step 2).
Step 6 — Run UPGRADE-VERIFY.sql and read the results
wp db query < UPGRADE-VERIFY.sql
This is read-only — it changes nothing. Check the output against these expectations:
| Check | Expected result |
|---|---|
| New columns present (Leave + Work-Experience) | All listed columns appear. If any are missing, you ran the SQL before Step 4 — redo Step 4, then re-run the migration and verify. |
| Version stamps | hrm_version = 2.14.1, hrm_db_version = 3.3. (The SQL file headers cite older numbers — cosmetic. What matters is that wp-admin loaded once so dbDelta reconciled to 3.3.) |
| Row counts (attendance, leave, work_experience, …) | Match your pre-upgrade numbers from Step 2 — nothing vanished. |
leave_rows_NOT_copied |
0 |
workexp_rows_NOT_copied |
0 |
| Orphan checks (leave / attendance / work-experience pointing at missing users) | 0 each |
| Residual zero-dates in attendance | 0 |
| Employee roles | hrm_employees / hrm_managers > 0; legacy_employer = 0 (auto-renamed on first admin load) |
Legacy tables (education, skill, whitelist) |
0 rows returned — they were dropped |
If anything is off — a non-zero NOT_copied, missing columns, unexpected orphans — stop and roll back (Step 8). Do not run Section 6.
Step 7 — Smoke-test the admin, then finish up
In wp-admin, confirm the live paths work:
- Punchwell Dashboard loads without errors.
- Employees list shows your people; open a profile and confirm details are intact.
- Add a test employee, then delete it — confirms the old PHP 8 “can’t add employee” hang is gone.
- Attendance — punch in and punch out for a test user; confirms punch-out works.
- Leave — open an existing leave record and confirm status, type, and comments display (not blank). Blank here means the copy didn’t happen — see Troubleshooting.
- Office-IP lock (if you use it) — re-enter your saved IPs under Structure → Locations / Settings → IP & Geofence, flag a test employee as office-only, and confirm enforcement behaves as expected. (See IP & Geofence.)
- Leave types — re-enter each type’s yearly entitlement.
When everything checks out:
- Only now, if you want a clean schema, you may uncomment and run Section 6 of
UPGRADE-DATA-MIGRATION.sqlto drop the redundant old columns. This is optional — leaving them in place is harmless. - Delete the old plugin files once you’re confident. You still have your Step-1 backup.
Step 8 — Rollback plan
If anything goes wrong at any point:
- Deactivate Punchwell.
- Restore your Step-1 backup (database + files). With a backup plugin, use its restore. With WP-CLI:
wp db import pre-punchwell-migration.sql - Reactivate the original plugin — this is exactly why you didn’t delete it in Step 3.
You’re back to your pre-migration state.
Why rollback stays safe: you never deleted the old plugin until Step 7, and Section 6 (the destructive old-column drop) is gated behind a clean verification. Until you run Section 6, the old columns still hold your original data — so even a partial migration is fully reversible from your backup.
Troubleshooting
- Leave or Work-Experience records look blank after migrating. You almost certainly ran the SQL before Step 4, so the new columns didn’t exist yet and nothing copied. Restore the backup, then redo Steps 4 → 5 → 6 in order.
UPGRADE-VERIFY.sqlreports missing new columns. Same cause:dbDeltahadn’t run. Load wp-admin as an administrator (or deactivate/reactivate the base plugin), then re-run the migration and verification.- Wrong-table-prefix errors. Your install isn’t using the
wp_prefix. Find-and-replacewp_in both SQL files with your real prefix (fromwp-config.php) and re-run. - Orphan checks come back non-zero. Some WordPress user accounts, or the old
emp_number → employee_idmapping, didn’t line up. Review the sample rows the verify script prints before proceeding. - Still seeing PHP 8 errors after migrating. Confirm you actually activated Punchwell (version 2.14.1) and not the original (2.2.17 or lower). Check the version on the Plugins screen.
FAQ
Will I lose any data?
No. Punchwell shares the original plugin’s data model, so your employees, attendance, and leave records stay in place. The migration script only copies legacy columns into their new names and drops three tables Punchwell never reads. As long as you take a backup first (Step 1), the whole process is reversible.
Do I need to re-create my employees?
No. Employees are WordPress users in both the original and Punchwell — they’re already there. Nothing to re-import.
Why are the version numbers in the SQL file different from 2.14.1?
The SQL file headers were written for an earlier release and reference older numbers. They’re cosmetic. What actually upgrades your schema is dbDelta, which runs when you load wp-admin (Step 4) and brings the database all the way to the current version 3.3. The verify script confirms you end up stamped at 2.14.1 / 3.3.
Can I do this without WP-CLI?
Yes. Run both .sql files through phpMyAdmin (the Import tab, or paste into the SQL tab) instead. The steps and order are identical.
My site uses a custom table prefix. What changes?
Open both SQL files and find-and-replace wp_ with your actual prefix (the $table_prefix value in wp-config.php) before running them. Everything else is the same.
What about my payroll and salary data?
The original salary structure is a different model, so it doesn’t auto-migrate. Punchwell’s payroll engine starts fresh — set per-employee pay type and rate, then generate payout reports and exports. See the Payroll export docs.
Files referenced (they ship with Punchwell): UPGRADE-DATA-MIGRATION.sql and UPGRADE-VERIFY.sql.
Punchwell is an independent, third-party maintained fork of the GPL-licensed “WP Human Resource Management” plugin. Sturdyhaus is not affiliated with, endorsed by, or sponsored by wpspear, weDevs, or the original author. “WP Human Resource Management” is referenced descriptively only, to help affected users find a maintained alternative.