Movements Reference Public

Data & Screen Reference

Data and screen reference for the Movements module: all six database tables and their key columns, controllers and routes, cron jobs, system-log events, statuses, permissions, and the mobility policy rule engine.

Guide version: r1 Module version: 1.1.0 Updated: 2026-07-22 Estimated time: 5 min 2 views
Reference

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 / slugMovements / movements
Display nameMovements
CategoryHuman Resource
Version1.0.0
Enable settingmodule_movements
Sidebar groupHR Operations (icon fa-exchange)
Migration tablemigrations_movements
Language filelanguage/english/movements_lang.php
NamespaceModules\Movements
DependenciesNone 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

ColumnMeaning
user_idThe employee.
effective_dateWhen the change takes effect.
movement_typenew_hire | promotion | transfer | salary_adjustment | role_change | manager_change | separation | correction.
from_team_id / to_team_idDepartment (team) before / after.
from_team_name / to_team_nameSnapshot titles — survive renames.
from_position_id / to_position_id, from_position / to_positionPosition id and snapshot title before / after.
from_manager_id / to_manager_idManager before / after.
from_salary / to_salaryMonthly salary before / after (permission-gated in the UI).
source / source_idmanual | internal_hiring | auto_capture | offboarding | legacy_backfill, plus the originating record id.
application_idThe internal application, when source is internal hiring.
reversed_movement_idThe movement this row corrects (for reversals).
idempotency_keySHA-256 of source + user + date + change — prevents duplicates (unique).
notesFree-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

ColumnMeaning
code, titleAuto code (e.g. IJP-0001) and the opening title.
position_id, team_id, hiring_manager_idTarget position, department, and hiring manager.
slots / filled_slotsOpenings available and filled.
work_arrangement, locationon_site | hybrid | remote, and location text.
description, responsibilities, requirementsLong text; requirements are one eligibility line each.
statusdraft | pending_approval | published | closed | filled | cancelled.
opens_at / closes_at, published_at, approved_byWindow dates, publish timestamp, and who published.
show_salary, salary_min / salary_maxWhether and what salary range to show applicants.
post_announcement, post_timelinePer-opening publication flags.
audience, audience_idsall | departments, plus the CSV of team ids for department scope.
announcement_id, timeline_post_idLinks 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.

SurfaceControllerMenu URL
Employee Movement (+ profile tabs)Movementsmovements
Internal Hiring workspaceInternal_hiringinternal-hiring
Internal Job Portal (self-service)Internal_jobsinternal-jobs
Mobility SettingsMovements_settingsmovements-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

New HirePromotion TransferSalary Adjustment Role ChangeManager Change SeparationCorrection

Movement sources

HR Update (manual)Internal Hiring Auto CaptureOffboarding Legacy Backfill

Opening status & allowed transitions

FromAllowed next
DraftPending Approval, Published, Cancelled
Pending ApprovalPublished, Draft, Cancelled
PublishedClosed, Filled, Cancelled
ClosedPublished, Filled
Filled— (terminal)
CancelledDraft

Application stages & statuses

AppliedScreening AssessmentInterview Offer / ApprovalSelected

Statuses: Submitted Withdrawn Rejected Selected.


Cron jobs

SlugSchedulePurpose
movements_capture_employee_movements20 2 * * * (02:20 daily)Diff-and-record Employee Master changes. First run baselines only.
movements_close_expired_openings10 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 keySeverityMeaning
create:employee_movementinfoA movement was recorded.
reverse:employee_movementwarningA movement was reversed (correction).
delete:employee_movementwarningA movement record was deleted.
create:internal_opening / update:internal_openinginfoOpening created / updated.
update_status:internal_openingwarningOpening approved / published / closed / cancelled.
delete:internal_openingwarningDraft opening deleted.
create:internal_applicationinfoApplication submitted.
update_stage:internal_applicationinfoApplication stage changed (or rejected).
withdraw:internal_applicationinfoApplication withdrawn.
select:internal_applicationwarningCandidate selected — employee updated + movement recorded.
create:mobility_override / decide:mobility_overrideinfo / warningException requested / decided.
update:movements_settingswarningMobility / 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.

#RuleKindBlocked key
1Opening is accepting applications (published, in window, free slot)Structuralopening_closed
2No existing active application for this openingStructuralactive_application_exists
3Usage below the rolling limitPolicy (overridable)mobility_limit_reached
4Minimum tenure met (when set & hire date known)Policy (overridable)minimum_tenure_not_met
5No active disciplinary case (when blocking is on)Policy (overridable)active_disciplinary_case
????
The window start is computed from the tenant-local clock and converted to UTC to match submit times. An approved override clears the policy rules (3–5) only; the structural rules (1–2) always apply. The "Request exception" CTA appears only when every block is a policy block and overrides are enabled.

Next steps

Was this guide helpful?

Report a content problem