Architecture & AI Roadmap · v2.0

Watchtower AR

Seven AI capabilities layered on top of an existing NetSuite dunning engine. Non-destructive, GDPR-compliant, human-in-the-loop.

Teqva Gruppen Norway East · Azure OpenAI Antire · NetSuite SuiteScript 2.1 7 AI Builds · 5 Phases

System Architecture Map

How seven AI capabilities layer on top of the unchanged dunning engine

Existing (unchanged)
Core AI (Builds 1–3)
New AI (Builds 4–7)
Dashboard
Azure OpenAI
Presentation Layer
🖥️
Watchtower Dashboard
Single Suitelet — the AR team's daily command center. Four panels: Risk Radar, Dunning Queue, Dispute Inbox, Cash Flow Forecast. KPI strip with live aggregates.
Suitelet
🔌
Dashboard Data RESTlet
Serves multiple endpoints: riskQueue, dunningQueue, disputeInbox, cashForecast, channelRec, escalationQueue. Client-side JS fetches on load.
RESTlet
▼ reads custom fields
Core AI Layer — Builds 1–3 PHASE 1
🎯
1 · Tone Engine
Scores customer behavior → picks dunning tone (gentle / neutral / firm / final). Stamps on Customer record before template merge.
User Event
📊
2 · Risk Predictor
Nightly scoring 0–100 for customers with open AR before they enter dunning. Score >75 → proactive call task for AR team.
Map/Reduce
💬
3 · Dispute Classifier
Inbound email → classify (promise/dispute/request/partial/no-intent) → draft Norwegian response → auto-pause on promise-to-pay.
Suitelet POST
Extended AI Layer — Builds 4–7 PHASE 2
4 · Send-Time Optimizer
AI picks optimal day and hour to send each dunning email for maximum open rate and payment likelihood.
Map/Reduce
💰
5 · Cash Flow Predictor
Forecasts when each overdue payment will likely arrive, feeding a live AR cash flow timeline on the dashboard.
Map/Reduce
📡
6 · Channel Optimizer
Recommends best communication channel per customer: email, print, phone, SMS — based on historical response patterns.
User Event
⚖️
7 · Escalation Advisor
At Level 3+, AI recommends: escalate to collection, extend deadline, or propose settlement — with reasoning and confidence score.
User Event
▼ anonymized signals ↕ structured JSON
Azure OpenAI — Norway East
☁️
Azure OpenAI (GPT-4o)
Norway East region. EU data residency. Receives only anonymized behavioral signals. Returns structured JSON. Never sees PII. Low temperature (0.2) for consistency.
GDPR Compliant
📋
AI Audit Log
Every API call logged: anonymized payload, response, script ID, version, timestamp, success/fail. No PII. Immutable after creation.
Custom Record
▼ integrates with existing flow
Existing Dunning Engine UNCHANGED
📄
Invoice UE
rc-norway-dunning-ue.js — Creates L0 dunning record on invoice creation
User Event
⚙️
Dunning Processor
rc-norway-dunning-mr.js — Loads procedures, searches records, groups, creates letters
Map/Reduce
📤
Letter Sender
rc-norway-dunning-letter-send-mr.js — Sends via email or print, marks processed
Map/Reduce
📚
Core Libraries
rc-norway-lib.js (59K) + rc-norway-def-lib.js — All dunning operations
Library
▼ persisted on
NetSuite Data Layer
Dunning Record Dunning Letter Dunning Procedure Level Map Configuration Dunning Status Dunning Level AI Audit Log ✦

Existing Dunning Flow

The current system — all unchanged. AI layer is additive only.

01
Invoice Createdrc-norway-dunning-ue.js (afterSubmit) checks if dunning is enabled → verifies procedure exists for subsidiary → creates Dunning Record at Level 0 / "Awaiting Payment" → links procedure. Fallback: uses default procedure from Configuration record.
02
Scheduled Processingrc-norway-dunning-mr.js (Map/Reduce, daily). getInputData loads all active procedures. map runs each procedure's saved search to find eligible records (days overdue, subsidiary, not paused, not in debt collection). reduce groups by customer | dunningDueDate | invoiceToEmail → creates one letter per group.
03
Letter CreatedcreateDunningLetterRecord() in rc-norway-lib.js. Sets customer, subsidiary, procedure, level, fee. Then updateDunningRecords(): locks current record, copies to new record at next level/status (via Level Map), marks old one inactive.
04
Letter Sendingrc-norway-dunning-letter-send-mr.js (Map/Reduce). Finds unsent letters. EMAIL: merges template → renders PDF → sends with optional attachments (letter + merged transaction PDFs). PRINT: renders PDF → saves to procedure's folder. Then markRecordsAsProcessed() sets sent flags/dates.
05
Level Progression → Next daily run picks up advanced records and matches against higher-level procedures. L0→L1→L2→L3→L4→L5 via customrecord_rcs_dunning_level_map. Terminal states: "Paid in Full" or "Sent for Debt Collection".
Norwegian Compliance Built In
Level 1 = Betalingspåminnelse (payment reminder, 14 days) · Level 2 = Inkassovarsel (collection warning, 28 days, per Inkassoloven) · Fee: NOK 70 per notice · Subsidiary-specific procedures support multi-entity compliance.

Core AI Builds 1–3

The original three capabilities from the Watchtower spec — proven patterns, immediate value

01

Tone Personalization Engine

Every customer gets the right tone — not the same letter

Injection point: User Event (beforeSubmit) on Dunning Letter record — fires before letter creation in existing Step ③
1
Pull customer AR signals: days overdue, late-pay rate, invoice count, prior escalations, amount bucket
2
anonymizer.js strips all PII → behavioral signal payload only
3
azureClient.js → Azure returns { tone: "firm", variant: "NO_B2B_45D_FIRM", reasoning: "..." }
4
Stamp custentity_ai_dunning_tone + custentity_ai_dunning_variant on Customer record
5
Existing email template reads tone → selects variant. auditLogger.js records the interaction.
📤 Anonymized Payload
"segment""B2B"
"country""NO"
"daysOverdue"45
"amountBucket""HIGH"
"latePayRate"0.33
"invoiceCount"3
"priorEscalations"1
"dunningStep"3
🏷️ Custom Fields — Customer
custentity_ai_dunning_toneList/Record
custentity_ai_dunning_variantFree-form Text
custentity_ai_last_scored_dtDate/Time
custentity_ai_scoring_reasoningLong Text
Tones: gentle · neutral · firm · final
02

Payment Risk Predictor

Score customers before they're overdue — intervene proactively

Standalone: Nightly Map/Reduce at 02:00 — independent of existing dunning flow
1
getInputData: SuiteQL pulls customers with open AR NOT yet in dunning
2
map: Build anonymized signal (segment, country, days-to-due, amount bucket, late-pay history)
3
reduce: Batch → Azure → score 0–100. Stamp custentity_ai_risk_score + flag on Customer.
4
Score >75: check existing open Task → if none, create proactive call Task for AR owner
5
summarize: Log totals, reschedule via N/task if governance exhausted
🏷️ Custom Fields — Customer
custentity_ai_risk_scoreInteger (0–100)
custentity_ai_risk_flagList: NONE|LOW|MED|HIGH|CRIT
custentity_ai_risk_scored_dtDate/Time
custentity_ai_risk_reasonFree-form Text
⚡ Task Creation
Trigger: Score > 75
Dedup: Existing open Task check
Assigned to: Customer's AR owner
Due: Today + 1 business day
Governance: getRemainingUsage() < 1000 → reschedule
03

Dispute Classification + Draft Response

Classify inbound replies, draft Norwegian responses, auto-act on promises

1
Inbound email webhook → Suitelet POST endpoint
2
sanitizer.js strips HTML, truncates 500 chars, wraps in delimiters (prompt injection defense)
3
azureClient.js → classify + draft Norwegian response
4
Stamp custentity_ai_dispute_class, store draft as Note on Customer
5
promise_to_pay → stamp date, pause dunning. dispute_invoice → create Support Case.
6
Watchtower Dispute Inbox surfaces draft for AR team review/edit/approve
📋 Classifications
promise_to_payCommits to date → pause dunning
dispute_invoiceDisputes → Support Case
request_copyWants invoice copy → auto-attach
partial_paymentOffers partial → flag for review
no_intentNo commitment → escalate flag
🏷️ Custom Fields — Customer
custentity_ai_dispute_classList
custentity_ai_promise_dateDate
custentity_ai_draft_responseLong Text
custentity_ai_reply_received_dtDate/Time

New AI Builds 4–7

Four additional capabilities that multiply the value of the core three

04

Send-Time Optimizer

Send each dunning email at the moment it's most likely to be opened and acted on

Problem: All dunning emails currently send at the same time (when the scheduled script runs). A B2B finance director reads email at 08:00. A small business owner checks at 20:00. Sending at the wrong time means burial in the inbox.
1
Signal collection: Track email open timestamps (if available via email tracking), historical payment times, customer timezone, business segment (B2B vs B2C), company size bucket
2
AI scoring: Azure receives anonymized engagement signals → returns optimal send window: { "sendDay": "Tuesday", "sendHour": 8, "confidence": 0.82, "reasoning": "B2B finance, Norway, opens Mon-Wed AM" }
3
Execution: Instead of immediate send, stamps custentity_ai_optimal_send_time on the Dunning Letter. The send MR script respects this timestamp — holds letters until their optimal window.
4
Learning loop: Weekly batch compares predicted vs actual open/payment rates. Feeds results back as signal for future scoring.
📤 Anonymized Payload
"segment""B2B"
"timezone""CET"
"historicalOpenHours"[8,9,14]
"historicalPayDays"["Mon","Wed"]
"companySizeBucket""MID"
"dunningStep"2
🏷️ Custom Fields
custrecord_ai_optimal_send_dtDate/Time (on Letter)
custentity_ai_send_preferenceFree-form Text
custentity_ai_open_ratePercent
Integration: Modifies send MR to check custrecord_ai_optimal_send_dt before dispatching. Letters held until their optimal window.
05

Cash Flow Predictor

Know when overdue payments will actually arrive — not just that they're late

Problem: The AR team knows NOK 2.4M is overdue but has no idea when it'll arrive. Finance asks "when can we expect these payments?" and the answer is a shrug. This build turns that shrug into a forecast.
1
Signal collection: For each overdue customer: historical average days-to-pay, payment pattern (pays on specific day of month?), current dunning level, dispute status, risk score from Build 2, amount bucket, seasonal patterns
2
AI prediction: Azure receives batch of anonymized customer signals → returns per-customer: { "predictedPayDate": "+12d", "confidence": 0.71, "expectedAmount": "FULL", "reasoning": "Historically pays 10-15d after Level 2" }
3
Dashboard panel: Feeds a live cash flow timeline on Watchtower: "Expected this week: NOK 450K · Next week: NOK 890K · 30-day forecast: NOK 1.8M" with confidence bands
4
Accuracy tracking: Compare predictions vs actual payment dates. Log accuracy to AI audit record. Surface prediction accuracy % on dashboard as a trust signal.
🏷️ Custom Fields — Customer
custentity_ai_predicted_pay_dtDate
custentity_ai_pay_confidencePercent
custentity_ai_avg_days_to_payInteger
custentity_ai_pay_patternFree-form Text
📊 Dashboard: Cash Flow Panel
This Week: NOK amount with confidence band
Next Week: NOK amount with confidence band
30-Day Forecast: Cumulative timeline chart
Accuracy: "Last 30 days: 78% within ±3 days"
Drill-down: Click any bar → see individual customer predictions
06

Communication Channel Optimizer

Right message, right channel — email, print, phone, or SMS

Problem: The system sends email to everyone, print to a few. But some customers never open emails — they respond to phone calls. Others are overseas and only respond to print. The current custentity_rcn_cust_dun_send_method field is manually set and rarely updated.
1
Signal collection: Email open/bounce history, previous dunning response method (replied by email? called in?), customer segment, country, dunning level (higher levels may warrant phone), amount at risk
2
AI recommendation: { "channel": "PHONE", "confidence": 0.88, "reasoning": "3 emails ignored, high-value, historically responds to calls", "fallback": "PRINT" }
3
Action: Stamps recommendation on letter/customer. If PHONE: creates Call Task instead of sending letter. If SMS: integrates with SMS gateway (future). Dashboard shows channel recommendation per customer for AR team to confirm.
🏷️ Custom Fields
custentity_ai_channel_recList: EMAIL|PRINT|PHONE|SMS
custentity_ai_channel_confidencePercent
custentity_ai_channel_reasoningFree-form Text
custentity_ai_email_engage_scoreInteger (0–100)
🔗 Integration with Existing
Existing field: custentity_rcn_cust_dun_send_method already controls email vs print. AI recommendation can auto-update this field (with AR approval) or surface as suggestion only.

PHONE channel: Creates Activity (Phone Call) task instead of sending letter — AR team sees it in Watchtower Risk Radar alongside call tasks from Build 2.
07

Escalation Advisor

At the critical moment — escalate, extend, or settle?

Problem: At Level 3+, the system automatically escalates to debt collection. But some customers are worth keeping — a rigid escalation path loses valuable relationships. Others should have been escalated earlier. The decision is currently binary and unintelligent.
1
Injection point: User Event on Dunning Record — fires when level reaches 3 or higher (before escalation)
2
Signals: Customer lifetime value bucket, payment history length, current dispute status, industry, relationship age, total outstanding, number of active projects/contracts, risk score from Build 2
3
AI recommendation: { "action": "EXTEND", "extendDays": 14, "reasoning": "Long-term customer, first late episode, active contract", "settlementOffer": null, "confidence": 0.85 }
4
Three possible actions:
ESCALATE → Proceed with debt collection referral (existing flow)
EXTEND → Pause dunning for N days, create follow-up Task
SETTLE → Generate settlement offer draft (e.g., "pay 85% within 7 days"), create approval workflow
5
Dashboard: Watchtower shows "Escalation Queue" — AR team reviews AI recommendation + reasoning, clicks to approve action. No automatic escalation without human approval.
🏷️ Custom Fields — Customer
custentity_ai_escalation_recList: ESCALATE|EXTEND|SETTLE
custentity_ai_escalation_confPercent
custentity_ai_settle_offerLong Text
custentity_ai_escalation_reasonFree-form Text
custentity_ai_clv_bucketList: LOW|MED|HIGH|STRATEGIC
💡 Settlement Offer Logic
When AI recommends SETTLE, it generates a structured offer:

Discount: 5–20% based on amount, age, and likelihood of full recovery
Deadline: 7–14 day window for acceptance
Draft: Norwegian email text stored in custentity_ai_settle_offer
Approval: AR manager reviews in Watchtower → approve → system sends offer email

This is potentially the highest-ROI capability — recovering 85% of a debt that would otherwise go to a collection agency (which takes 25–50% commission) is a massive win.

Impact × Effort Matrix

All seven builds ranked by business impact, technical effort, and implementation priority

# Build Impact Effort Dependencies Priority New Fields
1 Tone Personalization
Right tone per customer
Phase 1 libs only CORE 4 on Customer
2 Risk Predictor
Score before overdue
Phase 1 libs only CORE 4 on Customer
3 Dispute Classifier
Auto-classify + draft reply
Phase 1 libs + email webhook CORE 4 on Customer
4 Send-Time Optimizer
Optimal delivery timing
Build 1 + email tracking HIGH 3 (1 Letter, 2 Customer)
5 Cash Flow Predictor
Forecast payment timing
Build 2 (risk scores feed predictions) HIGH 4 on Customer
6 Channel Optimizer
Email vs phone vs print
Build 1 + engagement data MEDIUM 4 on Customer
7 Escalation Advisor
Escalate / extend / settle
Builds 2+5, CLV data PHASE 2+ 5 on Customer
Total New Custom Fields
~28 fields
~24 on Customer record · ~3 on Dunning Letter · 1 new custom record (AI Audit Log). All additive — no existing fields modified.
Highest ROI Build
Build 7 — Escalation Advisor
Recovering 85% of a debt via settlement instead of sending to a collection agency (25–50% commission) is the single largest revenue-saving capability. But it needs Builds 2+5 first.

Security & GDPR Architecture

Non-negotiable rules applied to every Azure API interaction across all seven builds

🔐
API Key Storage
Script Parameter (Secret type). Never hardcoded. Retrieved via runtime.getCurrentScript().getParameter(). Rotated quarterly.
🕶️
PII Anonymization
Every call through anonymizer.js. Stripped: name, email, VAT, invoice numbers, address. Amounts → buckets. Only behavioral signals cross.
🇪🇺
EU Data Residency
Azure OpenAI Norway East. Data never leaves EU. GDPR compliance by contract. No data retention on Azure side.
📋
Full Audit Trail
Every call → customrecord_ai_dunning_log. Anonymized payload, response, script ID, version, timestamp, success/fail. Immutable.
👤
Human in the Loop
No AI decision auto-executes. AR team reviews and approves every action via Watchtower before anything reaches a customer.
🛡️
Prompt Injection Defense
Customer email bodies: HTML stripped, truncated 500 chars, wrapped in delimiters. Model treats as data only.
Response Validation
All AI responses validated against schema. Missing/malformed → error log + fallback to default behavior. No raw output to users.
Governance Guard
governanceGuard.js checks remaining units. Below 1000 → reschedule via N/task. Never crash mid-batch.

File Structure

New files (cyan) alongside existing codebase (grey)

/SuiteScripts
/Libraries — existing, unchanged
rc-norway-lib.js — 59K core library
rc-norway-def-lib.js — definitions & constants
cs-moment.js · rc-xml-parser-lib.js

/User Events — existing, unchanged
rc-norway-dunning-ue.js
AN-UE-Dunning-Related-Customizations-On-Multiple-Records.js
AN_UE_Source_Email_Addresses_From_Transaction.js
rc-norway-sublist-report-field-ue.js

/Map Reduce — existing, unchanged
rc-norway-dunning-mr.js · rc-norway-dunning-letter-send-mr.js
rm-mr-create-dunning-records.js · rc-norway-dunning-fee-mr.js

/Watchtower — NEW · all AI capabilities
/lib — shared by all 7 builds
azureClient.js — API wrapper, retry, timeout
anonymizer.js — PII stripping, signal payloads
auditLogger.js — writes to AI audit log
governanceGuard.js — usage checks, reschedule
sanitizer.js — HTML strip, truncate, delimiters

/scripts — build implementations
ue_tone_engine.js — Build 1: tone personalization
mr_risk_predictor.js — Build 2: nightly risk scoring
sl_email_webhook.js — Build 3: dispute classifier
mr_send_time_optimizer.js — Build 4: optimal send timing
mr_cash_flow_predictor.js — Build 5: payment forecasting
ue_channel_optimizer.js — Build 6: channel recommendation
ue_escalation_advisor.js — Build 7: escalate/extend/settle

/restlets
rl_watchtower_data.js — all dashboard data endpoints

/suitelet
sl_watchtower.js — renders dashboard HTML
watchtower_ui.html — full HTML/CSS/JS

/setup
custom_fields_spec.md — ~28 new fields documented
script_parameters.md — all params and purposes
deployment_spec.md — scripts, deployments, scheduling

Implementation Phases

Sequential build order — each phase unlocks the next

Phase 1 · Foundation
Shared Libraries
Five utility modules shared by all seven builds. Azure API client with retry, PII anonymizer, audit logger, governance guard, sanitizer. Get these right — everything depends on them.
azureClient.jsanonymizer.jsauditLogger.jsgovernanceGuard.jssanitizer.js
Phase 2 · Quick Win
Build 1 — Tone Engine
Smallest surface area. Integrates with existing letter creation. Immediate visible value — customers get contextually appropriate communications. Safe fallback if AI fails.
ue_tone_engine.js4 custom fields
Phase 3 · Proactive
Build 2 — Risk Predictor
Standalone nightly job. First data source for the dashboard. AR team starts seeing proactive risk scores and call tasks. Changes the workflow from reactive to predictive.
mr_risk_predictor.js4 custom fieldsTask creation
Phase 4 · Reactive Intelligence
Build 3 — Dispute Classifier
Most complex core build. Requires email webhook setup. Classifies inbound, drafts Norwegian responses, auto-pauses on promises. Feeds Dispute Inbox panel.
sl_email_webhook.js4 custom fieldsEmail webhook config
Phase 5 · Command Center
Watchtower Dashboard v1
Wire Builds 1–3 into the single Suitelet dashboard. Three panels + KPI strip. The AR team's daily command center goes live.
sl_watchtower.jswatchtower_ui.htmlrl_watchtower_data.js
Phase 6 · Optimization
Builds 4+5 — Timing & Forecasting
Send-Time Optimizer improves email engagement. Cash Flow Predictor gives finance the payment forecast they've always wanted. New dashboard panel: Cash Flow Timeline.
mr_send_time_optimizer.jsmr_cash_flow_predictor.js7 custom fields
Phase 7 · Full Intelligence
Builds 6+7 — Channel & Escalation
Channel Optimizer ensures right medium per customer. Escalation Advisor — the highest-ROI build — recommends escalate/extend/settle at the critical moment. Watchtower Dashboard v2 with all panels.
ue_channel_optimizer.jsue_escalation_advisor.js9 custom fieldsSettlement workflow