Document: 01_DATA_SOURCES_INVENTORY.md Module: KPI Matrix (Employee Performance Management) Author: AI Research Agent Date: February 2026 Status: Implemented — data-source inventory retained as reference (consumed by
Kpi_calculation_engine; see 02 Appendix A)
1. Overview
This document catalogs every existing data point in ERPat that can serve as input for KPI calculations. Each source is documented with its model, table, key columns, available aggregation methods, and KPI applicability.
Total Data Sources Identified: 15 existing models (no new data collection needed for core KPIs)
2. Attendance Data
2.1 Attendance_model (ci_attendance)
File: application/models/Attendance_model.php (719 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
log_type |
VARCHAR | Clock-in/out pattern analysis | COUNT by type per period |
status |
VARCHAR | Approval compliance | COUNT approved vs pending |
in_time / out_time |
DATETIME | Punctuality, schedule compliance | Compare against schedule |
log_date |
DATE | Daily tracking | GROUP BY date for patterns |
Key Methods:
get_details($options)— Lines 258-400. Full SQL JOIN withattendance_metrics,users,schedule,team. Supports filters:id,log_type,status, date range (start_date/end_date),user_id,department_id,active_only,allowed_members,access_type.get_summary_details($options)— Lines 401+. Simplified aggregate query for summaries.
2.2 Attendance_metrics_model (ci_attendance_metrics)
File: application/models/Attendance_metrics_model.php (53 lines)
18 Metric Columns (returned by get_metric_fields()):
| Column | Type | KPI Category | Scoring Direction |
|---|---|---|---|
log_date |
DATE | Reference | — |
duration |
DECIMAL | Time Management | Higher = Better |
bonus |
DECIMAL | Attendance | Higher = Better |
schedule |
DECIMAL | Reference (expected hours) | — |
worked |
DECIMAL | Attendance | Higher = Better |
late |
DECIMAL | Punctuality | Lower = Better |
over |
DECIMAL | Overtime Analysis | Context-dependent |
under |
DECIMAL | Undertime | Lower = Better |
reg_ot |
DECIMAL | Regular Overtime | Context-dependent |
rest_ot |
DECIMAL | Rest Day Overtime | Context-dependent |
special_ot |
DECIMAL | Special Holiday OT | Context-dependent |
legal_ot |
DECIMAL | Legal Holiday OT | Context-dependent |
reg_nd |
DECIMAL | Night Differential | Availability indicator |
special_rd |
DECIMAL | Special Rest Day | Availability indicator |
legal_rd |
DECIMAL | Legal Rest Day | Availability indicator |
special_hd |
DECIMAL | Special Holiday | Availability indicator |
legal_hd |
DECIMAL | Legal Holiday | Availability indicator |
pto_hr |
DECIMAL | PTO Hours Used | Leave integration |
KPI Formulas from Attendance:
Attendance Rate = (days_worked / scheduled_days) × 100
Punctuality Score = ((scheduled_days - days_late) / scheduled_days) × 100
Undertime Rate = (SUM(under) / SUM(schedule)) × 100 [lower = better]
Schedule Compliance = (SUM(worked) / SUM(schedule)) × 100
Overtime Ratio = (SUM(all_ot) / SUM(worked)) × 100 [context-dependent]
3. Task & Project Data
3.1 Tasks_model (ci_tasks)
File: application/models/Tasks_model.php (629 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
status_id |
INT | Task completion tracking | COUNT by status per user |
points |
INT | Task value/complexity | SUM completed points |
deadline |
DATE | On-time delivery | COUNT overdue vs total |
assigned_to |
INT | Direct assignment | Per-user filtering |
collaborators |
TEXT (CSV) | Team contribution | FIND_IN_SET matching |
start_date / deadline |
DATE | Duration analysis | DATEDIFF calculation |
milestone_id |
INT | Milestone delivery | GROUP BY milestone |
recurring |
INT | Recurring task compliance | Cycle completion tracking |
Critical Method — get_task_statistics() (Lines 452-475):
SELECT COUNT(tasks.id) AS total, task_status.id AS status_id,
task_status.key_name, task_status.title, task_status.color
FROM tasks
LEFT JOIN task_status ON task_status.id = tasks.status_id
WHERE tasks.deleted = 0 AND tasks.assigned_to = ?
GROUP BY tasks.status_id
Returns: {total, status_id, key_name, title, color} — Perfect for KPI dashboard pie charts and completion rates.
KPI Formulas from Tasks:
Task Completion Rate = (completed_tasks / total_assigned_tasks) × 100
Points Completion = (completed_points / total_assigned_points) × 100
On-Time Delivery = (tasks_completed_before_deadline / total_completed) × 100
Task Velocity = completed_tasks / period_days
Average Task Duration = SUM(DATEDIFF(completed_date, start_date)) / completed_count
3.2 Projects_model (ci_projects)
File: application/models/Projects_model.php (337 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
total_points |
Computed | Project scope | SUM of task points |
completed_points |
Computed | Project progress | SUM of completed task points |
status |
VARCHAR | Project delivery | COUNT by status |
deadline |
DATE | Project timeliness | Overdue detection |
Critical Computed Fields (Lines 12-105 in get_details()):
SUM(tasks.points) AS total_points,
SUM(IF(tasks.status_id = 3, tasks.points, 0)) AS completed_points
Critical Method — count_project_status() (Lines 107-140):
Returns {open: N, completed: N} per user via project_members join.
KPI Formulas from Projects:
Project Progress % = (completed_points / total_points) × 100
Project Delivery Rate = (completed_projects / total_projects) × 100
Project On-Time Rate = (projects_completed_by_deadline / total_completed) × 100
4. Ticket/Support Data
4.1 Tickets_model (ci_tickets)
File: application/models/Tickets_model.php (379 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
ticket_type_points |
INT (from ticket_types) | Resolution value | SUM per resolver |
ticket_type_duration |
INT (hours, from ticket_types) | SLA compliance | Compare actual vs expected |
status |
VARCHAR | Resolution tracking | COUNT by status |
assigned_to |
INT | Assignment tracking | Per-user filtering |
created_at |
DATETIME | Response time baseline | TIMESTAMPDIFF from assignment |
due_date / created_at + duration |
Computed | Overdue detection | Current time comparison |
Overdue Calculation Logic (from get_details()):
-- Overdue if: current time > due_date OR current time > (created_at + ticket_type_duration hours)
IF(tickets.due_date IS NOT NULL,
IF(NOW() > tickets.due_date, 1, 0),
IF(NOW() > DATE_ADD(tickets.created_at, INTERVAL ticket_types.duration HOUR), 1, 0)
) AS is_overdue
Available Aggregation Methods:
count_new_tickets()— Total new ticketsget_ticket_status_info()— Grouped by status with countscount_tickets()— Filtered countcount_member_tickets()— Per-member count
KPI Formulas from Tickets:
Ticket Resolution Rate = (resolved_tickets / assigned_tickets) × 100
Average Resolution Time = SUM(resolution_time) / resolved_count
SLA Compliance = (tickets_resolved_within_duration / total_resolved) × 100
Ticket Points Earned = SUM(ticket_type_points for resolved tickets)
Overdue Ticket Rate = (overdue_tickets / total_tickets) × 100 [lower = better]
First Response Time = AVG(TIMESTAMPDIFF(first_response, created_at))
5. Timesheet Data
5.1 Timesheets_model (ci_project_time)
File: application/models/Timesheets_model.php (311 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
start_time / end_time |
DATETIME | Billable hours tracking | TIMESTAMPDIFF sum |
hours |
DECIMAL | Manual hour entry | SUM per period |
task_id |
INT | Task-time allocation | GROUP BY task |
project_id |
INT | Project-time allocation | GROUP BY project |
user_id |
INT | Per-employee tracking | Primary filter |
Critical Method — get_summary_details() (Lines 100-185):
SUM(TIMESTAMPDIFF(SECOND, start_time, end_time)) + SUM(ROUND(hours * 60) * 60) AS total_duration
Supports group_by parameter with values: "member", "task", "project"
Critical Method — get_timesheet_statistics() (Lines 241-280):
Daily hours aggregation with timezone conversion support. Returns per-day totals for chart rendering.
KPI Formulas from Timesheets:
Billable Hours Ratio = (logged_hours / expected_hours) × 100
Utilization Rate = (productive_hours / total_available_hours) × 100
Time per Task = AVG(duration per task completion)
Time Logging Compliance = (days_with_timesheet / working_days) × 100
6. Disciplinary Data
6.1 Discipline_entries_model (ci_discipline_entries)
File: application/models/Discipline_entries_model.php (~155 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
category |
VARCHAR | Infraction type analysis | COUNT by category |
status |
VARCHAR | Open vs resolved cases | COUNT by status |
date_occurred |
DATE | Frequency tracking | COUNT per period |
user |
TEXT (CSV) | Involved employees | FIND_IN_SET matching |
Key Methods:
get_yearly_entries_count($user_id, $start_date, $end_date)— Counts entries in date range with optional status filtercount_open_cases_for_user($user_id)— Counts entries withstatus IN ('new', 'open')whereFIND_IN_SET(user_id, user)
KPI Formulas from Disciplinary:
Disciplinary Score = MAX_SCORE - (infraction_count × penalty_per_infraction)
Compliance Score = 100 - ((open_cases / max_expected) × 100)
Infraction Frequency = infraction_count / months_in_period
Note: This is a negative KPI — more infractions = lower score. The scoring should use an inverse scale.
7. Leave Data
7.1 Leave_applications_model (ci_leave_applications)
File: application/models/Leave_applications_model.php (308 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
status |
VARCHAR | Approval tracking | COUNT by status |
start_date / end_date |
DATE | Duration calculation | SUM days per type |
leave_type_id |
INT | Type analysis | GROUP BY type |
applicant_id |
INT | Per-employee filtering | Primary filter |
total_hours |
DECIMAL | Precise leave usage | SUM per period |
Available Filters: status, date range overlap, target_year, applicant_id, department_id
7.2 Leave_credits_model (ci_leave_credits)
File: application/models/Leave_credits_model.php (233 lines)
Critical Method — get_balance():
SUM(IF(action='debit', counts, 0)) - SUM(IF(action='credit', counts, 0)) AS balance
Supports target_year filtering.
Critical Method — get_overall():
Per-user, per-leave-type, per-action summary grouped by user_id, action, leave_type_id.
KPI Formulas from Leave:
Leave Utilization Rate = (leave_days_used / leave_credits_allocated) × 100
Unplanned Leave Rate = (emergency_leaves / total_leaves) × 100 [lower = better]
Leave Balance Health = leave_credit_balance / allocated_credits × 100
Absence Rate = (total_leave_days / working_days_in_period) × 100
8. Schedule Data
8.1 Schedule_model (ci_schedule)
File: application/models/Schedule_model.php (~100 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
sched_id (from job_info) |
INT | Employee's assigned schedule | Lookup |
schedule start/end |
TIME | Expected work hours | Duration calculation |
title |
VARCHAR | Schedule identification | Display |
Key Methods:
getUserSchedId($user_id)— Gets schedule assignment from team_member_job_infogetUserSchedObj($user_id)— Returns full schedule object
KPI Application: Schedule data provides the baseline for calculating:
- Schedule compliance (actual vs expected hours)
- Late arrival detection (in_time vs schedule start)
- Early departure detection (out_time vs schedule end)
9. Professional Development Data
9.1 Certifications_model (ci_certifications)
File: application/models/Certifications_model.php (~60 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
due_date_of_certification |
DATE | Active cert count | COUNT WHERE due_date >= CURRENT_DATE |
user_id |
INT | Per-employee tracking | Primary filter |
title |
VARCHAR | Certification type | GROUP BY type |
Key Method — get_total_certifications_of_user($user_id):
Counts active/valid certifications where due_date_of_certification >= CURRENT_DATE.
9.2 Skillsets_workforce_model (ci_skillsets_workforce)
File: application/models/Skillsets_workforce_model.php (110 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
skillsets_id |
TEXT (CSV) | Competency tracking | COUNT distinct skills |
user_id |
INT | Per-employee skills | Primary filter |
| Prefixed IDs | skillsets:X or jobfunction:Y |
Skill type distinction | Parse prefix |
Bidirectional Matching: FIND_IN_SET enables skillset→job_function and job_function→skillset lookups.
9.3 Skillsets_model (ci_skillsets)
File: application/models/Skillsets_model.php (100 lines)
get_skillsets_color($skillset_ids)— Color/title for given IDsget_skillset_and_job_function_color()— Parses prefixed IDs for both tables
KPI Formulas from Professional Development:
Certification Score = (active_certifications / target_certifications) × 100
Skill Breadth Score = (distinct_skills / department_avg_skills) × 100
Competency Match = (matched_skills / required_skills_for_role) × 100
Development Growth = (current_certs - previous_period_certs) / previous_period_certs × 100
10. Salary & Compensation Data
10.1 Salary_grades_model (ci_salary_grades)
File: application/models/Salary_grades_model.php (230 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
grade_level |
INT | Grade band identification | Lookup |
min_salary / max_salary |
DECIMAL | Band range | Reference |
total_steps |
INT | Step count per grade | Reference |
step_increment |
DECIMAL | Salary per step | Computation |
Critical Method — get_grade_matrix():
Returns all active grades with embedded employees array. Each employee's grade determined via latest approved salary_history record (MAX(effective_date) subquery).
Critical Method — compute_salary_for_step($grade_id, $step):
salary = min_salary + (step - 1) × step_increment (capped at max_salary)
10.2 Salary_history_model (ci_salary_history)
File: application/models/Salary_history_model.php (643 lines)
| Column/Method | Type | KPI Use | Aggregation |
|---|---|---|---|
monthly_salary |
DECIMAL | Current compensation | Latest approved rate |
salary_grade_id |
INT | Grade assignment | Current grade lookup |
salary_step |
INT | Current step | Step position |
effective_date |
DATE | Rate change tracking | Timeline analysis |
status |
VARCHAR | Approval state | Only use 'approved' records |
Key Methods for KPI Integration:
get_rate_for_date($user_id, $date)— Most recent approved rate as of a given dateget_rates_in_range()— All rates within a period (for pro-rating)has_rate_change_in_range()— Boolean check for mid-period changessync_to_job_info($user_id)— Syncs to team_member_job_infoget_users_salary_summary()— All active staff with LATEST approved salary via MAX(effective_date) subquery + salary_grade joinsget_timeline_data()— Full salary change timeline with prev_record comparison
KPI-Salary Integration Points:
Current Grade Position = salary_step / total_steps (0.0 to 1.0)
Grade Band Position = (monthly_salary - min_salary) / (max_salary - min_salary)
Steps Remaining = total_steps - salary_step
Next Step Salary = min_salary + (salary_step) × step_increment
Increase on Advancement = step_increment / monthly_salary × 100 (% increase)
11. Payslip Aggregate Data
11.1 Payslips_model (ci_payslips)
File: application/models/Payslips_model.php
| Method | Returns | KPI Use |
|---|---|---|
get_yearly_absent_total($user_id, $year) |
SUM(absent) | Absence tracking (hours) |
get_yearly_undertime_total($user_id, $year) |
SUM(under) | Undertime tracking (hours) |
These methods aggregate from approved payslips joined with payrolls for date filtering. They provide year-to-date absence and undertime totals that are authoritative (tied to payroll approval).
KPI Application:
Payroll Absence Rate = yearly_absent_total / (expected_hours_per_year) × 100
Payroll Undertime Rate = yearly_undertime_total / (expected_hours_per_year) × 100
12. Cross-Reference: Data Source to KPI Category Mapping
| KPI Category | Primary Source(s) | Secondary Source(s) |
|---|---|---|
| Attendance & Punctuality | attendance_metrics (worked, late, under) | payslips (absent, undertime totals), schedule |
| Task Performance | tasks (status, points, deadline) | timesheets (duration per task) |
| Project Delivery | projects (total/completed points) | tasks (per-project), project_members |
| Support Quality | tickets (status, points, duration) | — |
| Behavioral/Compliance | discipline_entries (count, status) | — |
| Leave Management | leave_applications (status, days), leave_credits (balance) | attendance (pto_hr) |
| Professional Development | certifications (active count), skillsets (competencies) | — |
| Time Management | timesheets (logged hours), attendance_metrics (duration) | tasks (duration) |
| Salary Position | salary_grades (grade/step), salary_history (rate, effective_date) | — |
13. Proposed New Data Points
While the existing system covers ~80% of KPI needs, some new data points would enhance the scoring:
| Proposed Column/Table | Target Table | Purpose | Priority |
|---|---|---|---|
quality_rating |
ci_tasks | Manager rating on completed tasks (1-5 scale) | Medium |
customer_feedback_score |
ci_tickets | Customer satisfaction on resolved tickets | Medium |
training_hours |
New: ci_training_log | Professional development hours tracking | Low |
peer_nominations |
New: ci_peer_recognition | Peer-to-peer recognition count | Low |
These are optional enhancements — the core KPI system can function entirely on existing data.
14. Data Freshness & Update Frequency
| Data Source | Update Frequency | Staleness Risk |
|---|---|---|
| Attendance metrics | Real-time (per clock action) | Very Low |
| Tasks | Real-time (per status change) | Very Low |
| Projects | Real-time (computed from tasks) | Low |
| Tickets | Real-time (per status change) | Very Low |
| Timesheets | Manual (user-logged) | Medium — may be backfilled |
| Discipline entries | Event-driven (per incident) | Low |
| Leave applications | Event-driven (per request) | Low |
| Leave credits | Event-driven (per debit/credit) | Low |
| Certifications | Manual (admin-entered) | Medium — may not be current |
| Skillsets | Manual (admin-entered) | Medium — may not be current |
| Salary data | Event-driven (per approved change) | Very Low |
| Payslip aggregates | Per payroll cycle (bi-monthly) | Low — tied to payroll calendar |
Recommendation: KPI scores should be calculated on-demand or scheduled nightly. Real-time calculation is not necessary — most source data changes within normal business cycles.