Data & Screen Reference
The structured facts behind the module — its tables and key columns, controllers and routes, statuses and vocabularies, cron jobs, audit-log events, and the mobility-policy rule engine. For admins, implementers and support.
Manifest facts
| Module name / slug | Movements / movements |
| Display name | Movements |
| Category | Human Resource |
| Version | 1.0.0 |
| Enable setting | module_movements |
| Sidebar group | HR Operations (icon fa-exchange) |
| Migration table | migrations_movements |
| Language file | language/english/movements_lang.php |
| Namespace | Modules\Movements |
| Dependencies | None required. Optional (guarded) integrations: Announcements, Timeline (posts), Job Positions, Salary/Discipline (Compliance), mPDF. |
Database tables (6)
All tables end with the standard audit block (created_by, created_at,
updated_at, deleted) and are soft-deleted. Key columns per table:
employee_movements — the immutable audit trail
| Column | Meaning |
|---|---|
user_id | The employee. |
effective_date | When the change takes effect. |
movement_type | new_hire | promotion | transfer | salary_adjustment | role_change | manager_change | separation | correction. |
from_team_id / to_team_id | Department (team) before / after. |
from_team_name / to_team_name | Snapshot titles — survive renames. |
from_position_id / to_position_id, from_position / to_position | Position id and snapshot title before / after. |
from_manager_id / to_manager_id | Manager before / after. |
from_salary / to_salary | Monthly salary before / after (permission-gated in the UI). |
source / source_id | manual | internal_hiring | auto_capture | offboarding | legacy_backfill, plus the originating record id. |
application_id | The internal application, when source is internal hiring. |
reversed_movement_id | The movement this row corrects (for reversals). |
idempotency_key | SHA-256 of source + user + date + change — prevents duplicates (unique). |
notes | Free-text reason / feedback. |
employee_movement_snapshots — state for auto-capture
One row per employee: team_id, team_name, position_id,
position_title, monthly_salary, and a snapshot_hash. The
daily job compares the live Employee Master against this snapshot to detect changes.
internal_openings — internal roles
| Column | Meaning |
|---|---|
code, title | Auto code (e.g. IJP-0001) and the opening title. |
position_id, team_id, hiring_manager_id | Target position, department, and hiring manager. |
slots / filled_slots | Openings available and filled. |
work_arrangement, location | on_site | hybrid | remote, and location text. |
description, responsibilities, requirements | Long text; requirements are one eligibility line each. |
status | draft | pending_approval | published | closed | filled | cancelled. |
opens_at / closes_at, published_at, approved_by | Window dates, publish timestamp, and who published. |
show_salary, salary_min / salary_max | Whether and what salary range to show applicants. |
post_announcement, post_timeline | Per-opening publication flags. |
audience, audience_ids | all | departments, plus the CSV of team ids for department scope. |
announcement_id, timeline_post_id | Links to the created announcement / timeline post. |
internal_applications & internal_application_stages
internal_applications: opening_id (0 for direct promotion requests),
user_id, application_type (opening_application | promotion_request),
status (submitted | withdrawn | rejected | selected), current_stage
(applied | screening | assessment | interview | offer | selected), the
submitted_at / withdrawn_at / selected_at timestamps,
counts_toward_limit, a serialized policy_snapshot taken at submission,
and cover_note.
internal_application_stages: an append-only history — application_id,
from_stage / to_stage, notes, plus the actor
(created_by) and time (created_at).
mobility_overrides — audited policy exceptions
user_id, opening_id / application_id, a serialized
failed_rules list captured at request time, the reason, a
status (pending | approved | rejected | expired), the approver_id and
decided_at, an optional expires_at, and remarks.
Controllers & routes
Four controllers, all resolved through the module. Menu URLs use hyphens; underscore aliases exist for compatibility.
| Surface | Controller | Menu URL |
|---|---|---|
| Employee Movement (+ profile tabs) | Movements | movements |
| Internal Hiring workspace | Internal_hiring | internal-hiring |
| Internal Job Portal (self-service) | Internal_jobs | internal-jobs |
| Mobility Settings | Movements_settings | movements-settings |
Every controller gates the whole class on module_movements, then applies per-action
permission checks. Models extend Crud_model and hold all SQL; there are six models,
one per table.
Statuses & vocabularies
Movement types
Movement sources
Opening status & allowed transitions
| From | Allowed next |
|---|---|
| Draft | Pending Approval, Published, Cancelled |
| Pending Approval | Published, Draft, Cancelled |
| Published | Closed, Filled, Cancelled |
| Closed | Published, Filled |
| Filled | — (terminal) |
| Cancelled | Draft |
Application stages & statuses
Statuses: Submitted Withdrawn Rejected Selected.
Cron jobs
| Slug | Schedule | Purpose |
|---|---|---|
movements_capture_employee_movements | 20 2 * * * (02:20 daily) | Diff-and-record Employee Master changes. First run baselines only. |
movements_close_expired_openings | 10 1 * * * (01:10 daily) | Close published openings past their closing date. |
System-log events
Every mutation is logged (event key = action:component). Warnings mark the
higher-impact events.
| Event key | Severity | Meaning |
|---|---|---|
create:employee_movement | info | A movement was recorded. |
reverse:employee_movement | warning | A movement was reversed (correction). |
delete:employee_movement | warning | A movement record was deleted. |
create:internal_opening / update:internal_opening | info | Opening created / updated. |
update_status:internal_opening | warning | Opening approved / published / closed / cancelled. |
delete:internal_opening | warning | Draft opening deleted. |
create:internal_application | info | Application submitted. |
update_stage:internal_application | info | Application stage changed (or rejected). |
withdraw:internal_application | info | Application withdrawn. |
select:internal_application | warning | Candidate selected — employee updated + movement recorded. |
create:mobility_override / decide:mobility_override | info / warning | Exception requested / decided. |
update:movements_settings | warning | Mobility / HR-operations settings updated. |
The mobility policy engine
Evaluated by the server for the eligibility panel, on submission, and again at selection. The result reports whether the employee is eligible, which rules block them, and whether the block is overridable.
| # | Rule | Kind | Blocked key |
|---|---|---|---|
| 1 | Opening is accepting applications (published, in window, free slot) | Structural | opening_closed |
| 2 | No existing active application for this opening | Structural | active_application_exists |
| 3 | Usage below the rolling limit | Policy (overridable) | mobility_limit_reached |
| 4 | Minimum tenure met (when set & hire date known) | Policy (overridable) | minimum_tenure_not_met |
| 5 | No active disciplinary case (when blocking is on) | Policy (overridable) | active_disciplinary_case |