XeerSoft CRM · Custom Loyalty Module
Project 03 · Jun 2024 – Jan 2025 · Go-Live Jan 2025

CRM Star Reward
Loyalty System

BA / Implementation Consultant who helped design, build, harden and roll out a Star Reward loyalty system on XeerSoft Cloud ERP: the commendation workflow, LINE notifications to students & parents, rank tiers, and a bulk Excel import for awarding stars at scale. Led 5 iterative UAT cycles that caught a critical silent-failure defect, hitting zero critical post-launch incidents. Live since Jan 2025, rolled out to 100+ staff school-wide.

Project SpecP-03
Platform XeerSoft Cloud ERP
Role BA · Build · UAT Lead
Rollout 100+ staff · school-wide
Duration 7 months
Module CRM · Custom Loyalty Logic
UAT Cycles 5 build cycles
Status LIVE · Jan 2025
100%
✓ cleared
Go-live blockers cleared
found11
go-live0
0
✓ zero
Critical post-launch
100+ staff school-wide
live since Jan 2025
60
Defects tracked
5 UAT cycles · all documented
83.8% resolved pre go-live
5
UAT build cycles
blockers 7 → 2 → 2 → 0
Live UAT Dashboard
CRM Loyalty UAT · Defect Resolution Tracking
Power BI
Power BI dashboard showing UAT defect tracking across 5 build cycles

Business Context & Problem

The school runs a Star Reward loyalty programme: supervisors award stars to students for behaviour, participation and achievement, and the school turns accumulated stars into certificates and prizes that keep students motivated to learn (a Starbucks-style loyalty loop, applied to education). My remit on XeerSoft Cloud ERP was to help design, build, harden and roll out the system that runs it: the Commendation workflow, rank tiers, parent notifications over LINE, and a bulk Excel import so staff can award stars at school scale.

I worked as the Business Analyst / Implementation Consultant: shaping requirements and the functional spec with the XeerSoft development team, designing the import standard every staff member now uses, then leading 5 iterative UAT cycles that caught a critical silent-failure defect before launch. The system went live for the January term and rolled out to 100+ staff school-wide.

My Role & Accountability

The programme lives inside a School Management workspace on XeerSoft Cloud ERP. I worked across two modules: Activity (the Star Reward / Commendation engine) and a companion Leave & Online Learning module, with the Commendation list as the daily driver for every supervisor.

Activity · Commendation Award stars, write the reason, fire LINE notifications, and track each student's running balance & rank. The screen 100+ staff use every day. primary module
Bulk Star Import One standard Excel file → many students, many stars, in a single upload. Validated and written straight into the Cloud ERP. my design
🏅
Rank & Rewards Lifetime stars roll up into Bronze → Platinum ranks; the school issues certificates and prizes off the same data. gamification
🗓
Leave & Online Learning Companion module in the same workspace: student leave / online-learning requests with supervisor, track and status filters. companion

The Commendation List is the heart of it: a searchable student roster where any supervisor finds a student, opens the commendation panel, and awards stars in seconds. Below is a faithful recreation of that screen (student data anonymised):

🔒 Representative recreation · the real screen on XeerSoft Cloud ERP · student names, IDs, emails & photos anonymised · star counts illustrative.
★ Commendation List 🔎 Find student: ID · name · e-mail Supervisor ▾ ⬆ Import
Student IDStudentLevelStarsRank
AP
S-1042
Anya P. · "Aom"
Year 12 124 Platinum
BT
S-2087
Boon T. · "Tao"
Year 11 86 Gold
CM
S-1190
Chai M. · "Mint"
Year 10 41 Silver
DR
S-3055
Dao R. · "Ploy"
Year 12 19 Bronze
EK
S-2210
Eak K. · "Gun"
Year 9 6 Bronze
opens the commendation panel (give stars + reason) · opens that student's message history · ⬆ Import is the bulk path I designed. Live programme rolled out to 100+ staff.

Solution Design · Recognition Loop

A commendation is never just a number. Awarding stars also writes the reason, notifies the student and their parent over LINE, and re-computes the rank — closing the loop between the classroom and home. Each message has two LINE targets (student + parent), and delivery is tracked per target.

STEP 1
Find & openSupervisor searches the roster, opens the commendation panel for one student.
STEP 2
Award + reasonSet the star count (+ / −), write the required comment, or pick a message template.
STEP 3
Notify over LINESends to 2 targets — the student and a parent — and logs the delivery status of each.
STEP 4
Balance & rankBalance increments, the transaction is logged, and the rank tier recalculates automatically.

Every commendation is auditable as a message record: who sent it, how many stars, the message, and whether each LINE target was delivered. Recreation below:

🔒 Representative recreation · the Student Commendation Message List · senders, students & messages anonymised · LINE delivery status mirrors the real two-target model.
SenderStarsMessageLINE targetsStudentParentDate
Kao3 ★Excellent work on your assignment.Total: 2SuccessSuccess2025-05-27
Benz2 ★You nailed it — keep it up.Total: 2SuccessSuccess2025-05-26
Jay1 ★Great class participation today.Total: 2ExpiredSuccess2025-05-30
Pim5 ★Top of the cohort this term.Total: 2SuccessSuccess2025-03-11
Two LINE targets per commendation (student + parent). Expired = the recipient never linked / the push window lapsed — surfaced so staff can follow up, exactly as in the live system.

Lifetime stars roll up into rank tiers. Ranks are what the school recognises at assembly and converts into certificates and prizes, so the tier ladder is the motivation engine of the whole programme:

🥉
Bronze
1 – 24 ★
Getting started · first commendations
🥈
Silver
25 – 59 ★
Consistent contributor
🥇
Gold
60 – 99 ★
Standout across the term
🏆
Platinum
100 ★ +
Top tier · certificate & prize

Note: Bronze → Silver → Gold → Platinum is the live rank ladder; lifetime stars roll a student up the tiers, and the school recognises each tier with certificates and prizes.

Solution Design · Bulk Star Import

The feature I'm most proud of designing. Awarding stars one student at a time is fine for a single class, but at school scale a supervisor might log hundreds of stars after an event, a term, or a competition. Clicking + on each student, one by one, doesn't scale. So I designed a single standard Excel format that every staff member uses to import stars in bulk — straight into the Cloud ERP.

Before · manual entry
1 student / click

Open each student, set stars, write a reason, send. Repeated hundreds of times for a single event — slow and error-prone.

After · bulk import
1 file → many students

Fill the standard template once, upload, and every row is validated and written in a single pass — with the same audit trail and LINE notifications.

The win of a single standard format is consistency: every supervisor across the organisation prepares the file the same way, so imports are predictable and validatable. Columns, types and which fields are required:

ABCDE
Reason *Year *Class *Email *Sender *
1Assignment9Pre-IGCSE Physicsstudent.a@newton.ac.thsupervisor@newton.ac.th
2Assignment9Pre-IGCSE Physicsstudent.a@newton.ac.thsupervisor@newton.ac.th
3Q&A9Pre-IGCSE Mathstudent.b@newton.ac.thsupervisor@newton.ac.th
4Activity11IGCSE Further Mathstudent.c@newton.ac.thsupervisor@newton.ac.th
5Activity11IGCSE Further Mathstudent.c@newton.ac.thsupervisor@newton.ac.th
6Engagement12International AS-Level Physicsstudent.d@newton.ac.thsupervisor@newton.ac.th

One row = one star. A student's star total is the number of rows carrying their Email (the match key); Reason categorises each star (Assignment · Q&A · Engagement · Activity) while Year and Class carry the curriculum context. Above, student.a earns 2 stars (2 rows) and student.c earns 2 Activity stars. Every field is required; emails anonymised here.

How the import runs end-to-end once the file is uploaded:

01 · PREPARE
Standard templateStaff fill the one approved Excel format.
02 · UPLOAD
ImportUpload from the Commendation List.
03 · VALIDATE
Match & countMatch each row by email, count rows per student, flag unknown emails.
04 · WRITE
Bulk upsertBalances + transaction log, atomically.
05 · NOTIFY
LINE + rankPush to student & parent; recompute rank.

Live Import Simulation

An interactive model wired to a representative class roster (anonymised). For each row pick a Year → Track → Class → Student (Year 8–9 have no track; Year 10 splits Science / Business; Year 11–13 split into the five tracks) and the student's e-mail auto-fills; set the star count and the reason, then run Validate & Import. Rows are grouped by student e-mail and each balance & rank updates live (saved in your browser) — the specified behaviour I designed, not the proprietary XeerSoft UI.

XeerSoft Cloud ERP · CRM · Loyalty › Bulk Import Simulation SIMULATION

Build the import — pick Year → Track → Class → Student · e-mail auto-fills · set ★ & reason

#ReasonYearTrackClassStudentE-mail (auto)

Validation & writes

Live student balances — updates on import

Pick Year → Track → Class → Student; the e-mail auto-fills, then set how many stars and the reason. On import, rows are grouped by student e-mail and written as a single batch — balances and ranks update live and persist in your browser. Public demo uses an anonymised roster; on the school's machine a local data file supplies the live roster. Demonstrates the specified behaviour, not the proprietary interface.

Validation Risk · Critical Defect

DEF-001 · Entry-level blocker found Cycle 1

Symptom: Bulk star-point assignment to multiple students simultaneously was non-functional: only the first student received points; all others were silently skipped.

Root cause (identified by Dev after my escalation): The assignment function contained a loop with an inadvertent early exit after the first iteration.

Severity: P1: would silently fail in production with no error message, making it the hardest type of bug to detect post-launch.

UAT Defect Lifecycle · How I Managed Each Bug
BA / TESTER LANE DEVELOPER LANE BA / TESTER LANE (RETEST) 1. Detect Bug 2. Document 3. Set Severity 4. Escalate 5. Dev Fix 6. Build & Push Notify BA 7. Retest Pass? YES 8. CLOSED ✓ NO REGRESSION

Validation Outcome · Build Cycles

I structured UAT into 5 build cycles, each with explicit entry criteria, test scenarios, and exit gates. The defect log was the central artifact: every defect tracked from OPEN → IN-DEV → RETEST → RESOLVED with reproduction steps, severity, and regression test status.

Cycle Total Defects Go-Live Blockers Regression Count Reduction %
Cycle 1 16 7 0 baseline
Cycle 2 12 2 5 ▼ 25%
Cycle 3 12 2 2 ▼ 25%
Cycle 4 10 0 2 ▼ 37.5%
Cycle 5 10 0 1 ▼ 37.5%

Validation Evidence · Defect Log

The central UAT artifact: every defect tracked with ID, area, severity, the cycle it surfaced in, and status. DEF-001 (the silent bulk-assign failure) was the entry blocker; the rest span the validation scope below.

🔒 Representative recreation · DEF-001 is the real defect; other rows illustrative and masked · the totals (60 tracked · 11 blockers → 0 by Cycle 4 · 0 critical post-launch) are the real results.
IDTitleAreaSeverityCycleStatus
DEF-001Bulk star-assign stops after first student (silent)Loyalty · AssignP1C1Resolved
DEF-002 illus.Voucher re-redeemable after first useRedemptionP1C1Resolved
DEF-014 illus.Partial redemption leaves balance mismatchStar balanceP2C2Resolved
DEF-021 illus.Campaign trigger fires twice on record editCampaignP2C2Resolved
DEF-038 illus.Star-log timestamp missing on bulk actionAudit trailP3C3Resolved
DEF-052 illus.Reward label truncated on student portalUIP3C4Deferred
Real totals: 60 defects across 5 cycles · 11 P1 blockers driven 7 → 2 → 2 → 0 (cleared by Cycle 4) · 0 critical post-launch. Rows other than DEF-001 are illustrative, masked to the validation areas below.

XeerSoft Module Flow

The loyalty process as built in the XeerSoft CRM module: module → function paths.

#Process StepXeerSoft Function
1Teacher assigns stars (multi-select)Loyalty › Bulk Assign
2Update per-student balanceLoyalty › Star Balance
3Log every transactionLoyalty › Transaction Log
4Student views balance & historyStudent Portal › Balance & History
5Redemption + voucher validationLoyalty › Redemption / Voucher

Functional Spec & Data Model

The logical entities I specified for the loyalty module in the FSD: field design defined by me, physical implementation by the development team.

Entity: Student Star BalanceTypeDescription
Student ID (key)Char(10)Unique student identifier
Branch (key)Char(4)1100 / 1200 / 1300
Academic YearChar(4)e.g. 2024 / 2025
Current BalanceDec(7,0)Stars available now
Lifetime EarnedDec(7,0)Total ever earned
Total RedeemedDec(7,0)Total ever redeemed
Last Updated / ByDate / CharAudit of last change
Entity: Star Transaction LogTypeDescription
Log ID (key)Numeric(10)Auto-increment
Student ID (key)Char(10)Student reference
ActionChar(1)A = Assign · R = Redeem
StarsDec(5,0)Stars in this transaction
ReasonChar(50)Teacher’s reason
Assigned By / TimestampCharWho & when

Functional Spec & Fix Logic · DEF-001

My defect report specified the corrected expected behaviour for the bulk-assignment routine: it must iterate over every selected student, not stop after the first.

FSD-P3-02 · bulk-assign fixspec · pseudocode
// FSD-P3-02 · DEF-001 corrected behaviour: iterate ALL selected students FUNCTION assign_stars(selected[], stars, reason, user): FOR EACH student IN selected: // defect stopped after the 1st record bal = find_balance(student, current_year) IF bal not exists → create_balance(student, stars) ELSE → bal.current += stars; bal.earned += stars write_log(student, action = A, stars, reason, user) COMMIT all updates atomically // all-or-nothing

Live Spec Simulation

An interactive simulation that runs the FSD logic above directly in your browser: it reproduces the specified behaviour I designed, not the proprietary XeerSoft UI.

XeerSoft Cloud ERP · CRM · Loyalty › Bulk Assign Simulation SIMULATION

Bulk Star Assignment

Result · FSD-P3-02

Toggle the bug to reproduce exactly what I caught in UAT Cycle 1: the loop exits after the first record, so only one student is updated while the rest fail silently.

Transaction log

Demonstrates the specified fix vs the original defect · not the proprietary XeerSoft interface.
Delivery model · role boundary

On XeerSoft Cloud ERP I worked as Functional Consultant / Business Analyst: owning requirements, configuration, FSD authoring, UAT and defect management. The custom logic below was implemented by XeerSoft’s in-house development team against my specifications.

The pseudocode shown is the specified expected behaviour (my FSD deliverable), not vendor source code, and deliberately platform-neutral so it reads the same to a XeerSoft or generic ERP reviewer.

Validation Scope

Beyond the bulk assignment fix, UAT validated:

Acceptance criteria verified

· Voucher security controls: preventing duplicate redemption of same voucher

· Points redemption logic: partial vs full redemption, balance verification

· Campaign triggers: automated points award on configured events

· Regression testing: verified individual assignment still worked after bulk fix

· Audit trail: every transaction traceable via star log

Validation, UAT & Defect Control

The 5 build cycles and ~60 defects shown above are the summary view. This is the granular decomposition behind them: I broke the loyalty scope into 10 sub-unit tests, each run as a manual procedure of ~10 ordered steps validated against 5 complex conditions, with one written specific assurance per sub-unit (the exact thing the test guarantees). As UAT Lead I ran these by hand across the cycles; the steps, conditions and defect rows below are representative of the documented Jira log.

📋 Manual test criteria · how every sub-unit was validated

Each sub-unit test is a manual procedure: log in under the correct staff role, drive the award / redemption / rank flow step by step, and confirm the balance, transaction log and tier outcome at each gate. Every test carries 5 complex conditions — all-rows / partial-fail / duplicate / invalid / concurrency paths — not just the happy path. A sub-unit only closes when its specific assurance holds under all five and a regression retest is clean.

Flagship worked test case · full manual procedure 10 steps · 5 conditions
UT-P3-02 Bulk star import · multi-student award PASS · after fix

Role: Staff / Award · this is the procedure that caught the go-live blocker: a bulk star-point assignment that silently skipped every student after the first — no error, no failed-row report. This test was built to prove a batch reaches all of its targets.

Manual procedure · 10 steps

  1. Log in as Staff / Award role; open the bulk star import screen Import.
  2. Prepare a CSV of 30 students with star amounts and a single award reason.
  3. Validate the template — required headers, column order and data types Template.
  4. Run a dry-run preview; confirm all 30 rows parse and map to valid student IDs.
  5. Record each student's pre-import balance as the baseline.
  6. Execute the import; capture the batch ID and the row-level result summary.
  7. Confirm all 30 balances incremented by the exact star amount — not just the first.
  8. Verify a star transaction is logged per student (student, amount, reason, batch).
  9. Confirm each student's rank / tier is recalculated against the new lifetime total.
  10. Reconcile the batch summary: rows imported = 30, awarded = 30, failed = 0.

Complex conditions · 5 paths

  • C1All rows — every one of the 30 students receives points, not just the first; the critical path this test exists to prove.
  • C2Partial fail — one invalid row must fail that row only and roll back cleanly, never abort the batch silently.
  • C3Duplicate / re-run — re-importing the same batch must not double-award (idempotency).
  • C4Invalid student ID — an unknown / mistyped ID is rejected with a reported error, not silently dropped.
  • C5Concurrency — two imports running at once must not corrupt or interleave balances.
◆ Specific assurance

Guarantees that a bulk award writes to every targeted student or reports exactly which rows failed — no student is ever silently skipped — that a re-run never double-awards, and that every successful row leaves a logged transaction and a recalculated rank. A row that cannot be applied is reported in the batch summary, not dropped — the exact failure mode caught in UAT and closed as DEF-P3-01.

Sub-unit test register · the full decomposition 10 components
UT-P3-01Points accrual · earn rules on a single commendation9 steps
  • Configured earn rule awards the exact star amount on a commendation
  • Award reason and source event are stored on the transaction
  • Zero / negative star amount rejected before it posts
  • Balance increments atomically — no partial write
  • Lifetime and term counters both move together
Assurance: a single commendation always posts the configured star amount once, with a logged reason, and can never write a negative or partial balance. PASS
UT-P3-02Bulk star import · multi-student award10 stepsflagship
  • All 30 students awarded, not just the first (the critical path)
  • One invalid row fails that row only; batch is not aborted
  • Re-running the same batch does not double-award
  • Unknown student ID rejected with a reported error
  • Two concurrent imports do not corrupt balances
Assurance: detailed above — a bulk award reaches every targeted student or reports exactly which rows failed, with no silent skips. PASS · after DEF-P3-01
UT-P3-03Rank tier recalculation · Bronze → Platinum9 steps
  • Crossing 25★ / 60★ / 100★ promotes the tier
  • Recalc fires after the balance commits, not before
  • A multi-tier jump in one award lands on the correct tier
  • Tier never lags one transaction behind the balance
  • Downgrade path (on reversal) recomputes too
Assurance: a student's tier always matches their committed lifetime balance the instant the award posts — never one transaction stale. PASS · after DEF-P3-02
UT-P3-04Tier-boundary edge cases · 24/25, 59/60, 99/1008 steps
  • 24★ stays Bronze; 25★ flips to Silver (inclusive lower bound)
  • 59★ Silver; 60★ Gold — no off-by-one
  • 99★ Gold; 100★ Platinum exactly at the boundary
  • An award landing exactly on the boundary promotes, not holds
  • Boundary logic identical for accrual and reversal
Assurance: every tier threshold is inclusive at its lower bound and resolves with no off-by-one, so a student on an exact boundary lands in the higher tier. PASS
UT-P3-05Points reversal · mis-award correction9 steps
  • Reversing a mis-award subtracts the exact amount
  • Reversal re-triggers tier recalc (can downgrade)
  • A logged reversal transaction references the original
  • Cannot reverse more than was awarded (no negative balance)
  • Double-reversal of one award is blocked
Assurance: a reversal both corrects the balance and re-evaluates the tier, so a downgraded student never keeps a rank they no longer qualify for. PASS · after DEF-P3-03
UT-P3-06Lifetime vs term stars · rollup8 steps
  • Tier is driven by lifetime stars, not the term balance
  • Term reset clears the term counter, never the lifetime
  • Lifetime total reconciles to the sum of all transactions
  • A term reset never silently downgrades a tier
  • Reports separate term and lifetime cleanly
Assurance: lifetime stars drive ranking and survive every term reset, so a student is never demoted just because a new term began. PASS
UT-P3-07Member enrollment · new-student onboarding8 steps
  • A new student starts at 0★ Bronze by default
  • Required identity fields enforced on create
  • Duplicate enrollment of the same student blocked
  • A new member is immediately eligible for bulk import
  • Onboarding writes an auditable creation record
Assurance: every new student enters as a valid, deduplicated Bronze member ready to receive awards, with no duplicate loyalty records possible. PASS
UT-P3-08Duplicate-award prevention · idempotency9 steps
  • Re-submitting the same award is applied once
  • Idempotency key on (student, batch, reason)
  • An already-applied row is rejected, not re-posted
  • A retry after a timeout does not double-award
  • The batch summary reports rows skipped as duplicates
Assurance: the same award can be submitted repeatedly and only ever counts once, so a retry or re-run can never inflate a student's balance. PASS · after DEF-P3-04
UT-P3-09Leaderboard · ranking report7 steps
  • Ranking ordered by lifetime stars, then tier
  • Ties resolved deterministically across runs
  • Tie-break by earliest award timestamp
  • Totals reconcile to the underlying star log
  • Authorisation: staff see only their scope
Assurance: the leaderboard is reproducible — the same data always yields the same order — and its totals reconcile back to the transaction log. PASS · after DEF-P3-05
UT-P3-10Authorisation · who may award & staff scope7 steps
  • Only the award role can post or reverse stars
  • Staff scope limits which students they may award
  • Out-of-scope award attempt is blocked and logged
  • Bulk import respects the same scope as single award
  • Every award is attributable to a named user
Assurance: only authorised staff can award within their scope, and every star movement is attributable to a named user for audit. PASS
Test execution timeline · UAT cycle by working day
Day 1Day 13Day 25
Points accrual & earn rules
2d
UT-01
Bulk star import (defect)
3d
UT-02
Rank tier recalculation
2d
UT-03
Tier-boundary edge cases
2d
UT-04
Points reversal / correction
2d
UT-05
Lifetime / term & onboarding
3d
UT-06–07
Idempotency & leaderboard
3d
UT-08–09
Authorisation & staff scope
2d
UT-10
Regression · all 5 fixes
3d
retest
Sign-off & Go-Live readiness
3d
gate
Sub-unit testDefect foundRegression retestSign-off gate
Defect log · raised to dev → fixed → retested
IDSub-unitWhat broke (symptom)SevRoot causeFix I specified to devDaysRetest
DEF-P3-01 UT-02 bulk import A bulk award silently skipped every student after the first — only row 1 received points, no error raised. HIGH The import committed only the first row, then exited the loop with no per-row error capture. Rewrote it as a per-row committed loop with per-row success/fail capture and a batch summary of awarded vs failed rows. 3 ✓ PASS
DEF-P3-02 UT-03 tier recalc Rank lagged one transaction at a tier boundary — a student showed the old tier after promotion. MED Tier was recalculated before the balance commit (off-by-one). Recalculate the tier synchronously after the balance commits. 2 ✓ PASS
DEF-P3-03 UT-05 reversal Reversing a mis-award corrected the balance but did not downgrade the rank. MED Reversal updated the balance but never re-triggered tier recalc. Fire tier recalc on reversals too, not only on accruals. 2 ✓ PASS
DEF-P3-04 UT-08 idempotency Re-running an import re-awarded points — the same batch counted twice. HIGH No idempotency key on (student, batch, reason). Dedupe on a batch key; reject already-applied rows and report them as skipped. 2 ✓ PASS
DEF-P3-05 UT-09 leaderboard Tied students were ordered non-deterministically between runs. LOW No tie-break rule on equal star totals. Deterministic tie-break by earliest award timestamp. 1 ✓ PASS

These 5 rows are representative of the full Jira log — ~60 defects across the 5 build cycles, 83.8% resolved before go-live and zero critical post-launch. The discipline shown here — a named symptom, a root cause, a fix I specified to dev, days-to-resolve and a regression retest — is how every one of them was managed. The silent-skip blocker (DEF-P3-01) is the one that mattered most, because it failed without an error.

Measured Results

The measurable result was a controlled UAT burn-down rather than a lucky launch. Across 5 build cycles, I tracked 60 defects, drove go-live blockers from 11 to 0, managed 10 regressions, and reached zero critical post-launch incidents. The blocker trend moved 7 → 2 → 2 → 0 → 0, with defect reduction up to 37.5%.

Tools & Deliverables

XeerSoft CRM Module Custom Loyalty Logic Bulk Excel Import (Standard Template) LINE Notification (Student + Parent) Rank & Rewards Logic UAT Test Case Authoring Defect Log (Excel + Jira) Power BI Dashboard draw.io (UAT Flow) Word (Acceptance Criteria) Regression Test Suite

Delivery Timeline

How the project was actually run end-to-end after the consulting work above: the timeline and where it was at risk, how I specified the build for the developers and verified it, the weekly Agile cadence, and the stakeholder network I coordinated as the single point of accountability.

⏱ Schedule stakes · why the date mattered

Go-Live was tied to the January academic term: the reward programme had to launch with the term to be meaningful. At Cycle 1 the project carried 11 go-live blockers including the critical DEF-001 bulk-assign defect, directly threatening that fixed date.

Project timeline · month-by-month

Jun
Jul
Aug
Sep
Oct
Nov
Dec
Jan
Onboarding + acceptance criteria
2 mo
UAT Cycle 1 · DEF-001 found
C1 ⚠
Cycles 2–4 · blocker burn-down
C2–4
Cycle 5 + regression + sign-off
C5
Go-Live (academic term)
LIVE
DeliveredRisk / slippedRecoveredGo-LivePlanned / in progress

Schedule risk & recovery

11 go-live blockers threatened the Jan date

The bulk-assignment defect (DEF-001) failed silently and 11 P1 blockers stood between the build and a usable launch with only months of runway. Resolved → I severity-triaged every defect, ran 5 iterative UAT cycles, and drove blockers 7 → 2 → 2 → 0, clearing all of them by Cycle 4 and hitting the January Go-Live with zero critical post-launch incidents.

Silent-failure class of bug

DEF-001 produced no error message, the hardest type to catch and the kind that would have surfaced months into production. Resolved → I made multi-select / negative-path testing a mandatory entry gate, so the same failure class is caught at Cycle 1, not in production.

Spec design → developer handoff → build verification

01Requirements & As-IsStakeholder interviews, executive sessions, current-state process mapping.
02To-Be & AcceptanceTarget process design + measurable acceptance criteria agreed up front.
03FSD AuthoringDecision tables, field-level data model, GL/workflow rules, edge cases.
04Dev HandoffSpec walkthrough with the dev team, clarify, agree Definition-of-Done.
05Build VerificationTrace the build back to the FSD: data model, posting, workflow, negatives.
06UAT → Go-Live → HypercareCycle sign-offs, defect burn-down, cutover, post-live support.

How I spec for developers

  • Write every rule as a decision table (input → expected output), not prose.
  • Specify the data model field-by-field: keys, types, validation.
  • Define GL posting and workflow thresholds explicitly, with examples.
  • Enumerate edge & negative cases up front (multi-select, zero, partial, duplicate).
  • Agree a Definition-of-Done before the build starts.

How I verify the build (functional, not source-code review)

  • Functional trace: every FSD rule reproduced in the build.
  • Data model check: fields, keys and validation match the spec.
  • Posting check: correct GL accounts, debit/credit, contra logic.
  • Workflow check: routing & thresholds behave per the matrix.
  • Negative / edge tests before happy-path sign-off (the DEF-001 lesson).
  • Regression after every fix: nothing closes without a retest.

Weekly Agile cadence

MON

Plan cycle scope + entry criteria

TUE

Execute test cases (incl. edge)

WED

Log defects: repro + severity

THU

Dev fixes → retest + regression

FRI

Cycle exit gate / sign-off

5
UAT build cycles
60
Defects tracked
11 → 0
Go-Live blockers cleared

Stakeholder network & RACI

Chatree · sole consultant single point of accountability across 50+ UAT participants · teachers (assign) · students (redeem) · remote XeerSoft dev team
StakeholderCountTheir partRACI
You · BA + UAT Lead1Acceptance criteria, defect mgmt, sign-offA / R
UAT participants50+Executed test scenarios across branchesR
TeachersmanyAssign stars; primary operatorsI / R
Students50+Redeem rewards; end beneficiariesI
XeerSoft dev teamremoteFixed DEF-001 + built custom logicR

I joined mid-build and became the single owner of quality, coordinating 50+ testers and the dev team across 5 cycles. The DEF-001 catch alone changed whether this launched working or broken.

Consultant Takeaway

The biggest takeaway: UAT isn't just confirming what works: it's hunting for what fails silently. The bulk-assignment bug would have been invisible in production for months because there was no error message. Finding it required deliberately testing the edge case (multi-student selection) rather than the happy path (single student). Every UAT plan I write now starts with "what could fail without anyone noticing?"

The second lesson was about design for scale: a feature that works for one user can still fail an organisation. Awarding stars one click at a time was correct but unusable at 100+ staff, so the real win was the one standard import format everyone follows — turning a per-click chore into a single, validated, auditable upload. Good ERP work is as much about the standard you set as the screen you build.

← Previous Project Strategic Pricing & AR Configuration