WFDASH-WEBAPP/docs/sops/approver-supervisor.md
Dave aed3f5c861 feat: implement discount functionality in POS system
Added support for discounts in the POS checkout process, allowing operators to apply either a fixed amount or a percentage off the gross total. Updated the state management to include discount details and modified the receipt and cart rendering to display pre- and post-discount values. Enhanced the checkout API to handle discount inputs and ensure proper calculations. Updated relevant tests to cover new discount logic.
2026-09-03 12:19:21 +02:00

18 KiB

Approver / Supervisor — SOP

Owns: the approvals queue, pricing/markup policy, escalations from Quote and Order Operators, weekly KPI reviews, and the health of the system overall.

Tools: /quotes/approvals, all operator routes (read), /dashboard, /customers, /suppliers, /settings, /api/v1/... admin endpoints, the daily summary call.

Handoffs:

  • From Quote Operator → quote in approval_pending.
  • To Quote Operator → approved / rejected / change-requested.
  • From Order Operator → escalations (cancellation, refund, discount > 15%, supplier issue).
  • To Order Operator → decision + instruction.
  • From Collection Driver → escalations (refusal, damage dispute, customer relationship issue).
  • To everyone → policy updates, training, weekly review.

1. Daily / Weekly Checklist

Every working day (start of shift, 08:00 SAST)

  • Open /quotes/approvals. Clear the queue. Anything older than 4 working hours needs a decision today.
  • Open /dashboard. Quick scan:
    • Approval Rate gauge — should be > 70% on a healthy pipeline.
    • Quote Pipeline donut — too much in new for >2 days is a Quote Operator capacity problem.
    • Follow-ups Due — count should be trending down.
    • Concentric rings (quote pipeline depth) — if the "Approved" ring is growing while the "Sent" ring is shrinking, the email send flow has a problem.
  • Check #quote-ops and #order-ops channels. Triage any escalations posted overnight.
  • Skim /orders — Cancelled tab. A spike in cancellations = supplier problem or pricing problem. Investigate.

Every working day (mid-day, 13:00 SAST)

  • Re-check /quotes/approvals. Anything still in approval_pending from this morning is now a process bug.
  • Triage any pending escalations. Quote Operators and Order Operators should be unblocked by lunch.
  • Review one random operator action (audit). Pick an order or quote at random, walk through the action log. Calibrates your understanding of the team's actual work.

Every working day (end of shift, 17:00 SAST)

  • Clear the day's escalations. Every escalation should have either a decision or a clear next step.
  • Review today's KPI snapshot. Any operator trending red? Send them a 1-line note (not a formal message — keep it human).

Every Monday morning (90 min block)

  • Pull the weekly KPI one-pager for each Quote and Order Operator (and the Collection Driver's app-export).
  • Hold the weekly standup (15 min):
    • Each operator: 1 number (their worst KPI) + 1 win.
    • You: 1 policy reminder + 1 system change coming this week.
  • Update pricing policy if any of these moved:
    • Supplier price list changes (cost-side).
    • Competitor pricing (market-side).
    • Currency moves (ZAR volatility).
    • A new strategic account needs a standing discount.

Every Friday afternoon

  • Write the 1-page weekly summary. Distribution: owner (you), the 4 operators, the invoicing clerk (if separate), and the owner / MD if you have one. Sections:
    • Pipeline health (counts by status, vs last week).
    • Top 3 wins (one per operator, named).
    • Top 3 issues (with an owner + deadline).
    • 1 thing we changed (a process, a policy, a system tweak).
    • Next week's risks.
  • Forecast cash collection for the next 30 days. Pull delivered orders not yet invoiced, sum their selling_price. This is the cash-in number the owner wants.

Every month (1st, 60 min)

  • Monthly 1-on-1 with each operator. 30 min each. Agenda (use the 1-page review you wrote):
    • Their KPIs vs target.
    • Their 30-day improvement action.
    • What they need from you (training, tools, headcount).
    • What they want to keep doing.
  • Catalogue coverage review. What % of quote items this month were matched in the catalogue? If < 50%, the Pricelist Curator needs to upload more supplier lists.
  • Supplier performance review. Late deliveries, cost-mismatch rate, damage rate. Note any supplier that should be replaced or have terms renegotiated.

Every quarter

  • Strategic review. 2-hour session with the owner. Topics: revenue trend, margin trend, customer concentration risk, supplier concentration risk, system gaps.
  • Operator tier reviews. Who's eligible for markup- authority / trusted-buyer / senior-driver tier?
  • System roadmap input. What 1-2 features would unlock the most operator capacity?

2. Step-by-Step Procedures

2.1 Approve a quote

When: a quote lands in approval_pending.

  1. Open /quotes/approvals. The queue is sorted by age, oldest first.
  2. Click a quote. Review:
    • Customer + rep — known account? Standing discount?
    • All lines priced (every line has selling_price > 0).
    • Markup — does the markup meet the policy for this category / customer?
    • Validity — is the validity date realistic?
    • Supplier — do we have a healthy relationship with this supplier? Any open POs with them?
  3. Decide:
    • Approve → click Approve. Status flips to approved. The Quote Operator can now send.
    • Request changes → add a comment in the change- request field. Status stays in approval_pending (or reverts to processed if it was a pricing issue). The Quote Operator re-submits.
    • Reject → add a reason. Status flips to rejected. The Quote Operator may revise or close the quote.
  4. Log the decision in quote.notes (auto-stamped by the system, but add context if it's non-obvious — e.g. "Approved at 18% markup, customer's standing discount from June 2026 contract").

Don't:

  • Don't approve without reading the full quote. A 30-second review misses the wrong SKU, the wrong qty, the wrong customer.
  • Don't reject without a reason. "No" is demoralising; "No, because the JEI prices are below cost" is a teachable moment.

2.2 Set / change a pricing policy

When: cost or market conditions change.

  1. Identify the affected scope. Is it a category (e.g. "all FASTENERS"), a customer (e.g. "Account XYZ"), or a supplier (e.g. "all JEI lines")?
  2. Pull the data. What is the current avg markup for that scope? What are competitors charging? What's the supplier cost trend?
  3. Propose the new policy. Document:
    • Scope (which customers / categories / SKUs).
    • New markup range.
    • Effective date.
    • Reason (market move, supplier cost, strategic account).
  4. Communicate. Post in #quote-ops, mention in the Monday standup, and pin in /settings (if there's a pricing-policy field there).
  5. Audit after 2 weeks. Pull the avg markup for the scope — is the team applying the new policy? If not, retrain.

2.3 Handle an escalation from a Quote Operator

When: a Quote Operator pings you with a question (markup override, customer relationship, stuck item).

  1. Read the full context before responding. Don't respond to a 1-line ping with a 1-line answer.
  2. Categorise:
    • Pricing → see §2.2. Likely a one-off override.
    • Customer relationship → call the customer yourself if strategic; delegate back if not.
    • System / data → the system has a gap. File a feature request in src/app/api/mcp/FEATURE-REQUESTS.md (or whatever the current backlog file is).
    • Process → the SOP is unclear. Update the relevant SOP (and tell the team).
  3. Respond with a decision + a why. The operator needs to learn from the decision, not just execute it.
  4. Follow up next day. Verify the decision was applied.

2.4 Handle an escalation from an Order Operator

When: an Order Operator pings you with cancellation, refund, discount > 15%, supplier dispute, customer complaint.

  1. Same triage as §2.3, but the stakes are usually higher (real money, real relationships).
  2. For customer complaints — get the customer's side of the story first. Don't take the operator's word at face value; don't take the customer's at face value either.
  3. For supplier disputes — pull the PO + delivery evidence (photos, signed notes). Make the call based on the contract, not the relationship.
  4. Document the decision in the order's notes and your private escalation log.

2.5 Run a weekly KPI review

When: every Monday.

  1. Pull the one-pager. Each operator has 4-6 KPIs. The report highlights who's red, who's yellow, who's green.
  2. For each red operator:
    • Look at the underlying data. Is it a process issue, a capacity issue, or a skill issue?
    • Process → fix the SOP, retrain.
    • Capacity → redistribute the load or accept the miss.
    • Skill → 1-on-1 coaching, shadow a senior operator.
  3. For each green operator:
    • Find the win. Mention it in the standup.
    • If they're consistently green, consider the tier bump.
  4. Write the 1-page weekly summary. (See §1 Friday.)

2.6 Audit a random operator action

When: mid-day, when you have 10 minutes.

  1. Pick a random order or quote from the last 24 hours.
  2. Walk the action log: who touched it, when, what changed.
  3. Look for:
    • Status transitions that don't match the SOP (e.g. pending → delivered skipping the intermediate states).
    • Pricing changes without a pricing_notes breadcrumb.
    • Items stuck in a state longer than the SLA.
  4. If you find a real issue: message the operator privately, not in public. Coaching, not blame.
  5. If you find a SOP gap: update the SOP.

3. Decision Tree

3.1 Should I approve this discount?

What's the customer's standing discount (per the customer
record / contract)?
├── Matches → approve at face value
└── Doesn't match
    ├── Is the difference small (< 3%)? → approve, log the
    │                                       reason (e.g.
    │                                       "volume uplift
    │                                       from Q3 contract").
    ├── Is the difference medium (3-10%)? → approve if
    │                                          the customer
    │                                          is strategic
    │                                          OR the deal
    │                                          is a one-off
    │                                          (large order,
    │                                          end-of-line
    │                                          stock, etc).
    │                                          Otherwise,
    │                                          ask the
    │                                          operator to
    │                                          split the
    │                                          margin with
    │                                          the customer
    │                                          themselves.
    └── Is the difference large (> 10%)? → talk to the
                                          customer
                                          yourself.
                                          Strategic
                                          pricing is a
                                          relationship
                                          call, not a
                                          quote.

3.2 Supplier wants to renegotiate terms

Is the supplier a strategic dependency (> 20% of our spend)?
├── Yes → call the supplier yourself. Don't delegate.
│         Renegotiation is a relationship call.
└── No
    ├── Will the new terms save us money or improve
    │   service? → accept, log in the supplier record.
    └── Will they cost more or worsen service? → decline,
                                                  keep the
                                                  relationship
                                                  professional
                                                  (don't burn
                                                  the bridge).

3.3 Customer escalates a quality issue

Is the issue real (defect, wrong item, damaged in transit)?
├── Yes
    ├── Was the issue caused by us (wrong pick, late
    │   delivery, damaged in our care)?
    │   ├── Yes → own it. Replace or refund, no argument.
    │   │         Don't ask the customer to prove the
    │   │         damage.
    │   └── No (supplier defect, customer mishandling)
    │       ├── Defect is our supplier's → call them, get
    │       │                              a credit or
    │       │                              replacement, pass
    │       │                              it on.
    │       └── Customer mishandling → politely decline.
    │                                    Offer a goodwill
    │                                    discount at your
    │                                    discretion.
    └── What's the cost of fixing vs losing the customer?
        ├── Customer is strategic → fix, no matter the
        │                            cost. Relationships
        │                            > margins.
        └── Customer is transactional → fix only if it's
                                        cheaper than
                                        losing them. Most
                                        one-off customers
                                        aren't worth a
                                        free replacement.

3.4 An operator is consistently missing a KPI

How long have they been missing it?
├── < 2 weeks → noise. Mention in the 1-on-1, move on.
├── 2-4 weeks → pattern. Diagnose:
│   ├── Process gap (unclear SOP) → update the SOP,
│   │                              retrain.
│   ├── Capacity gap (too much load) → redistribute.
│   └── Skill gap (doesn't know how) → pair with a
│                                     senior operator for
│                                     a week.
└── > 4 weeks → performance issue. Formal conversation.
    Set a 30-day improvement target with consequences
    if missed.

3.5 A quote is in approval_pending for > 1 working day

Who submitted it?
├── Quote Operator on shift → ping them directly. "Why is
│                               this still in my queue?"
└── Quote Operator off shift / on leave → reassign to
                                          another operator
                                          OR approve it
                                          yourself if
                                          straightforward.

3.6 The system is misbehaving (data loss, wrong status, etc.)

Is the issue isolated to one record?
├── Yes → fix the record directly via the admin tools or
│         `pb-helpers.ts` / service layer. Document the
│         fix.
└── No (multiple records, or a pattern)
    ├── Stop the workflow that's causing the damage.
    │   (e.g. pause the n8n email intake if it's creating
    │   bad quotes.)
    ├── Page the dev. Don't try to fix the code yourself
    │   unless you ARE the dev.
    ├── Communicate to the team: "stop doing X until
    │   further notice."
    └── After the fix: write up the post-mortem. What
        happened, what we did, what we'll do to prevent
        it. Share with the team.

3.7 Strategic account wants terms we don't usually offer

What's the customer's annual spend with us?
├── Top 10% → call the owner / MD. Strategic accounts
│            can have bespoke terms; it's a relationship
│            call.
├── 10-25% → decide yourself. Document the terms in the
│            customer record, in a contract if material.
└── Bottom 75% → decline. Standardise. Bespoke terms
                 for non-strategic accounts erode
                 margin and create admin overhead.

4. KPIs

The supervisor's KPIs are different from the operators' — they're about the team's health, not the supervisor's own output.

KPI Target How it's measured
Approval turnaround < 4 working hours median approved_at - submitted_at on quotes/approvals
Escalation response time < 2 working hours decision_at - escalation_at on the escalation log
Team KPI attainment > 80% of operator KPIs at target weekly one-pager summary
Quote → order conversion > 35% trailing 90 days orders / emailed quotes
On-time delivery rate > 90% trailing 30 days orders delivered by delivery_date / total delivered
Catalogue coverage > 60% of quote items matched sprint items with matched_price_list_id / total sprint items
Supplier cost-mismatch rate < 3% trailing 30 days cost_mismatch verdicts / total receives
Customer concentration risk top customer < 30% of revenue revenue by customer over trailing 90 days
System uptime > 99% trailing 30 days uptime of WFDASH + PB + n8n (monitor externally)
Team tenure trending up months since each operator's start date

How the supervisor's KPIs feed into YOUR review

  • Weekly: the owner / MD sees the weekly summary. Your team KPIs are the headline.
  • Monthly: 1-on-1 with the owner / MD. Focus on strategic accounts, concentration risk, and system gaps.
  • Quarterly: strategic review. This is where you push for the headcount / tools / process changes the team needs.

What the system does NOT measure (yet)

  • Operator morale (no internal NPS yet)
  • Customer satisfaction (no external NPS yet)
  • Operator skill growth (no per-operator skill matrix yet)

If a KPI is unfair, raise it. The owner can adjust targets, but the metric stays.