Seven AI capabilities layered on top of an existing NetSuite dunning engine. Non-destructive, GDPR-compliant, human-in-the-loop.
How seven AI capabilities layer on top of the unchanged dunning engine
The current system — all unchanged. AI layer is additive only.
rc-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.rc-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.createDunningLetterRecord() 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.rc-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.customrecord_rcs_dunning_level_map. Terminal states: "Paid in Full" or "Sent for Debt Collection".The original three capabilities from the Watchtower spec — proven patterns, immediate value
anonymizer.js strips all PII → behavioral signal payload onlyazureClient.js → Azure returns { tone: "firm", variant: "NO_B2B_45D_FIRM", reasoning: "..." }custentity_ai_dunning_tone + custentity_ai_dunning_variant on Customer recordauditLogger.js records the interaction.getInputData: SuiteQL pulls customers with open AR NOT yet in dunningmap: Build anonymized signal (segment, country, days-to-due, amount bucket, late-pay history)reduce: Batch → Azure → score 0–100. Stamp custentity_ai_risk_score + flag on Customer.summarize: Log totals, reschedule via N/task if governance exhaustedsanitizer.js strips HTML, truncates 500 chars, wraps in delimiters (prompt injection defense)azureClient.js → classify + draft Norwegian responsecustentity_ai_dispute_class, store draft as Note on Customerpromise_to_pay → stamp date, pause dunning. dispute_invoice → create Support Case.Four additional capabilities that multiply the value of the core three
{ "sendDay": "Tuesday", "sendHour": 8, "confidence": 0.82, "reasoning": "B2B finance, Norway, opens Mon-Wed AM" }custentity_ai_optimal_send_time on the Dunning Letter. The send MR script respects this timestamp — holds letters until their optimal window.custrecord_ai_optimal_send_dt before dispatching. Letters held until their optimal window.
{ "predictedPayDate": "+12d", "confidence": 0.71, "expectedAmount": "FULL", "reasoning": "Historically pays 10-15d after Level 2" }custentity_rcn_cust_dun_send_method field is manually set and rarely updated.{ "channel": "PHONE", "confidence": 0.88, "reasoning": "3 emails ignored, high-value, historically responds to calls", "fallback": "PRINT" }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.{ "action": "EXTEND", "extendDays": 14, "reasoning": "Long-term customer, first late episode, active contract", "settlementOffer": null, "confidence": 0.85 }custentity_ai_settle_offerAll seven builds ranked by business impact, technical effort, and implementation priority
Non-negotiable rules applied to every Azure API interaction across all seven builds
runtime.getCurrentScript().getParameter(). Rotated quarterly.anonymizer.js. Stripped: name, email, VAT, invoice numbers, address. Amounts → buckets. Only behavioral signals cross.customrecord_ai_dunning_log. Anonymized payload, response, script ID, version, timestamp, success/fail. Immutable.governanceGuard.js checks remaining units. Below 1000 → reschedule via N/task. Never crash mid-batch.New files (cyan) alongside existing codebase (grey)
Sequential build order — each phase unlocks the next