Share:

Collections Portal

Replacing the debt ledger — the debt collection spine, with the ladder as its first consumer
DRAFT v7 · 31 July 2026
Contents
  1. First — what IES actually is
  2. How we know someone missed
  3. Square or IES — the split
  4. Retiring the debt ledger
  5. The debt collection spine
  6. The escalation ladder
  7. The stage 1 conversation
  8. What changes for Caet
  9. Where every field comes from
  10. The portal, screen by screen
  11. Reduction offer rules
  12. The clock — what fires when
  13. Integrations
  14. Build phases
  15. What we need from Colin
  16. Decisions still open
  17. Risks

01First — what IES actually is

The ChatGPT plan is built on a wrong assumption

The shared doc says "transitioning to IES booking platform" and designs the whole workflow to live inside it — account assigned in IES, IES sends the email and text, collector logs into IES each morning to see her queue.

IES is Intuit Enterprise Suite — the accounting platform we're migrating QuickBooks Online to. It's in our own notes: sandbox realm 9341456604789019, "IES Sandbox Company US 59bc", production blocked "waiting for IES to come online".

It's a finance system of record. No collector task queues, no SMS, no offer expiry timers, no approve-and-send. Handing that plan to Colin or Intuit asks for something that doesn't exist.

The doc isn't wasted — its field list is right, and so is the instinct "don't build another spreadsheet". What it gets wrong is the home. This plan keeps the data model and re-homes the workflow.

02How we know someone missed

Your question — how does IES know they missed a payment? The honest answer:

It doesn't. Not as an event.

IES has no concept of a "missed payment". It has invoices with due dates and payments applied against them. "Overdue" is something you derive: invoice balance > 0 and due date in the past.

For IES to derive it correctly, two things must already have happened:

  1. The invoice exists in IES with the right due date — pushed by our pipeline
  2. Every payment has been recorded against it

That second one is the problem. Square settles in daily lump deposits, not per-customer payments. Today that lump arrives in QuickBooks as a bank feed line and Elena matches it to invoices by hand. So IES's view of "who missed" is only ever as fresh, and as accurate, as that reconciliation.

Trigger collections off IES and you're triggering off the reconciliation cadence. In collections, where recovery drops hard with every week of delay, that's the wrong clock.

Square knows within seconds — and knows why

The recurring invoice flips to failed the moment the card declines, carrying the decline reason. report_missed_payments.js already reads exactly this, every day, across all six cities.

The decline reason is not a detail — it's the first fork in the road

These are three completely different problems wearing the same coat:

Square saysWhat it actually isRight response
Expired / replaced cardAn admin problem. They never chose to stop paying."Update your card" link. Should never reach a human, let alone a discount.
Insufficient fundsA timing problem. Usually pays on retry.Retry on a smarter date, gentle nudge.
Lost / stolen / do not honourA genuine collections problem.Enter the escalation ladder.

IES cannot tell these apart — it only ever sees an unpaid invoice. Square can. Sorting the expired cards out at the top is probably the single biggest recovery win here, and it costs us nothing but a link.

03Square or IES — the split

It isn't either/or. They answer different questions, and the workflow needs both:

QuestionAnswer fromWhy
Did a payment fail, and why?SquareReal time, with the decline reason. IES has no concept of the event.
Did money land?SquareSame day. IES confirms later, after reconciliation.
How many months behind?SquareMiss streaks already computed in report_zombie_accounts.js.
What's the total owed?IESCarries write-offs, reductions, refunds and anything not billed through Square.
What have we discounted?IESA reduction is a write-off — the books have to hold it.

The rule

Square is the event source. IES is the balance source. The portal listens to Square to decide when to act, and reads IES to decide how much to ask for.

And it goes back the other way

Worth flagging early because it's an Elena conversation, not a developer one: when Caet gives 50% off, the books have to carry the write-off. Square only ever sees the reduced amount landing — it has no idea the rest was forgiven. Today that's tracked in write-off columns on the Google ledger (ledger_config.json has one per year). In IES it becomes a credit memo or write-off entry, and the portal should be what triggers it, so the discount never has to be re-keyed.

Until IES is live

Balance comes from Square (outstanding recurring invoices) plus the CRM's package price. That's enough to run the whole ladder and make reduction offers. When IES lands it becomes the authority, shown against the Square figure with any disagreement flagged. Nothing waits on the migration.

04Retiring the debt ledger

The history is safe — it's all going into IES

That settles the biggest question hanging over this. Every write-off, reduced sale and refund decision back to 2023 lands in IES, so the audit trail survives the sheet. The ledger isn't being deleted, it's being superseded — it just stops being useful once the same information lives somewhere queryable.

So the problem isn't where does the history go. It's what has to be true on the day it stops being maintained — because the sheet is currently doing live work, not just holding records.

What the ledger does today, and who takes over each job

JobTakes overReady?
Historical write-offs, reduced sales, refundsIESMIGRATING
Current balance per debtorIESNEEDS IES LIVE
Month-by-month payment gridSquare (already has it)HAVE IT
Caet's reminder / offer trackingThe portalBUILD
Telling staff what someone owesIES → CRM pushDOESN'T EXIST

The last row is the one that bites

Today, someone who needs to know what a customer owes looks at the ledger. When it goes, IES holds the truth — but nobody works in IES. Caet works in the CRM. The collectors work in the CRM. If the balance doesn't get pushed across, the sheet's real job just quietly stops being done, and people start quoting numbers from memory or from Square, which doesn't know about any of the reductions.

The IES → CRM push isn't a nice-to-have on the side. It's the thing that replaces the ledger's day job.

Where each leg stands

LegTodayNeeded
Square → ledgerBUILT scripts/leads/ledger_sync.js pulls Square daily, matches sheet rows, writes amounts and generates a CRM CSVRepoint at IES instead of the sheet
Square → IESMANUAL lump settlements matched by hand in the Banking tabAutomate — this is what kills the reconciliation lag in section 2
IES → CRMDOESN'T EXISTThe genuinely new piece — and the ledger's actual replacement
Portal → IESDOESN'T EXISTReductions post as write-offs, or we recreate the same gap somewhere new

The good news is that the first leg is already built. ledger_sync.js does Square → ledger → CRM CSV today, so this isn't inventing a path — it's repointing it at IES and making the return leg real.

The order this has to happen in

  1. IES live, history loaded
  2. Square → IES automated, so balances stop depending on manual matching
  3. IES → CRM push built — staff see the true balance where they actually work
  4. Parallel run. Ledger and IES side by side, every disagreement chased down
  5. Then stop maintaining the sheet

The rule worth holding to

The ledger stops being maintained when it and IES have agreed for a few weeks running — not on a chosen date. Two measures disagreeing is exactly how we've caught bad numbers before. Pick a date instead and any migration gap surfaces after the sheet has gone cold, with nothing left to check against.

It's seven sheets, not one

One ledger per market. The Square half is a non-issue — all six token sets and every recurring location are already configured in city_config.json, and ledger_sync.js already loops cities. The sheet half is the work, because ledger_config.json is currently written for New York alone.

The failure mode to design out: seven sheets that look identical but aren't

The New York config isn't generic — it's hard-coded to that sheet's exact geometry:

ref D · name C · sales E · balance Q · months from AE · write-offs U/V/W (2024/25/26) · reduced sales X/Y/Z/AA (2023–26) · refunds AB/AC/AD

If six other sheets grew up separately — a column inserted here, a different year range there, a different tab name — then reading them with the wrong column letters won't throw an error. It will return a number. Just the wrong one. Write-offs read from the refunds column produce balances that look entirely plausible and are quietly wrong, on the very data we're migrating as the permanent record.

That's the one thing here that could corrupt IES rather than merely delay it.

What that adds to the plan

  1. Audit all seven sheets first — read the headers, confirm what every column actually holds, and write a per-city block in ledger_config.json. Cheap, and it's the step that de-risks everything after it.
  2. Reconcile each city against Square before migrating — sheet balance vs Square payments per customer. Cities that agree are safe to move; cities that don't get looked at while the sheet is still live and someone still remembers why.
  3. Parallel run per city, not globally. Seven separate sign-offs. A city can retire its sheet as soon as its own numbers agree, rather than all seven waiting on the worst one.

The audit needs the seven spreadsheet IDs, and each sheet shared with studio1-automation@studio1-automation.iam.gserviceaccount.com — the service account key is already in the repo and working.

05The debt collection spine

Agreed — and "finance spine" was the wrong name for it

You're right. IES is the finance spine. General ledger, balances, invoices, write-offs, refunds, the P&L — that's its job and it does it properly. We shouldn't be building a second one, and this plan shouldn't have implied it.

What we're building is the layer above it: the debt collection spine. Your name for it is the accurate one.

The distinction that matters for the design

IES is authoritative about money but it is not operational. It has no events, no triggers, no queues, no comms — and it's reconciliation-lagged by design. It can tell you what someone owes. It can't tell you that a card declined this morning, whose job it is to chase, what's already been tried, or what happens tomorrow if nobody replies.

LayerOwnsCharacter
IES — finance spineBalances, invoices, write-offs, reductions, refunds, the booksAuthoritative. Slow. Nobody works in it.
Collection spine — this buildMiss events, ladder stage, comms history, offers, arrangements, Monterey handoverReal-time. Event-driven. Where the work happens.
CRMThe client, the package, who's assignedWhere staff actually sit.
SquarePayments, declines and reasonsThe event source feeding both.

So the ladder, the offers, the arrangements and the Monterey handover all belong on the collection spine, reading balances from IES rather than being built inside it.

The questions that prove they belong together

Each of these sits across two systems, so today nobody has to answer them — and if collections gets built in isolation first, they get answered by accident, in code, and discovered later:

  • A payment lands after we've written the balance off. Does it reopen the account, or is it a windfall against a closed one?
  • A chargeback on an account we already discounted. Does it reverse the reduction, or does the write-off stand?
  • A customer at stage 4 starts paying again mid-offer. Does the offer survive, and what's owed once it expires?

That's what "just doing this one component is missing a trick" looks like in practice.

What rides on the collection spine

ConsumerNeeds from the spineStatus today
The ladder + discount offersMiss events, stage, comms, offers, write-backThis document
Caet's queueEverything above, filtered to stage 4One cog, near the end — sections 6 and 8
Payment arrangementsTerms, missed-instalment detection, re-entry to the ladderBUILD
Missed paymentsSquare declines + reasonsRUNNING
Refunds & chargebacksAdjustments against the right customerRUNNING — reported, not reconciled back
Balances into the CRMShared plumbing — IES → CRMDOESN'T EXIST — needed by everyone, collections is just its biggest user

Recommendation

Skeleton the collection spine for all of it, implement the ladder first.

And Phase 1 — the payment watch — still ships now, because it reads Square directly and depends on none of this.

Settled
This is replace the ledger and build the debt collection spine, with the ladder as its first consumer and Caet's queue as one cog near the end — not "automate Caet's spreadsheet".

06The escalation ladder

Your point — "this would be the new way we do all collections, and if people don't answer after putting them into a workflow they progress along the path to get to Caet" — is the biggest change from v1 of this plan, and it's a better design.

Caet stops being the front door and becomes the last human stage. Every missed payment enters one path. Most of it never reaches a person.

Stage 0
Day 0
Automatic · Square

Miss detected and sorted

Payment fails. Decline reason read. Expired cards split off immediately to a card-update flow — they're not collections. Everything else enters the ladder.

Stage 1
Days 0–7
Automatic · GHL

Self-serve recovery — two-way text

15% off to settle now, then a forward check on the next payment: is it going to be OK, or would they like to speak to someone. Replies are handled automatically. This is where most recoverable money comes back, and where it's cheapest. Detailed in section 5.

Stage 2
Days 7–21
Automatic · GHL

Persistent chase

Escalating sequence, firmer each time, still automated. A call task can be raised here without the account leaving the workflow.

Stage 3
Day 21+
Human · collections team

Collector calls

Ignored everything automated. Assigned to one of the 8 collectors for live contact. Payment arrangements can be set up here.

Stage 4
Day 45+
Human · Caet

Reduction offer

The portal in this document. Only accounts that ignored every stage above. Offer, follow-up, expiry, final notice — with the full contact history already attached, so she can see everything that's been tried.

Stage 5
On expiry
External

Monterey

Offer expired, no payment, one business day's grace. Exported, stamped, handed over.

Exit
Any time
Automatic · Square

Payment lands → drop out

At any stage. Account leaves the ladder, sequences stop, status updates. If it had already gone to Monterey, that's a red alert — pull it back before we pay a fee on money we collected ourselves.

Why this is worth more than automating Caet's spreadsheet

  • A reduction offer is the most expensive tool we have — so it should be last. Right now accounts reach Caet with no documented chase history, which means we may be discounting people who'd have paid at stage 1 to a text message.
  • Her queue gets small and pre-qualified. Every account arriving has a full record of what's been tried, so she's not opening cold.
  • The volume is only reachable by automation. 2,614 live accounts, ~$542k a month billed and never collected. Stages 1–2 are the only way to touch that.
  • Expired cards never become debt. They get fixed at stage 0.
Decision needed
The day counts above (7 / 21 / 45) are my placeholders, and the stage-3 step assumes the wider collections team. Both need your call — they set how much lands on Caet's desk.

07The stage 1 conversation

Your call: make it a two-way text, offer a small discount to pay now, then check whether the next payment is going to be OK or whether they'd like to speak to someone. That last part is the best idea in this plan — it turns a collections touch into a retention touch.

Most of this already exists

  • modules/convo-intel/engine.js — AI conversation engine, built for ICONIC. Reads a transcript, works out where the conversation is, replies.
  • /api/healing/webhook/ghl in serve_reports.js — already receives and processes inbound GHL messages.
  • /pay — the payment portal is live. Needs a discount parameter added so the link can carry the reduced amount.

So this is largely assembly, not a new build.

How it runs

Day 1 · card declined, reason: insufficient funds
Hi Sarah — Studio 1 here. This month's payment of $180 didn't go through. If you can settle it today we'll take 15% off, so $153. Here's the link: pay.studio1.com/s/4XK2

This one's a one-off courtesy. Reply STOP to opt out.
just paid it thanks
Square confirms $153 · account drops out of the ladder
Got it, thanks Sarah — that's cleared. Quick one: your next payment is $180 on 15 Aug. Is that going to be OK?

Reply YES, or HELP and someone will call you to sort something that works.
HELP
→ routed to the collections team for a payment arrangement · exits the ladder

That forward-looking question is the part worth protecting. Someone who replies HELP is a payment-arrangement candidate, not a debtor — they've self-identified before missing anything. Catching them there keeps the account alive instead of walking it down to Monterey.

What every reply does

Pays

Detected from Square, not from what they say. Exits the ladder, confirmation sent, next-payment check fires.

"Can't afford it" / "lost my job" / HELP

Exits the ladder into a payment arrangement, task raised for the collections team. Never gets pushed further down the path while an arrangement is being set up.

"My card changed"

Card-update link. No discount — see the guardrail below.

"I already paid"

Checked against Square automatically. Found → apologise and close. Not found → straight to a human to verify, never argued with by a bot.

"I want to cancel" / complaint / anything angry

Hard stop — human immediately. No automated reply handles a cancellation or a complaint.

STOP

Opt-out honoured instantly, no further texts. Account continues down the ladder by email and phone only.

No reply

Stage 2.

The guardrail this needs — a pay-now discount can train people to miss

15% at day 1 is far cheaper than 50–75% at day 45, and that arithmetic is why this is a good idea. But on a recurring base it has a failure mode worth designing out up front: if a missed payment reliably produces 15% off, some customers will learn to let the card decline every month. A one-time cost quietly becomes a permanent 15% price cut on that account — and it travels by word of mouth.

Five rules that keep the upside without the trap:

  1. Never on the expired-card path. Those people were going to pay anyway — the discount is pure margin given away. This falls straight out of the decline-reason fork in section 2.
  2. Once per customer per rolling 12 months, enforced by the portal, not by anyone remembering.
  3. Say it's a one-off in the message itself — so a second miss isn't an argument.
  4. First or second miss only. Someone four months behind needs the stage 4 conversation, not 15% off one invoice.
  5. Watch the repeat-miss rate among people who took the discount versus those who didn't. If it climbs, the discount is training behaviour — that's a manager-view metric from day one.

Deterministic replies, not a chatbot that improvises about money

The AI should classify the reply and pick from approved copy — not generate free text about what someone owes. Anything it can't confidently classify goes to a human. That's the shadow-first pattern convo-intel already uses: run it in draft mode for the first couple of weeks, review what it would have sent, then let it send once the branches look right.

Two practical things before a single text goes out

  • Quiet hours, per city. We bill across Central and Eastern. Sends must be scheduled in the customer's local time, not the server's — a collections text at 7am reads very differently from one at 10am.
  • Opt-out and consent. STOP handling is non-negotiable, and worth a quick check that the billing consent covers service texts of this kind. We're collecting our own debt rather than acting as a third-party collector, which is a different position from Monterey's — but the texting rules apply either way.
Decision needed
Confirm 15%, and whether it applies to the whole missed invoice or the whole arrears balance. And whether "speak to someone" raises a call task for the collections team or books a slot directly.

08What changes for Caet

Today — every box manual

Grab account from CRM Work out reduction Send email + text Type into spreadsheet Wait Follow-up Final notice Mark collections Monterey report

The spreadsheet in the middle is quietly doing four jobs: reminder system, payment tracker, reduction tracker, reporting tool. Three of those four automate away entirely from data we already hold. The fourth — deciding the offer — stays hers, with the numbers put in front of her.

After — three decisions and a button

Account arrives at stage 4 with full history Caet approves or changes the offer Sent, dated, tracked, chased Caet clicks Export

The gap she's most worried about

"I have no current method of being notified of any payments being made to these accounts, as their balance remains open on the finance."

Two live failure modes: someone pays after being marked for collections and Monterey chases them anyway (we pay a fee on money we already collected); or someone part-pays a reduced offer, nobody updates the ledger, and a paying client gets a final notice.

Both close with a watch on the Square feed that already runs daily. It needs nothing from IES, nothing from Colin, and nothing from GHL — which is why it's Phase 1.

09Where every field comes from

Nothing gets typed twice. Every field has exactly one owner.

FieldOwnerHow we get itStatus
Client name, phone, email, addressCRMColin's account feedASK COLIN
Assigned collectorCRMColin's account feedASK COLIN
Package priceCRMColin's account feedASK COLIN
Payment failed + decline reasonSquarereport_missed_payments.jsHAVE IT
Payments receivedSquareDaily pull, all 6 citiesHAVE IT
Months missed, amount outstandingSquarereport_zombie_accounts.jsHAVE IT
Authoritative balance owedIESIntuit API, per customerIES NOT LIVE
Write-off / reduction on the booksIESPortal triggers credit memoIES NOT LIVE
Ladder stage + collection statusPortalSupabaseBUILD
Offer amount + % reductionPortalRules engine + Caet overrideBUILD
Offer, follow-up and expiry datesPortalAuto-set from offer dateBUILD
Payment arrangement termsPortalEntered once by collectorBUILD
Communication historyPortalLogged on every GHL send, all stagesBUILD
Date sent to MontereyPortalStamped on exportBUILD

Status vocabulary

In Workflow (1–2) With Collector (3) Reduction Offered Follow-Up Due Final Notice Sent Payment Arrangement Paid in Full Ready for Collections Sent to Monterey Closed

10The portal, screen by screen

Screen 1 — Today's Queue

Replaces "check the spreadsheet". Built nightly, sorted by urgency, nothing to search for.

reports.iconicbyai.com/collections — Today · Fri 31 Jul
Adams, R.PAID $420 — marked for collections 3 days ago · pull back from Monterey
Brown, T.Arrangement broken — missed $50 weekly, 2nd miss
Smith, J.Offer expires today — final notice ready to send
Jones, M.Follow-up due — email + text drafted
Carter, L.Paid in full — offer accepted, closing automatically
Diaz, A.Arrived from stage 3 · 6 contacts, no reply · offer suggested

Red first, always: money landing where it shouldn't outranks routine follow-ups. That ordering is the point of the screen.

Screen 2 — Account view

Screen 3 — Offer builder

Portal suggests offer Caet reviews / overrides Clicks Send GHL sends email + text Dates set, status flips, logged

Balance, package price, suggested reduction, resulting figure. She can change it. Email and text come pre-written with the amount, the expiry date and the payment link already in them. One click sends both, and the follow-up date, expiry date and status set themselves — that's the spreadsheet row, written for her.

Screen 4 — Monterey export

One button. CSV with exactly what Monterey needs — name, balance, offer made, expiry, date sent to collections, phone, email, address. Every account on it gets stamped Sent to Monterey with the date, so nothing can go twice.

Plus: a manager view

Nearly free once the data exists, and it's what makes this worth doing at the business level: recovery rate by ladder stage (how much comes back at stage 1 vs stage 4 — that number tells you whether the discounts are even necessary), open offers by value, acceptance rate by reduction tier, monthly discount exposure, Monterey recovery vs handover. Nobody can answer any of that today.

11Reduction offer rules

You said: "we would just give an option based on the balance — say 50% or 75% off." That becomes a small table the portal reads. Placeholders — you set the real numbers.

Balance owedStandard offerEscalation on expiryApproval
Under $50050% off75% offCaet
$500 – $1,50050% off75% offCaet
$1,500 – $3,00050% off75% offManager for 75%
Over $3,00050% offManager, both tiers

12The clock — what fires when

WhenWhat happensWho acts
Square reports a failed paymentDecline reason read. Expired card → card-update flow. Otherwise → stage 1Portal
Stages 1–2Automated text/email sequences, charge retriesGHL, automatic
No response by stage 3 thresholdAssigned to a collector for callsPortal assigns
No response by stage 4 thresholdLands in Caet's queue, offer suggested, history attachedPortal
Offer day 0Offer email + text sent. Follow-up and expiry dates setCaet clicks Send
Follow-up date (default +7)Follow-up drafted, surfaces in queueCaet clicks Send
Expiry date (default +14)Final notice email + text draftedCaet clicks Send
Expiry + 1 business day, no paymentStatus → Ready for CollectionsPortal, automatic
Monterey export runStatus → Sent to Monterey, date stampedCaet clicks Export
Any payment, any stageDrops out of the ladder, sequences stop. If already at Monterey → red alertPortal, automatic
Balance hits zeroStatus → Paid in Full, account closesPortal, automatic
Arrangement payment missedFlagged, reminder drafted, follow-up rescheduledPortal drafts, human sends

Stages 1–2 send automatically; stage 4 never does. Routine dunning is safe to automate — a reduction offer changes what someone owes, so it stays draft-and-approve, per your call.

13Integrations

SystemWhat we needWhere we stand
SquareFailed payments + decline reasons + payments, all cities HAVE IT Running daily. Both reports already built on it.
GHLStage 1–2 sequences; send Caet's offer email + text; log every send HAVE IT Live on two sub-accounts. Needs a collections sender + number decided.
Inbound SMS + AI repliesReceive replies, classify them, answer or escalate MOSTLY HAVE IT modules/convo-intel/engine.js is the conversation engine; /api/healing/webhook/ghl already processes inbound messages. Needs collections branches + ANTHROPIC_API_KEY.
/pay portalCarry the discounted amount on the pay-now link SMALL BUILD Route is live (Reports/pay.html) — needs a discount parameter and one-time-use handling.
IES (Intuit)Read balances; write reductions as write-offs NOT LIVE But the OAuth + API client is already written (scripts/qb/qb_auth.js) and tested against the Intuit sandbox — a realm swap and a query, not a new build.
CRM (Colin)Account feed; status write-back TWO ASKS See below.
SupabaseStages, offers, dates, comms log HAVE IT Already the persistence layer for the reporting stack.

Why the portal lives on our stack

A sequencing argument, not a vendor preference. IES isn't live and its date is TBD; the CRM is Colin's roadmap and Colin's timeline. If the workflow lives in either, nothing ships until someone else's project lands. On our stack, Phase 1 ships now against Square alone, and IES and the CRM plug into something already working. Caet still gets one screen — she just doesn't wait for a migration to get it.

14Build phases

Phase 1 · no dependencies · ships first

The payment watch

Accounts marked for collections are watched against the Square feed. Payment lands → Caet is told the same day. Also catches part-payments against live reduction offers.

Needs nothing from IES, Colin or GHL. It's the thing she's actually frightened of losing with the ledger gone, and it runs on feeds that already fire daily.

Phase 2 · needs GHL sequences + convo branches

Stages 0–2 — the automated ladder and the conversation

Miss detection with decline-reason sorting, expired-card flow split off, the two-way text with the 15% pay-now offer and the next-payment check, reply classification and escalation, discount eligibility rules, quiet-hours scheduling. This is where the volume gets handled and the recovery economics change — and it reduces what reaches every human downstream.

Ship it in shadow mode first: it drafts every reply for a fortnight, nobody receives them, and we check the branches before letting it send.

Phase 3 · needs Colin's account feed

Stages 3–5 — queue, offers, Monterey

Collector assignment, Caet's queue with full ladder history, offer builder on the rules table, auto-flip to Ready for Collections, one-click Monterey CSV, arrangement tracking. The spreadsheet dies at the end of this phase.

Phase 4 · when IES goes live

IES as balance truth + write-back

Balance switches to IES, shown against Square with disagreements flagged. Reductions post back as write-offs. Manager dashboard: recovery by stage, discount exposure, Monterey performance.

No dates until you've picked the platform and Colin's given a timeline — I'd rather size these once than guess.

15What we need from Colin

The join key is settled RESOLVED

Confirmed the systems will share an ID. That removes the one genuine technical risk in v1 of this plan — no fuzzy name-and-phone matching, so CRM ↔ Square ↔ IES joins cleanly and the balances can be trusted. We do need to know which field carries it, but that's a question, not a problem.

1. Read: accounts assigned to a collector REQUIRED

Per account: client name, phone, email, address, package price, assigned collector, and the shared ID. A nightly CSV drop is fine — it doesn't need to be a live API.

2. Write: collection status back to the CRM NICE TO HAVE

So anyone opening the account in the CRM sees the current ladder stage rather than a stale record. Without it the portal still works — the CRM just stays read-only.

16Decisions still open

Settled
Scope: replace the ledger and build the debt collection spine, ladder first, Caet's queue one cog near the end · IES is the finance spine — we don't rebuild it · ledger history migrates into IES, nothing lost · shared ID across systems · Square as event source, IES as balance source · the ladder sequence · stage 1 is a two-way text with a pay-now discount and a next-payment check · portal drafts and Caet approves, nothing auto-sends a reduction offer.
The 15% pay-now offer
Confirm the number, and whether it comes off the missed invoice or the whole arrears balance — quite different amounts once someone is a few months behind. Plus the eligibility rules in section 5 (once per 12 months, never on expired cards, first two misses only).
"Speak to someone"
Does HELP raise a call task for the collections team, or book a slot directly in someone's diary?
Platform
Still open. This plan assumes our stack for the sequencing reasons in section 10 — but Phase 1 should ship our side regardless, because it's buildable now and it's the bit that's bleeding.
Ladder timings and stage 3
The 7 / 21 / 45 day thresholds, and whether stage 3 is the wider collections team or whether accounts go straight from the automated workflow to Caet. This decides her workload.
Reduction bands and the floor
The 50% / 75% split, the balance bands, the minimum % of package price, who approves the deeper tier.
Follow-up and expiry intervals
Day 7 and day 14 are placeholders. Caet will know the real ones.
Monterey's actual file format
If they have a required layout, match it exactly rather than make them re-key it.
GHL sender identity for collections
Which sub-account, which from-address, which number. Collections texts from an unfamiliar number get ignored, and a shared marketing number risks compliance problems.
Write-off treatment in IES
An Elena question, not a developer one: how reductions should post to the books. Worth asking now so Phase 4 isn't a redesign.

17Risks

RiskHow we handle it
IES date is TBD — plan stalls waiting for itPhases 1–3 don't need IES. Balance comes from Square + CRM meanwhile; IES swaps in at Phase 4.
Triggering off the wrong clockSquare drives the ladder, not IES's reconciled position. Section 2 is the reason.
Automated stages annoy good clientsExpired cards split off before stage 1. Payment at any stage stops every sequence immediately. Tone escalates gradually, not from the first message.
The pay-now discount trains people to missThe main risk in the stage 1 design, and the reason for the five eligibility rules in section 5. Tracked from day one as repeat-miss rate among discount takers vs everyone else — if it climbs, the discount is the cause.
An AI says something wrong about someone's debtIt classifies replies and picks approved copy — it does not compose free text about money. Cancellations, complaints and disputed payments go straight to a human. Shadow mode for the first fortnight.
Texts sent at the wrong hourScheduled in the customer's local time — we bill across Central and Eastern. STOP honoured instantly.
Seven ledgers with drifted column layoutsThe one risk that could corrupt IES rather than delay it — wrong column letters return plausible numbers, not errors. Audit all seven sheets and reconcile each against Square before migrating, per section 4.
Ledger switched off before the portal is readyShip Phase 1 first, and run the spreadsheet in parallel until Phase 3 has been agreeing with it for a couple of weeks.
Reductions drift out of the booksPortal is what triggers the write-off, so the discount is never re-keyed. Needs Elena's sign-off on treatment.
Client PII in a web portalSame gated-key pattern the existing PII reports use, plus a login. No PII in URLs, no-cache on downloads.
A wrong offer goes outNothing auto-sends at stage 4. Portal drafts, Caet approves. Overrides logged.
Double-handling with MontereySent-to-Monterey stamp makes a second send impossible, and the payment watch catches anyone who pays after handover.
Draft v7 for discussion — Studio 1 · 31 July 2026
Sources: Caet's email (30 Jul), Caet ai workflow doc, Neil's direction on the escalation ladder, and what's already running in the Studio 1 reporting stack.