KCH Performance Review
Covers: Executive Summary · Budget Achievement · Customer Analysis · Components · Labour & Efficiency · Data & Notes
Devices: Windows / Mac PC, iPhone / iPad (iOS), Android phones and tablets
Prepared for: Kian Chue Hwa (Industries) Pte Ltd — Management, Workshop and Parts personnel
Version: 1.1 · 19 September 2026 (security update)
Screens in this guide use generated sample data. Figures shown are examples only, not company results. This page contains no code and cannot contact any address.
1. About the app
The KCH Performance Review app turns five Excel exports into an interactive performance report for the workshop and parts business: revenue, gross profit (GP), margin, budget achievement, customers, components produced, and technician utilization, efficiency and contribution.
1.1 Who it is for
| Audience | Typical questions answered |
|---|---|
| Management |
|
| Workshop supervisors |
|
| Technicians |
|
1.2 How it works
1.3 Key principles
Private by design: the Excel files are read inside your browser. The app contains no company data and sends nothing to any other server. With Microsoft 365 sign-in, data goes only from SharePoint to your device.
Protects itself: a security rule on the very first line of the page lets only the approved code run and blocks it from sending anything to other addresses. If unknown code is found, a red warning appears and loading files is switched off (section 8).
No installation needed: it is a web page. On phones it can be added to the home screen and then behaves like an app.
Same numbers everywhere: every page uses the same filters and the same definitions (section 7).
Latest month by default: the report opens on the most recent month that has invoices.
2. The app package
The delivered folder KCH_Performance_Review_App contains everything needed to run the app on PCs and mobile devices.
| Folder / file | What it is | Who uses it |
|---|---|---|
| web/index.html | The app (mobile-ready web app with Microsoft 365 sign-in). Its settings block near the top holds the tenant ID, client ID and SharePoint folder link | IT hosts this folder and fills in the settings once |
| web/manifest.webmanifest, web/sw.js, web/icons/ | Home-screen install, app icon and offline start for Android and iOS | Hosted with the app |
| web/web.config, web/staticwebapp.config.json | Web server settings (IIS or Azure) that also send the security rule from the server | IT |
| web/guide.html | This guide as a web page, opened from the app | Everyone |
| standalone/Performance_Review.html | Single-file version for PCs; open by double-clicking. Cannot contact any address | Anyone, today |
| standalone/Performance_Review_M365.html | Single file with Microsoft 365 sign-in, for hosts that take one file only | IT |
| SHA256SUMS.txt | Fingerprints of every app file, to check a hosted copy has not been changed | IT |
| docs/KCH_Performance_Review_Guide .html / .pdf / .docx | This guide | Everyone |
| docs/IT_Setup_Microsoft365.md | Step-by-step hosting and sign-in set-up | IT |
| docs/infographics/ | The infographics in this guide as images (for slides and notices) | Everyone |
| source/ | Source code and build script for future changes | Developer |
2.1 Choose how to open it
2.2 Quick start on a PC (standalone file)
Sync the SharePoint Data folder: open it in SharePoint and click Sync. It then appears in File Explorer under the company name.
Double-click standalone/Performance_Review.html. It opens in Edge or Chrome.
Click Choose files…, go to the synced Data folder and select all five Excel files (Ctrl+A).
Check that the line under the buttons says Security check passed (green), and that each file shows a green tick. Then click Open report.
Keep "Remember these files on this device" ticked. Next time, click Open saved data.
3. Using the app on iPhone and Android
The web/ folder is a Progressive Web App (PWA). Once IT hosts it on a company HTTPS address, it can be installed from the browser on iOS and Android. It gets its own KCH icon, opens full-screen, and starts even without a signal (using the last saved data).
3.1 iPhone / iPad
Open the company report address in Safari. Other iOS browsers cannot install web apps on older iOS versions.
Tap the Share button (square with an arrow), scroll down and tap Add to Home Screen, then Add.
Open KCH Review from the home screen and tap Sign in with Microsoft 365. The latest files load by themselves.
Before sign-in is set up: tap Choose files → Browse → OneDrive → Shared libraries → the Data folder, select the five files, then Open report.
3.2 Android
Open the company report address in Chrome.
Tap the ⋮ menu → Install app (on some phones: Add to Home screen) → Install.
Open KCH Review from the app drawer or home screen and sign in with Microsoft 365.
Before sign-in is set up: tap Choose files, open the ☰ menu in the file picker, choose OneDrive → Shared libraries → Data folder, and select the five files.
3.3 Working on a small screen
Filters: tap the blue Filters tab on the left edge. The filter side bar slides in over the report. Tap outside it, or ‹, to close it.
Pages: swipe the tab bar sideways to reach Components, Labour & Efficiency and Data & Notes.
Charts: tap a bar or point for its exact values. Turn the phone sideways for wider charts.
Tables: wide tables scroll sideways inside their frame. The first column stays in place.
Refresh: the ↻ Refresh button at the top reloads the newest SharePoint files.
4. Loading data
4.1 The five files
| File | Needed? | Used for |
|---|---|---|
| Invoice Margin | Required | Revenue, GP, margin, customers, departments (by PIC), budget comparison, contribution |
| Job Route Summary List | Recommended | Components, employee units, efficiency, contribution, Employee filter |
| Budget FY26 (C) | Recommended | Budget comparisons and the Budget Achievement page |
| Available Hours | Recommended | Utilization (normal hours) |
| OvertimeTBL | Recommended | Utilization (OT 1.5 and OT 2.0 hours) |
Files are recognised by their column headers, not their names, so renamed files still work. Title rows above the header row (company name, listing period, printed date) are skipped automatically. Totals rows without an invoice date are ignored.
4.2 Three ways to load
| Method | How | When to use |
|---|---|---|
| Choose files | Pick or drag the five files from the synced SharePoint folder (PC) or the OneDrive app (phone) | Always available |
| Open saved data | Opens the last files remembered on this device (IndexedDB, this browser only) | Quick re-opening, including offline |
| Sign in with Microsoft 365 | Company web app only: loads the latest files from the SharePoint Data folder; ↻ Refresh reloads them | Once IT has set up sign-in |
Removing saved data: Data & Notes → Forget data saved on this device. Untick "Remember these files on this device" on the load screen to stop saving.
4.3 Checking the data
The Data & Notes page lists every file loaded and runs data-quality checks, for example: rows skipped, credit notes netted, foreign-currency invoices, PICs not mapped to a department, Workshop invoices without a job route, and customers with more than one Cust ID.
5. Filters
All filters sit in the filter side bar. On a PC it is pinned on the left; click « or the Filters tab to slide it away. On phones it slides in when you tap the Filters tab. The "Showing" strip at the top of every page summarises the current selection.
| Filter | Options | Notes |
|---|---|---|
| Fiscal year | FY25, FY26 … | FY runs 1 April – 31 March and is named by its start year: FY26 = Apr 2026 – Mar 2027. |
| Fiscal months | Apr … Mar; Latest · YTD · Full year; Q1–Q4; H1, H2 | Default: Latest (the most recent month with invoices). Dashed months have no invoice data yet. |
| Department | All · Parts · Workshop · Other | From the invoice PIC: Jane Teng Neng Li = Parts, Workshop Team = Workshop, any other PIC = Other (editable in Data & Notes). |
| Customer | Multi-select with search | Names exactly as in Invoice Margin. Budget comparisons are hidden while a customer is selected. |
| Employee | Multi-select with search | Keeps invoices whose SO Num has job route work by the selected employees. |
Reset returns to the latest month of the latest fiscal year, all departments, all customers and all employees.
6. The report pages
Every page follows the same pattern: headline cards at the top, charts in the middle and detailed tables at the bottom. Hover over (or tap) any chart for exact values. Tables with Export CSV can be downloaded (PC and company web app).
6.1 Executive Summary
Headline cards: Revenue and GP (S$, 2 decimals) against budget and the same months of the prior FY; GP margin against target; activity (invoices, customers, credit notes).
Revenue / GP by month: the fiscal year to date, with faded bars for months outside your selection, prior FY and budget lines.
GP margin by month: Parts and Workshop against their targets (20% / 40%).
Revenue by department, Rolling 12 months, Monthly table, Department summary and Best months (highest revenue, GP and margin month, this FY and overall).
6.2 Budget Achievement
% of annual budget achieved: YTD actual ÷ total annual budget for Revenue and GP. The black tick shows where you should be by now (budget to date ÷ annual budget).
Status: On pace ✓ (at or above expected), Slightly behind ▼ (within 90% of expected), Behind ✕.
Margin: YTD GP% ÷ annual budget GP%.
Cumulative actual vs budget, Progress towards annual budget, by-department and monthly progress tables.
6.3 Customer Analysis
Customers chart: SBS Transit, SMRT, Tower Transit, Go-Ahead, ZF Asia and Others, with revenue and GP on the bars. Tap a bar to filter the report to that group.
Revenue / GP change by customer: Increase table sorted by % (highest first; new customers at the top) and Reduction table sorted by % (largest drop first). Compare with the previous month or the same period last FY, by revenue or by GP.
Revenue vs GP margin scatter, Revenue concentration (Pareto), Needs attention (loss-making or below target), All customers table.
6.4 Components
Units by component: grouped (Ecolife Transmission, ASTronic Transmission, Others, and single components). Tap a group to see its components. Compared with the previous month, with totals on the bars.
Units by employee: efficiency-weighted units (section 7.3), current against previous month.
Units by month, Component table, Employee table.
6.5 Labour & Efficiency
Utilization: by employee and by month, with the 85% target line and a table of normal hours, OT 1.5, OT 2.0, total available and Act hours.
Efficiency per SO and per Seq Desc: items below 95%, lowest first ("Show all" to see every item).
Contribution by employee: each SO’s revenue and GP shared by Act Hrs, with revenue and GP per Act hour. Tap an employee to see their SOs.
6.6 Data & Notes
Data loaded and data-quality checks.
Department mapping (by PIC): change which PIC counts as Parts, Workshop or Other; saved on the device.
GP% targets: Parts and Workshop targets used for the flags.
Security: the result of the page’s security check (green = passed) and a link to this guide.
Definitions of every measure, and Forget data saved on this device.
7. How the numbers are calculated
7.1 Revenue, GP and departments
| Measure | Rule |
|---|---|
| Revenue | Invoice Amt + Charges from the "Amount in SGD" columns of Invoice Margin. GST is excluded. Credit notes (negative amounts) reduce revenue. |
| Gross profit (GP) | The GP column of Invoice Margin. |
| GP margin | GP ÷ Revenue. Target: Parts 20%, Workshop 40%; weighted by revenue when both are shown. |
| Department | From PIC: Jane Teng Neng Li = Parts; Workshop Team = Workshop; others = Other. |
| Customer | Grouped by name exactly as written in Invoice Margin (case and extra spaces ignored). |
| Prior FY | Same fiscal months one year earlier, same filters. |
| Budget (Executive Summary) | Monthly budget by department for the selected months; hidden when a Customer or Employee filter is on. |
| Budget achievement | YTD actual (April to the last selected month) ÷ total annual budget (all 12 months). |
7.2 Components
| Measure | Rule |
|---|---|
| Unit | One service order (SO No) per Job Desc in the Job Route Summary List, counted only when the SO Num also appears in Invoice Margin. |
| Month | The month of the SO’s first invoice. |
| Groups | Ecolife Angle Drive + Ecolife Co-Axial = Ecolife Transmission; ASTronic Mid + AS Lite + ASTronic / TC Tronic / HD = ASTronic Transmission; Schindler Lifts + Transmission Actuator = Others; all other Job Descs stand alone. |
| Comparison | Previous month (or the same number of months before a multi-month selection). |
7.3 Labour measures
| Measure | Rule |
|---|---|
| Employee units | min(1, Exp ÷ Act) per employee per component. Employees sharing a Seq are pooled: pool units = min(1, Exp ÷ total Act), split by each person’s Act Hrs. Transmission Actuator × 0.25. External 1 / External 2 are not shown. |
| Utilization | Act Hrs ÷ (Normal Hours + OT 1.5 hrs + OT 2.0 hrs), by job route Start Date month. Target ≥ 85%. Sng Beng Huat is not included. |
| Efficiency per SO | Σ Exp Hrs ÷ Σ Act Hrs over all Seq lines of the SO. A Seq shared by several employees counts its Exp Hrs once. |
| Efficiency per Seq Desc | The Seq’s Exp Hrs ÷ the Act Hrs of everyone on that Seq, per SO. Listed below 95%. |
| Contribution | Employee Act Hrs ÷ SO total Act Hrs × SO revenue (excl GST) and × SO GP. |
8. Security and tamper protection
The app is built so that company files cannot leave your device through the page, and so that you can see straight away if a host or anyone else has changed the page.
8.1 The security rule on line 1
The very first line of every page file holds its security rule (a Content-Security-Policy). The browser reads it before anything else and enforces it for the whole visit:
Only approved code runs. Each block of code in the page is identified by its SHA-256 fingerprint. Code that is added or edited has a different fingerprint, and the browser refuses to run it.
Only listed addresses can be contacted. The page cannot send or fetch data anywhere else, including through images, fonts, frames or forms.
Nothing else may be embedded: no plug-ins, no other web pages inside the app, and no change of the page’s base address.
| Version | Addresses the page may contact |
|---|---|
| standalone/Performance_Review.html | None at all. The page cannot send anything anywhere. |
| standalone/Performance_Review_M365.html | login.microsoftonline.com (sign-in), graph.microsoft.com (folder list), kiananncomsg.sharepoint.com and kiananncomsg-my.sharepoint.com (file download). |
| web/ (mobile web app) | The same Microsoft addresses, plus its own site for the app icon, install manifest and offline copy. It never sends data to its own site. |
8.2 The red warning
A page guard runs immediately after the rule, before the rest of the app. It checks the page when it opens and keeps watching while it is open. It shows the red warning when it finds any of the following:
a block of code whose fingerprint is not on the approved list (for example an analytics or tracking snippet added by a host);
code loaded from another address, an embedded page or object, an automatic redirect, or a form that sends data;
the security rule removed, moved from the first line, loosened or changed;
anything the browser blocked because of the rule, such as an attempt to send data to another address.
When the warning appears, the report is hidden, the Choose files, Open saved data and SharePoint buttons are switched off, and the reasons are listed in the warning.
8.3 If you see the red warning
Do not load any company files, and do not sign in.
Take a screenshot of the warning, including the list of reasons.
Close the page and tell IT the address you used.
IT checks the hosted files against SHA256SUMS.txt (section 8.4) and uploads the original files from the package again.
False alarms: some browser extensions (translators, ad-blockers, password managers) add their own code to every page and trigger the warning. Open the page in a private window with extensions switched off. If the warning disappears, the extension caused it. Remove or disable that extension for this site.
8.4 Checking fingerprints (IT)
SHA256SUMS.txt lists the SHA-256 fingerprint of every app file as delivered. To check the copy on the web server has not been changed:
Download the hosted page, e.g. in PowerShell: Invoke-WebRequest https://<report address>/index.html -OutFile hosted.html
Get its fingerprint: Get-FileHash hosted.html -Algorithm SHA256 (Mac: shasum -a 256 hosted.html)
Compare it with the line for web/index.html. They must be identical.
8.5 Limits
A full replacement: checks inside a page cannot stop a host that replaces the whole file, because that host could remove the checks too. The server copy of the rule and the fingerprint check cover this. Host the app only on a server the company controls.
The device itself: the rule protects the page, not the phone or PC. Malware, or a browser extension allowed to read every site, can still see what is on screen.
Exports: CSV exports and screenshots are files you create on purpose. Keep them in company storage.
The older claude.ai page runs on a third-party host that adds its own code. It does not carry this protection, so use it only with sample data, not company files.
9. Settings and customisation
| Setting | Where to change it | Current value |
|---|---|---|
| GP% targets | In the app: Data & Notes → GP% targets (saved per device) | Parts 20%, Workshop 40% |
| Department by PIC | In the app: Data & Notes → Department mapping | Jane Teng Neng Li = Parts; Workshop Team = Workshop |
| SharePoint folder, sign-in IDs | Settings block near the top of web/index.html (IT) | Data folder link pre-filled; IDs from IT |
| SharePoint address the app may download from | source/build.py → SETTINGS, then rebuild | kiananncomsg.sharepoint.com (and -my) |
| Customer groups | Source code: CUST_GROUPS (source/src/app.js) | SBS Transit, SMRT, Tower Transit, Go-Ahead, ZF Asia |
| Component groups and factor | Source code: COMP_GROUPS, UNIT_FACTORS | Ecolife, ASTronic, Others; Transmission Actuator 0.25 |
| Excluded from employee figures | Source code: isExternal | External 1, External 2 (any "External n") |
| Excluded from utilization | Source code: UTIL_EXCLUDE | Sng Beng Huat |
| Utilization / efficiency targets | Source code: UTIL_TARGET, EFF_TARGET | 85% / 95% |
Source-code settings are grouped at the top of each section of source/src/app.js. After a change, run python3 build.py in the source folder to rebuild all versions (section 10.5).
10. Deployment and IT set-up
10.1 Hosting the web app
Upload the contents of the web/ folder to an HTTPS web address, e.g. Azure Static Web Apps (free plan) or the company intranet. SharePoint document libraries cannot run HTML pages.
Keep index.html, guide.html, manifest.webmanifest, sw.js and the icons/ folder together.
Keep the supplied web.config (IIS) or staticwebapp.config.json (Azure Static Web Apps). They send the security rule from the server as a second copy, and stop other sites from showing the app inside their pages.
Add a link or button to the address on the SharePoint site, so staff can launch it from SharePoint.
10.2 Microsoft 365 sign-in (Entra ID)
| Step | Value |
|---|---|
| App registration | Name: KCH Performance Review; single tenant |
| Platform | Single-page application; Redirect URI = the exact web address (including the trailing /) |
| API permission | Microsoft Graph, delegated: Files.Read.All (read only); grant admin consent |
| Settings block | Open web/index.html in Notepad. Near the top, find SETTINGS FOR IT and paste the Directory (tenant) ID and Application (client) ID between the quotes. Change nothing else in the file. |
| SharePoint | Users need Read access to the Data folder |
Full steps, fingerprint checks and troubleshooting are in docs/IT_Setup_Microsoft365.html.
10.3 Mobile (PWA) requirements
HTTPS is required for installation and offline start (service worker).
The service worker caches only the app’s own files. Microsoft sign-in, SharePoint and Excel data are never cached by it.
Supported: iOS / iPadOS 16.4+ (Safari), Android 10+ (Chrome), current Edge and Chrome on Windows and macOS.
10.4 Security and privacy
Data flows only from SharePoint (or the user’s own files) to the user’s device. No company data is stored in the app or on any third-party server.
The page’s own security rule and guard are described in section 8. After filling in the settings, record the new fingerprint of index.html (section 8.4).
Sign-in uses Microsoft’s own library (MSAL). The app can only read files the user can already open in SharePoint, and never writes to SharePoint.
Remembered files stay in that browser on that device, and can be removed at any time from Data & Notes.
10.5 Updating the app
Change CACHE = "kch-review-v2" in source/src/sw.js to a new value (e.g. v3), so installed phones fetch the new version.
Edit the source files in source/src, then run python3 build.py in source/. This rebuilds the standalone file, the web app and the Microsoft 365 file.
build.py adds the security rule and new fingerprints automatically, and writes a new SHA256SUMS.txt. Never edit the code in index.html by hand: the page would show the red warning. Only the settings block may be edited.
Upload the new web/ files to the web address, and fill in the settings block again (or keep your filled-in copy of the settings).
11. Troubleshooting and FAQ
| Symptom | What to do |
|---|---|
| Clicking the HTML in SharePoint downloads it | Expected: SharePoint does not run web pages. Use the company web address, or open the downloaded file on a PC. |
| A file shows "Not recognised" | The expected column headers were not found. Check that the file is the correct export and that the header row has not been renamed. |
| Invoice Margin shows "Amount in SGD label not found" | The group label row above the headers is missing; the last amount columns are used. Check the export. |
| Department "Other" has values | A PIC is not mapped. Data & Notes lists it; map it under Department mapping. |
| Budget comparisons are hidden | Clear the Customer and Employee filters, or choose a department other than Other. Check that a budget file for that FY is loaded. |
| Components page says "No matching service orders" | The Job Route and Invoice Margin files do not cover the same SOs or period. |
| Utilization shows "no available hrs" | The employee is missing from Available Hours for that month, or the name is spelt differently. |
| Sign-in error AADSTS50011 | The web address does not exactly match the Redirect URI in Entra ID. |
| "No permission to read the SharePoint folder" | Give the user Read access, or ask IT to grant admin consent. |
| Open saved data is missing on iPhone | iOS removed the saved copy. Choose the files again, or sign in. |
| Red "Security warning: this page has been changed" | Do not load files. Follow section 8.3. If it disappears in a private window with browser extensions off, an extension caused it. |
| "The settings block … is not valid" | A quote or comma is missing in the settings block of index.html. Compare it with the original in the package. |
| Warning "Blocked by the security rule: connect-src → https://….sharepoint.com" | The Data folder was moved to another SharePoint address. Update SETTINGS in source/build.py and rebuild (only IT). |
| Export CSV buttons are missing | They are hidden on the older claude.ai page. Use the standalone file or the company web app. |
12. Version history
| Version | Changes |
|---|---|
| Phase 1 | Revenue, GP, margin; filters (FY, months, department, customer, employee); budget and prior FY comparisons; Executive Summary, Customer Analysis, Data & Notes. |
| 1.1 – 1.4 | Full S$ with 2 decimals; department by PIC; latest month default; customer names as in Invoice Margin; Best months. |
| 1.5 – 1.8 | Components page with groups and drill-down; efficiency-weighted employee units; Transmission Actuator 0.25; externals removed; larger bar labels. |
| 1.9 | Customers chart by group; increase / reduction tables sorted by %; floating filter side bar; month shortcut rows. |
| Phase 2 | Labour & Efficiency: utilization (85%), efficiency per SO and per Seq Desc (95%), contribution with revenue / GP per Act hr. |
| 2.1 | Logos; Budget Achievement page (YTD vs annual budget); remember data on device; private claude.ai page. |
| 2.2 | Microsoft 365 / SharePoint sign-in and refresh; mobile web app (install, offline start); this guide. |
| 2.3 (1.1 of this guide) | Security rule on line 1 of every page (approved code fingerprints, allowed addresses); page guard with red warning and loading lock; server copy of the rule; SHA256SUMS.txt; settings moved into index.html; HTML version of this guide. |
Appendix A – Data file layouts
| File | Header row | Columns used |
|---|---|---|
| Invoice Margin | Row with Cust ID … Stock Room; "Amount in SGD" group above | Cust ID, Name, Invoice, Inv Date, SO Num, Order Ref, Curr, Invoice Amt (SGD), Charges (SGD), GST (SGD), GP, Team, PIC, Invoice Type, Stock Room |
| Job Route Summary List | Row with Cus Code … Act Cost | Cus Code, Cus Name, SO No, Job Code, Job Desc, Employee, Seq, Seq Desc, Start Date, Exp Hrs, Exp Cost, Act Hrs, Act Cost |
| Budget FY26 (C) | Row with Month | Month, Workshop Revenue, Workshop GP, Parts Revenue, Parts GP (or Revenue, Gross Profit for a total-only budget) |
| Available Hours | Row with Employee … Normal_Hours | Employee, Date Start, Normal_Hours |
| OvertimeTBL | Row with Date, Mth, Name, X 1.5, X 2 | Date, Name, X 1.5, X 2 |
Appendix B – Source folder
| File | Purpose |
|---|---|
| src/shell.html | Page layout and styles |
| src/app.js | Reading files, calculations, charts and tables |
| src/m365.js | Microsoft 365 sign-in and SharePoint loading |
| src/guard.js | Page guard: checks the code fingerprints and shows the red warning |
| src/sw.js | Service worker (offline start) |
| vendor/ | SheetJS (Excel reader), Chart.js (charts), MSAL (Microsoft sign-in), logos |
| build.py | Builds standalone/, web/ and the Microsoft 365 single file; adds the security rule on line 1, the server settings and SHA256SUMS.txt |