{title}
{portal.toUpperCase()} portal · Asia/Kolkata
This auth user needs a profile and role.
Attendance intelligence, gate control, leave management, visitor tracking, and emergency readiness — unified.
{err}
}{portal.toUpperCase()} portal · Asia/Kolkata
{error.message||String(error)}
Run SQL 26 first.
Deny by default · role + scope permissions · HR view-as audited · mail dormant
| Employee | Org | Login | Status | Scopes | Actions |
|---|---|---|---|---|---|
| {r.employee_code} {r.full_name} {r.official_email||'No official email'} | {r.department_code||'—'} {r.site_code||'Site?'} Mgr: {r.reporting_manager_name||'—'} | {r.login_id||'Not generated'} {r.username||''} | {r.access_enabled?'Access enabled':'Access disabled'} | SelfManagerReporteesDeptSiteHRGuard |
Select an employee from Provisioning first.
:<>{selected.full_name} · {selected.employee_code}
>}| Permission | Group | Scope | Sensitive |
|---|---|---|---|
| {p.permission_code} {p.description} | {p.permission_group} | {p.default_scope_type} | {p.is_sensitive?'Yes':'No'} |
Use this to catch wrong employee context, exited users with access, broad manager/HR/guard access, and missing self-view.
| Employee | Gaps |
|---|---|
| {g.employee_code} {g.full_name} | {(g.access_gaps||[]).map(x=>{x})} |
| Notice | Version | Status | Effective |
|---|---|---|---|
| {p.notice_title} {p.notice_code} | {p.version_no} | {fmtDate(p.effective_from)} |
| Employee | Notice | Status |
|---|---|---|
| {a.employee_code} {a.full_name} | {a.notice_title} {a.version_no} | Pending |
This is not impersonation. HR remains HR. A reason is required and each session is audited.
Select an employee from Provisioning and click View As.
{selected&&}| Target | Reason | Status | Started |
|---|---|---|---|
| {v.target_employee_id} | {v.reason} | {fmtDateTime(v.started_at)} |
| When | Action | Target | Reason |
|---|---|---|---|
| {fmtDateTime(a.created_at)} | {a.action_type} {a.action_summary} | {a.target_employee_id||a.target_user_id||'—'} | {a.reason||'—'} |
{JSON.stringify(data.ctx,null,2)}{error.message||String(error)}
{data.ctx?.access_block_reason||'Employee profile not linked'}
No fallback employee context is used. Contact HR to link your employee profile.
{ctx.full_name} · {ctx.employee_code}
Portal status: {ctx.portal_status} · Access enabled: {String(ctx.access_enabled)}
Privacy acknowledgement pending.
>:No pending privacy acknowledgement.
} {notice&&{notice.notice_text}
{error}
| Employee | Type | Date | Requested |
|---|---|---|---|
| {a.employee_code} — {a.full_name} | {a.request_type} | {a.work_date} | {a.requested_in_time?timeOnly(a.requested_in_time):""} {a.requested_out_time?timeOnly(a.requested_out_time):""} |
| Employee | Request | Work Date | Requested Time | Reason | Action |
|---|---|---|---|---|---|
| {r.employee_code} — {r.full_name} {r.department_name||""} | {r.request_type} | {r.work_date} | {r.requested_in_time?`IN ${timeOnly(r.requested_in_time)}`:""} {r.requested_out_time?`OUT ${timeOnly(r.requested_out_time)}`:""} | {r.reason_text} |
| Employee | Date | Status | Current Reason | Resolve |
|---|---|---|---|---|
| {r.employee?.employee_code} — {r.employee?.full_name} | {r.absence_date} | {r.status} | {r.remarks} | {r.status==="unresolved"?:"—"} |
{v.organization||"—"} · {v.phone||"—"}
| Employee | Role | Site | Dept |
|---|---|---|---|
| {r.employee_code} — {r.full_name} | {r.emergency_role} | {r.site_code} | {r.department_name} |
{error}
| Employee | Dept | Site | First IN | Last OUT | Inside | Outside / Free | Break | Exits | Flags |
|---|---|---|---|---|---|---|---|---|---|
| {r.employee_code} — {r.full_name} | {r.department_name||"—"} | {r.site_code||"—"} | {timeOnly(r.first_in)} | {timeOnly(r.last_out)} | {r.total_inside_hhmm} | {r.total_outside_hhmm} | {r.total_break_hhmm} | {r.exit_count} | {r.missing_final_out?Missing OUT:r.currently_inside_as_of_last_event?Inside:"—"} |
| Time | Employee | Event | Reason | Source | Site |
|---|---|---|---|---|---|
| {fmt(e.event_time)} | {e.employee?.employee_code} — {e.employee?.full_name} | {String(e.event_type)} | {e.reason_code||e.reason_text||"—"} | {String(e.source)} | {e.site?.site_code||"—"} |
| Time | Report | Format | Rows | File |
|---|---|---|---|---|
| {fmt(x.exported_at)} | {x.report_type} | {x.export_format} | {x.row_count} | {x.file_name} |
{error}
{sec.desc}
| {humanLabel(f)} | )}{active==="orgs"&&Path | }Actions |
|---|---|---|
| {f==="org_unit_type"?{typeBadgeLabel(valueFor(row,f))}:String(valueFor(row,f)??"")} | )} {active==="orgs"&&{row.pathLabel} | }{active==="orgs"&&} |
{String(this.state.error?.message||this.state.error)}
The data route is working. This is a frontend render issue. Use v1.5.2 patch and refresh.
{error}
Run SQL 23 first, then hard refresh.
Design your organization before changing your organization.
{loadWarnings.length>0&&Load warning: {loadWarnings[0]}
}Roots: {derivedRootCount} · Main branch: {mainRoot?countDescendants(mainRoot)+1:0} positions
{rootsRanked.map(r=>)}Click a card to see position details.
:<>| Position | Occupant | Status | Parent | Org Unit | Site | Band | Grade | Actions |
|---|---|---|---|---|---|---|---|---|
| {n.position_title} {n.position_code} | {n.full_name||"—"} | {n.position_status} | {n.parent_position_title||"—"} | {n.org_unit_name||"—"} | {n.site_code||"—"} | {n.band||"—"} | {n.grade||"—"} |
| Position | Status | Criticality | Hiring | Target DOJ | Org Unit | Site |
|---|---|---|---|---|---|---|
| {n.position_title} {n.position_code} | {n.position_status} | {n.criticality} | {n.hiring_status||"—"} | {n.target_joining_date||"—"} | {n.org_unit_name||"—"} | {n.site_code||"—"} |
| Position | Employee | Gaps |
|---|---|---|
| {g.position_title} {g.position_code} | {g.full_name||"—"} | {(g.gaps||[]).map(x=>{x})} |
| Version | Status | Purpose | Design Principle | Created |
|---|---|---|---|---|
| {v.version_name} {v.version_code} | {v.status} | {v.purpose||"—"} | {v.design_principle||"—"} | {new Date(v.created_at).toLocaleString()} |
Use these for leadership reviews and PowerPoint/SmartArt creation.
{makeHierarchyText(view==="people"?"people":"position")}
Use this if the module appears blank or counts look wrong.
{JSON.stringify({activeVersionId,loadWarnings,summary,orgMode,derivedRootCount,mainRoot:mainRoot&&{position:mainRoot.position_title,code:mainRoot.position_code,descendants:countDescendants(mainRoot)},orphanRootCount:orphanRoots.length,edgeSample:edges.slice(0,3),rootSample:(childMap.ROOT||[]).slice(0,8).map(n=>({position:n.position_title,code:n.position_code,id:n.position_id,descendants:countDescendants(n)}))},null,2)}
{error}
Run SQL 22 first.
Manage structure, reporting relationships and employee org mapping from one module.
{loadWarnings.length>0&&Load warning: {loadWarnings[0]}
}{nodes.length===0&&No visible org nodes. Run SQL 22D view visibility fix, then refresh.
}| Code | Name | Designation | Org Unit | Manager | Functional Head | HR Partner | Quality | Action |
|---|---|---|---|---|---|---|---|---|
| {n.employee_code} | {n.full_name} | {n.designation_name||"—"} | {n.org_unit_name||"—"} | {n.reporting_manager_name||"—"} | {n.functional_head_name||"—"} | {n.hr_partner_name||"—"} | {n.mapping_quality} |
| Code | Name | Gaps | Action |
|---|---|---|---|
| {g.employee_code} | {g.full_name} | {(g.gaps||[]).map(x=>{x})} |
Changes here update org assignment history and helper fields in Employee Master.
| When | Change | Employee | Field | Old | New | Reason |
|---|---|---|---|---|---|---|
| {new Date(l.created_at).toLocaleString()} | {l.change_type} | {nodes.find(n=>n.employee_id===l.employee_id)?.full_name||l.employee_id} | {l.field_name} | {l.old_value} | {l.new_value} | {l.reason} |
Search, verify, punch, track visitors and inter-site movement from one screen.
E-Code {selected.employee_code}{selectedPresence ? <> · Inside {runTime(selectedPresence.last_event_time)}> : selectedTransit ? <> · In transit {minutesToRunTime(selectedTransit.running_transit_minutes)}> : null}
{selectedState.message}
{error}
| {h} | )}|||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| {e.employee_code} | {e.full_name} | {statusLabel(e.status)} | {e.site_code||"—"} | {e.department_name||e.department_code||"—"} | {e.sub_department_code||"—"} | {e.team_cell_code||"—"} | {e.designation_name||"—"} | {e.band||"—"} | {e.grade||"—"} | {e.reporting_manager_code||"—"} | Contact Access Emergency |
| {humanLabel(k)} | )}
|---|
| {String(r[k]??"")} | )}
| Row | Employee Code | Validation | Commit | Messages | Photo Action | Import Action |
|---|---|---|---|---|---|---|
| {r.row_number} | {r.employee_code} | {r.validation_status} | {r.commit_status||"not_committed"} | {r.commit_message||((r.validation_messages||[]).join("; ")||"Ready")} | {r.row_payload?.photo_action||"KEEP"} | {r.import_action} |
{error.message||String(error)}
Frontend-managed identity linking. Link each login to an employee profile, then assign portal access and roles. No manual SQL should be needed for normal HR administration.
These accounts have roles but no employee context. They will show “Employee profile not linked” until linked here.
| User | Linked Employee | Status | Portal | Roles | Suggestion | |
|---|---|---|---|---|---|---|
| {u.username||u.login_identifier} {u.login_identifier||u.auth_user_id} | {u.employee?`${u.employee.employee_code} — ${u.employee.full_name}`:Not linked} | {(u.portal_access||[]).map(x=>{x})} | {(u.roles||[]).map(x=>{x})} | {!u.linked_employee_id && sug?{sug.employee_code} · {sug.full_name}:—} |
Select a user to link employee and assign roles.
:<>{selected.username||selected.login_identifier}
{selected.auth_user_id||"No auth user id"}
{msg}
}This is the proper operational path. SQL should only be for one-time schema/RPC installation or diagnostics.
>}{error.message||String(error)}
Lifecycle now uses Employee Master fallback, but core views may still require backend SQL.
| toggleSort('event_date')}>Date | toggleSort('event_type')}>Event | toggleSort('full_name')}>Employee | toggleSort('department_code')}>Department | Status | Source |
|---|---|---|---|---|---|
| {fmtDate(e.event_date)} | {eventTypeNice(e.event_type)} | {e.employee_code} · {e.full_name} | {e.department_code||'—'} | {e._source} |
| Employee | Gaps |
|---|---|
| {g.employee_code} · {g.full_name} | {(g.gaps||[]).map(x=>{x})} |
{error}
Run SQL 25 first to create the v_confirmation_tracker view.
{msg}
} {view==='department'&&| toggleSort('full_name')}>Employee | toggleSort('date_of_joining')}>DOJ | toggleSort('standard_probation_end_date')}>Standard End | toggleSort('current_confirmation_due_date')}>Current Due | toggleSort('actual_confirmation_date')}>Actual | toggleSort('tracker_bucket')}>Status | toggleSort('reporting_manager_name')}>Manager | Actions |
|---|---|---|---|---|---|---|---|
{r.full_name} {r.employee_code} · {r._department||''} | {fmtDate(r.date_of_joining)} | {fmtDate(r.standard_probation_end_date)} | {fmtDate(r.current_confirmation_due_date)} | {fmtDate(r.actual_confirmation_date)} | {r.confirmation_status} | {r.reporting_manager_name||—} |
{error}
Active on-roll employees only. Birthdays, anniversaries and confirmation dues are calculated live from Employee Master, with backend events de-duplicated.
{data.viewError&&Backend event view warning: {data.viewError}
}{rohan&&Rohan check: DB DOB = {rohanDob?fmtDate(rohanDob):'blank in employees table'} · Next birthday = {rohanBday?fmtDate(rohanBday):'not readable'}
}| toggleSort('event_date')}>Date | toggleSort('event_type')}>Type | toggleSort('full_name')}>Employee | Detail | toggleSort('department_code')}>Department | Urgency | Source |
|---|---|---|---|---|---|---|
| {fmtDate(e.event_date)} | {eventTypeNice(e.event_type)} | {e.employee_code} · {e.full_name} | {e.event_type==='birthday'&&e.age_turning?`Turning ${e.age_turning}`:e.event_type==='work_anniversary'&&e.years_completed?`${e.years_completed} years`:e.event_title||'—'} | {e.department_code||'—'} | {e._urgency} | {e._source} |
{e.employee_code} · {e.full_name}
{e.department_code||'—'} · {e.site_code||'—'}{e.event_type==='birthday'&&e.age_turning?`Turning ${e.age_turning}`:e.event_type==='work_anniversary'&&e.years_completed?`${e.years_completed} years`:e._urgency}{error}
Run SQL 25 first.
Emails are prepared as drafts/ready items only. Actual sending is disabled until a backend mail sender is configured.
| When | Channel | Status | Employee | Recipient | Subject | Mail Enabled? |
|---|---|---|---|---|---|---|
| {fmtDate(n.scheduled_for)} | {n.channel} | {n.employee_name} | {n.recipient_employee_name||n.recipient_email||n.recipient_role} | {n.subject_rendered} | {String(n.is_mail_enabled)} |
| Rule | Event | Recipient | Channel | |
|---|---|---|---|---|
| {r.rule_code} {r.rule_name} | {r.event_type} | {r.recipient_role} | {r.channel} |
{error}
One place for team, org visibility, approvals, confirmations and interview tasks.
{data.warnings?.length>0&&Some manager views are not installed yet: {data.warnings.join(" | ")}
}| Date | Action | Employee | Manager | Status |
|---|---|---|---|---|
| {fmtDate(a.action_date||a.due_date||a.created_at)} | {a.title||humanLabel(a.action_type)} {humanLabel(a.action_type||a.request_type||"action")} | {a.employee_code||"—"} · {a.full_name||a.employee_name||"—"} | {a.manager_name||"—"} |
| When | MRF | Role | Candidate | Status |
|---|---|---|---|---|
| {fmtDate(i.scheduled_at)} | {i.mrf_reference_no||"—"} | {i.role_title||"—"} | {i.candidate_name||"—"} |
Next build will save this to interview_assessments and route to HR Admin for offer workflow.
{error}
{d.full_name} · {d.employee_code}
{d.designation_name||'Designation not mapped'} · {d.department_code||'Department not mapped'} · {d.site_code||'Site not mapped'}
Confirmation:
Due date: {fmtDate(d.current_confirmation_due_date)}
{error}
{b.explanation_text}
| Type | Dates | Days | Status |
|---|---|---|---|
| {a.leave_types?.leave_code||a.leave_type_id} | {fmtDate(a.start_date)} to {fmtDate(a.end_date)} | {a.calculated_debit_days||a.requested_days} |
{error}
{error}
| Date | First IN | Last OUT | Inside | Status | Regularization |
|---|---|---|---|---|---|
| {fmtDate(r.work_date)} | {r.first_in?new Date(r.first_in).toLocaleTimeString(): '—'} | {r.last_out?new Date(r.last_out).toLocaleTimeString(): '—'} | {r.total_inside_minutes||0} min | {r.raw_status||'—'} |
{error}
| When | Channel | Status | Subject |
|---|---|---|---|
| {fmtDate(n.scheduled_for)} | {n.channel} | {n.subject_rendered||n.body_rendered} |
{error}
{error}
| Type | From | To | Days | Submitted | Status |
|---|---|---|---|---|---|
| {a.leave_types?.leave_code||'—'} · {a.leave_types?.leave_name||'—'} | {fmtDate(a.start_date)} | {fmtDate(a.end_date)} | {a.calculated_debit_days||a.requested_days||'—'} | {fmtDate(a.submitted_at)} |
| Date | Type | Requested Time | Reason | Status |
|---|---|---|---|---|
| {fmtDate(r.work_date)} | {r.request_type} | {r.requested_in_time?`IN ${timeOnly(r.requested_in_time)}`:''} {r.requested_out_time?`OUT ${timeOnly(r.requested_out_time)}`:''} | {r.reason_text} |