Help & Manual

Quick-start guides for each kind of user. Pick your role above.

Admin Guide

This guide is for people in the ADMIN role — system owners who manage users, KPI catalog, settings, and oversight.

What you'll do here

  • Provision users + roles (USER / MANAGEMENT / ADMIN / CUSTOMER)
  • Configure the KPI catalog (groups, rule types, KPI types, department-KPI mapping)
  • Manage countries, departments, holidays
  • Assign pending intake tickets
  • Configure global app settings (date format, ticket edit window)
  • Review the audit log

The Admin Dashboard

Admin, in the menu under your name at the top right, opens the Admin Dashboard: the platform at a glance. While intake tickets wait for someone to be assigned, an inbox with their count sits at the top right too; it opens Pending Tickets.

  • Four counts — countries, departments, staff (active people, customers counted apart) and the KPI types in use today (on for at least one department, out of all defined). Each opens its admin page.
  • A notice when intake tickets are waiting for someone to be assigned; it opens Pending Tickets.
  • Monthly average score — the organisation's score over the last six months: the plain mean of the countries' scores, as each appears on Performance.
  • Recent activity — the latest entries of the Audit Log; a ticket's entry opens its status page. View all opens the whole log.

Rebuild Reports recomputes the persisted reports (see Rebuilding reports below).

The left sidebar lists every admin area. The order is curated; click to navigate:

SectionWhat's there
CountriesCountry list + working-hours config (timezone, workday window, working days)
DivisionsOrg divisions departments roll up to (parallel to country). Optional; departments without one show as Unassigned in division reports.
DepartmentsDepartment records linked to a country and, optionally, a division
UsersEveryone who signs in: staff from HRIS (read-only, with their role in KPI and a lock), group mailboxes, service logins and customers
KPI GroupsTop-level KPI categories (e.g. Issue, Internal Control, Uptime)
Rule TypesThe formula behind each KPI Type (rr, acr, accuracy, submit, project, ic-*, uptime). Usually only admins of admins touch these.
KPI TypesConcrete metrics tracked. Each KPI Type picks a Rule Type, sets parameters (SLA minutes, weights, targets), and belongs to a KPI Group.
KPI ItemsRaw ticket data with import-from-Excel + manual editing.
Department KPIsWhich KPI Types are valid for which Departments.
Pending TicketsIntake tickets that arrived with no assigned user — assign or delete.
HolidaysPer-country holiday calendar + import-from-Nager-API.
General SettingsGlobal app settings (ticket edit window, date format).
Email TemplatesCustomise the subject + body of the transactional emails (live preview, reset-to-default).
Email LogHistory of every email the system has tried to send (filterable).
ModulesTurn whole feature modules (KPI / Workflow / Asset) on/off at runtime.
SearchWhether the header search may ask Vertex AI to understand a question, and the questions it could not answer.
Audit LogRead-only history of ticket lifecycle, approval workflow, laptop request and maintenance events, and of the organisation changes HRIS sends (people added or moved, departments, managers).
Data CleansingExport-then-delete old tickets / pending intake / audit logs / orphaned attachments past a cutoff.
Other KPI SettingsUptime unit configuration (and, historically, the global settings now on General Settings).

User management

Roles:

  • CUSTOMER — auto-created the first time someone signs in with Google. Can submit intake tickets and chat on their own tickets only. No internal pages.
  • USER — agent. Has a Department. Can self-log KPI tickets, handle assigned intake tickets, and follow them on their own My KPI.
  • MANAGEMENT — supervisors. See Performance and the Monthly report for the departments they manage or head, and there — like a department manager, never beyond — assign, reassign and delete tickets. Cannot log tickets of their own.
  • ADMIN — full admin access (sidebar + all settings).

Staff come from HRIS. HC adds a member of staff in HRIS, and they arrive here with a welcome email. Their name, mailbox, department, joining date and leaving date are kept in HRIS: change them there and the change arrives here. Click a person's pencil on Admin → Users to see their record from HRIS, read-only, with Open in HRIS. Below it are the two things this screen still decides:

  • Role in KPI — HRIS adds everybody as an Agent. Make someone Management or Admin here.
  • Can sign in — untick it to lock the account at once, e.g. before HC records the leaving in HRIS. A leaving date from HRIS switches the account off by itself, and the list then shows the person as Left.

The list's Status button does the same locking: Active or Locked, or Left for someone whose leaving HRIS recorded.

Staff without a mailbox (frontdesk staff, Value Designers) show as No mailbox. They sign in with Sign in with Employee ID, using the same employee ID and password as in HRIS. Their record here shows the Employee ID, read from HRIS. A forgotten password is reset in HRIS by HC or their manager, never here.

Add mailbox or login adds what HRIS doesn't keep: a group mailbox shared by a team (e.g. alluid@) or a service login for an app. Customers are never added here: they're created the first time they sign in.

Department assignment is required for an agent; MANAGEMENT and ADMIN can be left without one.

On a KPI that is not connected to HRIS (a standalone copy, or a local one with ORG_EDITING=unlocked), the full form comes back: Add New creates any user, and End date in the past switches the account off on save.

Delete removes the user and all their tickets — only do this in test environments.

Viewing KPI as someone else

To check what a person sees — a manager's My Team, a member's score, a customer's My Requests — click the eye on their row in Users. KPI opens on their home page as them: their Dashboard, My KPI, My Team and Performance, with their numbers and their access (an admin page shows them what it would show them).

  • It is read-only: nothing can be filed, edited or deleted while you view — a save answers Read-only while you view KPI as someone else.
  • An amber bar on every page says who you are viewing and until when; Stop viewing brings you back to Users as yourself. It also ends by itself after an hour, and when you sign out.
  • It is KPI only: HRIS, SDA and the portal still see you.
  • Each start and stop is in the Audit log under your name.

No need any more to move a test account into someone's department, or make it a manager, to see their data.


KPI catalog setup

Order matters when bootstrapping a new environment:

  1. Country → set timezone, workday start/end, working days of the week.
  2. Division (optional) → create the org divisions departments will roll up to. Skip if you only report by country.
  3. Department → links to a country; optionally assign a division.
  4. KPI Group → toggle "contributes to uptime" only for groups whose KPIs feed the Uptime calculation.
  5. Rule Type → these are pre-seeded; only edit if you understand the formula.
  6. KPI Type → pick a Rule Type, set parameters:
    • For rr: responseSlaMin, resolutionSlaMin, respWeight, resoWeight.
    • For rr-dynamic (Ad Hoc with an extendable, per-ticket resolution deadline): responseSlaMin, resolutionSlaWorkingDays (the default deadline in holiday-aware working days; the agent can raise it per ticket and extend it later), respWeight, resoWeight. Two differences from rr: the resolution target is a working-day deadline set on each ticket (not a fixed minute SLA), and a ticket is scored in the month it is resolved (closedAt), not the month it was requested — open tickets don't score until they close. Each deadline extension logs a reason and emails the requestor.
    • For submit: submitCutoffMin.
    • For accuracy: respAccTarget, dataAccTarget, respAccWeight, dataAccWeight.
    • For acr: six target percentages + six weights.
    • For ic-*: slaWorkingDays, targetDayOfWeek, minFindings (as relevant).
    • availableForIntake: true exposes the KPI Type on the public intake form.
    • ignoreWorkingDayFilter: true means weekend/holiday tickets count without the override.
  7. Department KPIs → assign each KPI Type to the Departments that should be able to log/select it. Effective From starts on the 1st of the current month. Mind it for an uptime system (a KPI type in a group that counts toward System Availability) and a project KPI: those are scored every month from that date even with no tickets — 100% uptime where no downtime was logged, 0% where no project was filed. Left blank, they reach back to the very first report month: Indonesia IT's systems read 100% for 2025, before anyone was in IT, until they were given Effective From 1 Jan 2026. Effective To retires an assignment the same way.
  8. Other KPI Settings → for Uptime KPI Types, configure unit counts per country.

Countries

Managed in HRIS. When KPI is connected to HRIS, as in production, Countries is read-only here: a country, its timezone and its working hours are changed in HRIS and arrive here. The banner's Open HRIS goes straight there. Each country's holidays stay KPI's own: see Holidays.

On a KPI not connected to HRIS, the Country form sets per-country defaults used in working-hour math:

  • Timezone (IANA name, e.g. Asia/Jakarta).
  • Workday Start / End (local time of day, e.g. 10:00-19:00).
  • Working Days as comma-separated ISO weekday numbers (1=Mon … 7=Sun). Default 1,2,3,4,5 (Mon-Fri).

These settings drive response time, resolution time, uptime windows, and ticket inclusion filters. Change carefully — reports recompute on the next dashboard view but consider the impact on historical scoring.


Divisions

Managed in HRIS. When KPI is connected to HRIS, as in production, Divisions is read-only here: divisions and their heads are set in HRIS and arrive here. The steps below are for a KPI that is not connected to HRIS.

Divisions are an organizational tier parallel to country — both are attributes a department carries, and reports can group departments either way. Use them to mirror your real org chart (e.g. Business Operations, Finance, IT & Business Analytics).

  • A division has a name and an optional abbreviation.
  • Assign a department to a division on the Departments form (the Division field is optional).
  • Set the division's Heads via the Heads button on the division row. A division can have one or more heads. Every head gets manager capabilities over all departments in the division — assign tickets, approve extensions, view performance — exactly like a department manager, but division-wide. (This is independent of the user's role; it works like designating a department manager.)
  • Departments with no division roll up under an Unassigned bucket in the division scorecard.
  • The division score is the average of its departments — the same roll-up the country score uses — so the two views always reconcile for a given month.

You can adopt divisions gradually: create them here, then assign departments at your own pace. Until a department is assigned, only its country reporting is affected (nothing breaks).

The structure you build here (divisions, heads, departments, managers, user assignments) is shown live to management on the Org Chart page (in the top bar) — it updates automatically as you make changes.


Departments

Managed in HRIS. When KPI is connected to HRIS, as in production, Departments is read-only here. HRIS sets each department's name, country, division and parent department, its managers, and who sits in it; the changes arrive here.

What stays in KPI:

  • Which KPI types a department is scored on, on Department KPIs.
  • Its uptime units, on Uptime Settings.

A sub-department (one with a parent) is scored inside its parent: ACR and VD count toward ALLU Indonesia.

On a KPI not connected to HRIS, departments and their managers are added and edited on this screen.


Holidays

The Holidays admin lets you:

  • Add/edit/delete holidays for any country.
  • Filter the list by country with the radio group.
  • Import public holidays from Nager.Date by picking a country + year and clicking Import. The country must have a 2-letter abbreviation (e.g. ID, US).

Holidays apply to tickets whose country matches.


Pending tickets

Intake tickets submitted without a specific user appear here.

  • Pick a user from the destination department's dropdown.
  • Click the green check to assign — the user gets an email and the ticket flips to On Progress.
  • Click the trash to discard (e.g. spam) — the ticket is permanently deleted.

Once assigned, the ticket lives on the agent's My KPI and disappears from this list.


Audit log

Path: Admin → Audit Log.

A read-only log of ticket lifecycle events. Filters: action, actor, date range. Columns: When, Who, Action, Entity, Details.

Events captured (v1):

  • TICKET_INTAKE_SUBMITTED — a customer (or signed-in user) submitted via intake.
  • TICKET_SELF_LOGGED — an agent created via /input.
  • TICKET_ASSIGNED — admin/manager assigned a pending ticket.
  • TICKET_REASSIGNED — a manager/admin moved an already-assigned ticket to a different teammate.
  • TICKET_UPDATED — agent edited a ticket (no status change).
  • TICKET_STATUS_CHANGED — agent moved status forward.
  • TICKET_DELETED — ticket removed (pending-tickets admin or the agent's My KPI).
  • DATA_CLEANSED — an admin ran a Data Cleansing purge (records cutoff + counts removed).

Logs are append-only; nothing here can be edited or deleted from the UI.


Email Templates

Path: Admin → System → Email Templates.

Customise the subject + body of the transactional emails (ticket assigned, closed, rejected, re-opened, deadline-extended, and the verification code) without touching code:

  • Pick a template; edit the Subject and Body (HTML). The branded header/footer is fixed (you only edit the message body).
  • Insert variables like {{kpiName}}, {{statusUrl}}, {{rejectionReason}} from the chips (or type them) — they're highlighted in the body and filled in at send time. Required variables (e.g. {{code}} on the verification email) can't be removed.
  • Format tidies the HTML indentation; the right/top preview renders with sample data live.
  • Save to apply; Reset to default drops your customisation and returns to the built-in template. Templates with no override use the built-in default.

Email Log

Path: Admin → System → Email Log.

A history of every transactional email the system has tried to send: recipient, subject, status (sent / failed, with the error), and time. Filter by status and search by recipient/subject. Shows the latest 200; narrow with the filters for older entries.

Path: Admin → System → Search.

The magnifier in the top bar searches everything in KPI: tickets (by words or number), people, departments, KPI types and groups, roles, the audit and email logs, pages and this manual. Each part shows only what the person searching could open anyway. An agent finds their own tickets and their department's people, a manager their departments, and an admin everything. Logs, KPI types and roles are found by admins only.

It also answers questions from KPI's own data, in English or Indonesian: my score, my open tickets, overdue tickets, unassigned tickets, who is below target, how is Business Analytics doing, Sandy score.

  • Understand questions with Vertex AI — off by default. When it is off, the search answers only the phrasings it already knows. When it is on, a question it does not recognise is sent to Vertex AI in the company's Google Cloud project to be classified. Only the typed text is sent, with every name the search recognised replaced by PERSON or DEPARTMENT. The answer is still worked out inside KPI.
  • Questions it could not answer — what people asked and got nothing for, most asked first, names replaced. Who asked is never recorded. A question leaves the list once it is answered. Use it to see what people look for; Clear removes one, or Clear all removes the lot.

Switching Vertex AI on or off is written to the audit log.

Data Cleansing

Path: Admin → System → Data Cleansing. Destructive — read carefully.

Permanently removes old data past a cutoff, after exporting a JSON backup. Choose how many months old, tick the data to remove, Preview (counts only, nothing deleted), then Export & Delete (a JSON backup downloads first):

  • Resolved KPI tickets — aged by resolution date (closedAt); cascade-removes their chat + extension requests and deletes their image attachments. Open tickets are never touched.
  • Pending / unassigned intake tickets — aged by submitted date.
  • Audit log entries — aged by created date.
  • Orphaned chat attachments (GCS) — image blobs whose ticket/message is already gone.

Minimum cutoff is 1 month; the run is itself audit-logged. Removing tickets refreshes KPI reports on next view.


Global settings

Other KPI Settings page has:

  • Ticket Edit Window (days) — USER-role accounts can only modify tickets dated within this window. ADMIN/MANAGEMENT always bypass.
  • Date Format — date-fns format pattern used everywhere in the app (table dates, ticket dates, email dates). Examples: dd/MM/yyyy, MM/dd/yyyy, yyyy-MM-dd.

Both fields save together when you click Save.

This page also hosts the Uptime Unit table — pairing each Uptime KPI Type with its country and unit count (number of units, e.g. number of stores).


Operational tasks

Backfilling closed tickets

If you have closed tickets pre-dating the response/resolution auto-tracking, run:

npx tsx scripts/backfill-intake-metrics.ts

It will fill in metrics.responseTimeMin, metrics.resolutionTimeMin, closedAt, and firstAgentReplyAt for closed tickets that are missing them, using createdAt, the first agent chat message, and closedAt ?? updatedAt as anchors. Then it rebuilds the KPI reports.

Rebuilding reports

The persisted KPI report tables (DashboardSummary, KpiMonthlySummary) rebuild lazily: a ticket change marks the reports dirty, and the next time someone opens the dashboard / Monthly Report, the system recomputes them — but only if tickets actually changed since the last rebuild (otherwise the view is instant). So daily ticket actions (submit, chat, close, reassign…) stay fast; the recompute cost lands on the next report view. Admin-config saves (KPI types, holidays, etc.) and bulk imports still rebuild in place.

If something looks stale, just open the dashboard (it self-heals on view) or force a rebuild:

POST /api/admin/rebuild-reports

Importing KPI items from Excel

The KPI Items admin has an Import button that accepts an Excel file. Preview the rows first, then run. The preview shows: which rows will create, update, skip, or error. Errors usually mean unmatched user / country / department / KPI Type names — make sure those exist before importing.


Frequently asked

A user can sign in but doesn't have admin access. Check Users page — they're probably CUSTOMER (auto-provisioned). Change their role to ADMIN.

Country deletion fails with "Cannot delete country with existing department associations". Move or delete the dependent Departments first.

Holiday import says "Country has no abbreviation". Edit the Country and set a 2-letter abbreviation. Nager.Date uses ISO country codes.

The audit log has no entries before today. Audit logging started recently; pre-existing tickets aren't retroactively logged. Going forward, every ticket action is captured.

An intake ticket appears stuck in "Pending Tickets" forever. Assign it manually here. Auto-assignment only happens when the customer picked a specific user at submission.

Pick a role: Customer — Submit a ticket and chat with the agent. · Agent — Handle tickets, self-log activity, close tickets. · Management — Read dashboards and monthly reports. · Admin — Manage users, KPIs, settings, and audit history. · Developer — Public intake API reference for external integrations.

My Profile