Dashboard

Payment Demo Simulator

Triggers real Square sandbox payments — each fires a webhook and appears on the Square Payments page.

Square Sandbox Dashboard

Client Demo Runner — Late Fee Automation

Keep this page in the background; present the surfaces below. Each step stages real state on contract CFD-E2E-JANE (Kintone record 170) and fires the same nightly job the midnight cron runs. Full script: docs/flows/late-fee-client-demo.md

Demo contract CFD-E2E-JANE not found — run scripts/test-late-fee-e2e-record170.ts once (its Phase 0 seeds it), or check the API is up.

Default Management Demo Runner

Demoing contract CFD-DEMO-DEFAULT — no Kintone payment history is needed for this module, it only reads/writes the contract's status. Each step back-dates the due date and fires the same nightly job the midnight cron runs. Full flow: docs/flows/default-management-flow.md

Contract "CFD-DEMO-DEFAULT" not found — check the CFD ID and that it's synced into the local DB.

Matching Chain Scenario Lab

Each card fires a real Square sandbox payment with specific fields to exercise one path of the 8-level matching chain. After clicking, check the Square Payments page in ~2s to see the result.

P1Reference ID Match

Kintone $id=108 (Ilkania Lopez). reference_id = Kintone $id "108" → local DB miss → Kintone API fetch + auto-sync → MATCHED.

Fields sent to Square

reference_id"108"
note"Monthly CFD payment - Ilkania Lopez"
buyer_email_address"rohan.m@godatanova.com"
amount$878.69
Expected:MATCHED
P3CFD Pattern in Note

No reference_id. note contains "CFD-00108" → regex extracts token → DB lookup by CFD ID.

Fields sent to Square

note"Payment for CFD-00108"
amount$878.69
Expected:MATCHED
P4Email → Multi-Match

"rohan.m@godatanova.com" shared by all 10 Kintone records → multi-match → manual queue.

Fields sent to Square

buyer_email_address"rohan.m@godatanova.com"
amount$878.69
Expected:PENDING_CONFIRM
P0–P7Anonymous Payment

No reference_id, no note, no email, no customer ID → all 8 levels fail → UNMATCHED / ANONYMOUS.

Fields sent to Square

amount$999.00
Expected:UNMATCHED
P1Bad Reference ID

reference_id "99999" not in DB → P1 fails BAD_REFERENCE_ID → falls through chain → UNMATCHED.

Fields sent to Square

reference_id"99999"
amount$878.69
Expected:UNMATCHED
BATCHBatch Payment — 3 Contracts

note contains BATCH[454,654,232] → worker splits $1,450 across 3 contract IDs → creates PaymentBatch + per-contract Payment rows → BATCH ×3 badge on Payments page.

Fields sent to Square

note"BATCH[454,654,232]"
amount$1,450.00
Expected:BATCH_MATCHED

Step 1: Seed demo contracts first

Creates DEMO-BATCH-454/654/232 in local DB with kintoneRecordId 454/654/232 so the worker can resolve them without hitting Kintone.

Contract Payment Simulator

Pay a real contract amount via Square sandbox — uses reference_id matching (P1).

How this works: Each “Pay” button calls Square's Payments API (sandbox) with the contract's unique ID set as reference_id on the payment. Square fires a payment.updated webhook → our worker matches by reference_id first (exact lookup, no regex) → logs to DB + writes to Kintone → appears on the Square Payments page.
Loading contracts…

Late Fee Scenario Lab

Seed test contracts, fire the nightly cron on demand, and watch results appear on the Late Fee Automation page. Each scenario exercises a different code path in the state machine.

1st Offense

Has Clause — Pending Review

First overdue offense on a contract with a late fee clause. Cron flags it for operator review — no automatic charge.

Contract seeded with

hasLateFeeClausetrue
isSpecialStatusfalse
offenseCount0
nextDueDate35 days ago
Cron action:action: created
Fee status:PENDING_REVIEW

Appears in table — Waive / Enforce action buttons visible.

2nd Offense

Has Clause — Auto-Enforced

Second overdue offense. Cron escalates straight to AUTO_ENFORCED and starts a 15-day grace countdown.

Contract seeded with

hasLateFeeClausetrue
isSpecialStatusfalse
offenseCount1
nextDueDate35 days ago
Cron action:action: created
Fee status:AUTO_ENFORCED

Appears in table — Enforce button visible. Grace expires 15 days from now.

No Clause

No Clause — Reminder Only

Contract has no late fee clause. Cron sends a reminder email but creates no fee record.

Contract seeded with

hasLateFeeClausefalse
isSpecialStatusfalse
offenseCount0
nextDueDate35 days ago
Cron action:action: reminder_sent
Fee status:no fee created

No row appears in /late-fees. Email sent (no-op with placeholder Resend key).

Bypass

Special Status — Skipped

Military / hardship flag set. Cron skips this contract entirely — no email, no fee.

Contract seeded with

hasLateFeeClausetrue
isSpecialStatustrue
offenseCount0
nextDueDate35 days ago
Cron action:action: skipped
Fee status:no fee created

No row appears in /late-fees.

Grace Expired

Grace Period Expired — Invoice

Pre-seeded AUTO_ENFORCED fee whose 15-day grace expired yesterday. Cron tries to send a $50 Square invoice.

Contract seeded with

preSeededAUTO_ENFORCED fee
gracePeriodExpiresAtyesterday
offenseCount1
nextDueDate35 days ago
Cron action:action: auto_enforced
Fee status:ENFORCED (or error)

With placeholder Square creds: squareInvoiceError shown in table. Wire real creds to see ENFORCED.

Gap Fixes Test Lab (LAND-412)

Three end-to-end scenarios for the LAND-412 gap fixes. Each card: seed a contract → trigger the cron → check results. Wait ~3s after triggering before clicking “Check Results”.

Early WarningGap 2 — LAND-436/439

10–29 Day Early Warning Email

Contract is 15 days overdue — inside the Pass 1 window. Cron stamps lastReminderEmailSentAt but does NOT create a LateFee record.

Seeded with

scenarios6
nextDueDate15 days ago
hasLateFeeClausetrue
offenseCount0
lastReminderEmailSentAtnull (reset on seed)

Expected

cron logearlyWarningsSent ≥ 1
fee.statusno fee created

No new row on /late-fees for CFD-LF-S6

Level AGap 1 — LAND-436

Enforcement Level A — 1st Offense Auto-Enforced

With Level A, even a first offense goes straight to AUTO_ENFORCED — skipping the PENDING_REVIEW gate.

Seeded with

scenarios1
nextDueDate35 days ago
hasLateFeeClausetrue
offenseCount0 (1st offense)
Pre-step: Change Enforcement Level → A in Settings first → open /settings
Reset to Level C after testing.

Expected

cron logfeesCreated: 1
fee.statusAUTO_ENFORCED (not PENDING_REVIEW)

Row on /late-fees shows AUTO_ENFORCED — no Waive button visible

Waive BlockedGap 3 — LAND-412

Waive Button Hidden on AUTO_ENFORCED

2nd offense → cron creates AUTO_ENFORCED fee. On /late-fees, the Waive button is absent — only "Apply Fee" is shown.

Seeded with

scenarios2
nextDueDate35 days ago
hasLateFeeClausetrue
offenseCount1 (repeat offender)

Expected

cron logfeesCreated: 1
fee.statusAUTO_ENFORCED

On /late-fees the s2 row shows only "Apply Fee" — no Waive button

Live Late Fee E2E Runner

Runs the full Kintone-dynamic late fee + consolidated invoicing flow against a real contract — real Kintone record, real Square sandbox invoices. Unlike the Scenario Labs above, results here reflect actual Kintone and Square API state, not local-only seeds.

Step 1 — Pick a contract

Loading eligible contracts…

Inspect any Square invoice

Live status + linked Order line-item breakdown for any invoice ID — the same two checks from the manual curl guide (old invoice status, new invoice's Order line items), exposed here instead of the terminal.

Email Test Lab

Exercises all 4 late-fee email types (PRE_DUE_WARNING, EARLY_LATE_WARNING, LATE_FEE_WARNING, CATCH_UP_INVOICE) against a real contract. To see real deliveries instead of just server-log skips, set RESEND_API_KEY, EMAIL_TEST_MODE=true, and EMAIL_TEST_TO=your-inbox@gmail.com in lol-api/.env — every send then redirects to that inbox from Resend's sandbox address instead of the contract's real kintoneEmail. That redirect is hard-disabled outside NODE_ENV=production — it can never fire for a real customer.

Pick a contract

Loading…