Sample output from the Purchasing & Spend Intelligence prompt in the Sonar AI Prompt Library, run against a NetSuite test account. Every name and number here is test data. Back to the post · The library
Procure-to-Pay Deep Dive · Second Edition

Purchasing & Spend Intelligence

Trailing 12 months · September 2025 – August 2026 · Account TD3016323 (all subsidiaries, USD) · Generated 2026-08-24 by Sonar AI · Fully reproducible — all 19 source queries in Appendix B

00Executive Summary

The company spent $2.26M with 31 vendors across 555 bills in the trailing 12 months — and the run-rate nearly doubled mid-year. Second-half spend (+91.7% vs. first half) is being driven by genuine volume growth plus two August one-offs ($120K lease prepayment, $52.5K consulting). Cash paid out to vendors in August alone was $538K.

The purchasing machine is disciplined where it's automated and loose where it's manual. The inventory pipeline is exemplary: 388 POs flowed to bills in 0–3 days, receipts matched, no stale commitments. But 45% of spend ($1.02M) arrives with no PO, 23.6% carries no department attribution, and two contracts totaling $334K/yr have billed identical amounts for 12 straight months without a re-bid.

The payment policy is exactly backwards. Bills are paid on average 4.2 days after receipt — 24 days before due — surrendering ~$137K of average float (~$6,800/yr at 5%). Meanwhile all five bills that offered early-pay discounts missed their windows, forfeiting ~$1,810. Fixing both is recommendation #2 and worth ~$8,600/yr at current volume.

Three items need eyes this week: an open bill with a 285× price anomaly (VB397, $2,995 vs. the established $10.48 rate), a first-ever $120K round-number bill from a brand-new vendor due Sep 2 (Davidson Leasing — verify bank details out-of-band), and a $31K round-number bill dated Christmas Day. A first-digit (Benford) test on all 555 amounts also fails at the 1% significance level — §06 explains why that is probably structural, and how to confirm.

$2.26M
Total vendor-bill spend
555 bills · 31 vendors · avg $4,076
+91.7%
H2 vs H1 spend
$775K → $1.49M
$184K
Open A/P right now
incl. $3.1K stuck in approval
$233K
Spend with vendors <6 months old
10.3% of total · 13 new vendors

01The Year in Spend

Monthly vendor-bill totals [Q1]. August 2026 hit 199% of the monthly average — the biggest month of the year. Dashed overlay = August restated without its two one-off transactions.

$87K
Sep
$139K
Oct
$121K
Nov
$120K
Dec
$142K
Jan
$166K
Feb
$177K
Mar
$271K
Apr
$241K
May
$228K
Jun
$194K
Jul
$375K
Aug
$202K
Aug*

*Aug restated excl. Davidson Leasing $120,000 (Prepaid Expenses) and Cloud Consulting $52,550 (Training) [Q8]. The underlying growth is real regardless: Apr–Aug averages $262K/mo vs. $122K/mo for Sep–Jan. Two structural drivers: bill counts jumped from ~31/mo to ~57–81/mo starting April (new vendors Johnson Supply, Crown Equipment, Cloud Consulting onboarded May–Jul), and cash-out followed one month behind, peaking at $538K in August [Q9]. If H2 is the new normal, annualized purchasing is ~$3.0M — budget accordingly.

02Vendor Concentration — Top-Heavy, With a Ghost Town Below

Top 10 of 31 vendors by 12-month spend [Q2].

Generation N
$556,688 · 24.6%
Bedline
$365,460 · 16.2%
FrisCo US
$249,755 · 11.0%
Broyhill
$249,378 · 11.0%
The Apparel Co Inc.
$221,073 · 9.8%
Davidson Leasing
$120,000 · 5.3%
Dell US
$101,049 · 4.5%
Brocade Communications Systems US
$84,207 · 3.7%
Lotion Co
$53,915 · 2.4%
Cloud Consulting
$53,550 · 2.4%
Concentration

Top 5 vendors = 72.6% of all spend

Top 10 = 90.9%. Herfindahl-Hirschman index ≈ 1,290 (computed over vendor spend shares; 1,000–1,800 = moderately concentrated by DOJ convention). Losing Generation N or Bedline tomorrow would disrupt a quarter to a sixth of the supply base overnight — and §04 shows 79 items have no second source at all.

Tail spend

18 vendors share the bottom 5%

Over half the active vendor base (18 of 31) collectively bills under $113K. Nine sent exactly one bill all year — including "Well" ($1,000), "China Manufacturer" ($750) and "Harris Technology" ($20). Each one-off vendor is onboarding overhead and fraud surface with almost zero purchasing leverage in return.

Vendor churn

13 of 31 vendors are less than 6 months old

Vendors first billed after 2026-02-24 already account for $233,426 (10.3%) of 12-month spend [Q13] — led by Davidson Leasing ($120K, single bill) and Cloud Consulting ($53.6K in 3 bills over 5 weeks). Fast vendor onboarding without a verification protocol is how payment-diversion fraud gets in.

Benchmark

Where you stand

A 31-vendor base on $2.26M spend (~$73K/vendor) is lean — many mid-market companies run 3–5× more vendors per spend dollar. The problem isn't count; it's the shape: heavy head, unmanaged tail, no mid-tier redundancy.

03What the Money Actually Bought

Vendor-bill spend by GL posting account, A/P offset excluded [Q3].

2220 · Inventory Received Not Billed
$1,225,000 · 54.2%
1210 · Inventory in Stock
$357,418 · 15.8%
6060 · Advertising
$249,755 · 11.0%
1400 · Prepaid Expenses
$120,000 · 5.3%
6655 · Computer — Office Expense
$101,049 · 4.5%
6671 · Telephone — Regular Service
$84,207 · 3.7%
6260 · Training Expense
$53,550 · 2.4%
6240 · Supplies Expense
$33,522 · 1.5%
6640 · Other Utilities
$10,104 · 0.4%
All other (7 accounts)
$26,504 · 1.2%

70% of spend is resale inventory — healthy for retail/distribution. The tells are in the indirect lines: $84,207/yr of telephone service (all Brocade, 24 bills of ~$3.5K like clockwork) and $249,755/yr of advertising (all FrisCo US, ~$10.4K/mo, identical cadence). Steady, identical, never re-bid — the exact profile of contracts running on autopilot. Also note $12.1K of fixed-asset purchases (accounts 1610/1620) came through as plain vendor bills — confirm they were also registered in Fixed Assets Management, which is installed in this account.

04Items, Subsidiaries & Attribution

Top items

Leather rules the buy — top 12 items [Q12]

ItemBillsQtySpend
INV_Black Leather Jacket38586$117,200
INV_Black Leather Valise38638$82,302
INV_Gold Watch w/ Leather Strap36319$70,180
INV_Brown Leather Satchel36196$58,798
INV_Brown Leather Valise37333$53,280
INV_Canvas Backpack36345$42,090
6 more…$199,346

The top 6 items alone are $424K — and per §05, 79 of 154 purchased items are single-sourced. Where the top items and the single-source list intersect is your highest supply-chain risk.

Attribution

Who's spending it — and the $534K blind spot

DimensionShare of spend
Subsidiary 1 [Q14]$1,635,133 · 72.3%
Subsidiary 2$625,308 · 27.6%
Parent Company$1,564 · 0.1%
By department [Q15]
Warehouse Operations$999,538 · 44.2%
(no department)$534,437 · 23.6%
Sales$499,841 · 22.1%
Store Ops / Production / Admin$228,190 · 10.1%

Nearly a quarter of line-level spend has no department — which means departmental P&Ls understate real cost consumption by up to $534K. Most of it is the big no-PO bills (lease, advertising, consulting). A make-department-mandatory rule on bill entry closes this.

05Findings You Didn't Ask For (But Should See)

Anomalies surfaced by cross-cutting queries — each verified against live transaction data, each with its query in Appendix B.

Price anomaly

A 285× price spike on one item [Q6/Q7]

Item INV_2-Layer Copper costs $10.48/unit on all 5 Core4Solutions bills this year. Then bill VB397 (Generation N, 2026-08-01) billed 1 unit at $2,995.00 — 285× the established rate, from a vendor that doesn't normally supply this item. VB397 is still open ($2,995 unpaid, due Aug 31). Verify before paying: likely a mis-keyed line or wrong item selected.

Discounts missed

All 5 early-pay discount windows lapsed [Q11]

Only five bills all year carried 1%/2% 10-day discount terms — including Davidson Leasing's $120,000 (worth $1,200) and Cloud Consulting's $52,550 (worth $525). Every one of the five 10-day windows expired unpaid by Aug 13. Total forfeited: ~$1,810. The irony: you pay everything else 24 days early (next card) — just not the bills that reward it.

Working capital

Bills are paid 24 days before due [Q5]

Average bill-to-payment: 4.2 days against predominantly Net 30 terms (87% of bills are Net 30 [Q10]). 533 of 542 paid bills (98.3%) settled 10+ days early; only 8 were ever late. That's ~$137K of average float handed to vendors ($2.078M paid spend × 24/365), worth ~$6,832/yr at a 5% cost of capital — with zero discounts captured in return. Monthly trend [Q16] shows this is policy, not accident: every single month averages under 10 days.

Process control

45% of spend has no purchase order [Q4]

$1.02M across 167 bills hit A/P with no PO behind them, vs. $1.24M PO-backed (388 bills). No PO = no receiving match, no pre-commitment approval. Some is legitimately non-PO (lease, telecom, consulting) — but at 45% it's a habit, not an exception. The PO-backed pipeline, by contrast, is airtight: PO→bill in 0–3 days, average 1.1 [Q17].

Odd timing

29% of bills dated on weekends — one on Christmas [Q18]

161 bills totaling $660,720 carry Sat/Sun transaction dates; heaviest weekend biller is Bedline ($163K over 15 weekend bills). And bill VB04 — a round $31,000 to Generation N — is dated December 25, 2025 [Q8]. Weekend dating usually means backdated batch entry (consistent with the Monday entry spike in §07), but round-number holiday bills are textbook audit flags. Pull the paper on VB04.

Supply risk

79 of 154 items are single-sourced [Q19]

51% of purchased items — $1.02M of 12-month spend — came from exactly one vendor. Combined with top-5 concentration of 72.6% and 70% of spend being resale inventory, a single vendor failure could stall both stores and DCs. Start with alternates for the top-6 leather items in §04.

New vendor risk

$120K to a vendor with one transaction ever [Q13]

Davidson Leasing first appeared 2026-08-03 with a single $120,000 round-number bill (no document number recorded), booked to Prepaid Expenses, carrying a 1%-10 discount nobody took, due 2026-09-02. Large + round + first-ever + missing tranid is the classic new-vendor-fraud checklist. Presumably a legitimate lease prepayment — but confirm bank details out-of-band before the payment run, and attach the lease to the vendor record.

Stuck items

4 bills idling in Pending Approval — one 55 days past due [Q11]

A $1,500 Bedline bill has sat in approval since June 1. Two Flexsteel "interco alloc" bills ($1,000 each) are 30 and 61 days past due — intercompany allocations that miss month-end distort both subsidiaries' P&Ls. And 6 bills totaling $3,833 have no payment terms, so their due dates are guesses [Q10].

06Forensic Digit Analysis (Benford's Law)

First digits of naturally-occurring amounts follow a logarithmic curve (30.1% start with 1, 4.6% with 9). Auditors test invoice populations against it. Solid bars = your 555 bill amounts [Q20]; hollow bars = Benford expectation.

27.4/30.1
1
16.0/17.6
2
19.3/12.5
3
11.0/9.7
4
10.1/7.9
5
6.5/6.7
6
4.9/5.8
7
0.7/5.1
8
4.1/4.6
9

Labels = observed% / expected%. χ² = 48.9 on 8 degrees of freedom — the population fails conformity at the 1% level (critical value 20.09); mean absolute deviation 2.29pp ("nonconformity" on the Nigrini scale). Two digits drive it: digit 3 is over-represented (19.3% vs 12.5%) and digit 8 is nearly absent (4 bills vs ~28 expected).

Read this carefully before reaching for a pitchfork. Benford assumes amounts spanning several orders of magnitude from many independent processes. This population is 555 bills from 31 vendors, several billing fixed installments — Broyhill alone repeats $13,900 ×4, $10,530.50 ×4, $9,500.50 ×4, $9,103 ×4 (all digit-consumers for 1, 9 and 3). Repeated contract amounts mechanically distort digit frequencies; that's the innocent explanation and the likely one. The useful signal: the digit-3 excess and digit-8 hole are concentrated in mid-size ($3K–$40K) bills — if you ever commission a fraud review, that's the stratum to sample first. This is a screening statistic, not an accusation.

07The Rhythm of Your Spend

PatternEvidenceRead
Recurring "subscription-like" billsFrisCo US, Dell US, Brocade, Staples, XCOM, CDW each billed exactly 24× (2/mo), same accounts, near-identical amounts [Q2/Q3]Predictable — automate matching
Repeated same-amount bills25 vendor+amount pairs repeat ≥3× — Broyhill $13,900 ×4, Bedline $12,373.50 ×4, etc. [Q21]Verify installments, not duplicates
PO discipline where it counts388 closed POs worth $1.24M flowed PO → receipt → bill in 0–3 days (avg 1.1) [Q17]; only 2 POs pending receipt ($2,050) + 19 pending billing ($29.7K) [Q22]Inventory pipeline is airtight
Monday is billing day99 bills / $629K land on Mondays — the heaviest day; Tuesday quietest (49) [Q18]. Consistent with weekend-dated bills being entered Monday.Batch-entry cadence
Payment velocity is policyMonthly avg days-to-pay ranged 1.8–9.9 all year; since April it's locked at 2.3–3.2 days [Q16] — payments accelerated exactly as spend doubledCash going out faster as volume grows

08Risk Register

Every finding, scored. Severity = likelihood × financial impact; effort = time to remediate.

#RiskExposureSeverityEffortOwner (suggested)
R1VB397 price anomaly paid as-billed$2,985High10 minA/P
R2Davidson Leasing unverified before $120K payment$120,000High1 hourController
R3Single-vendor dependency (top 5 = 72.6%; 79 single-sourced items)~$1.0MHighQuartersPurchasing
R4Backwards payment policy (float + missed discounts)~$8,600/yrMedium1 weekController
R5No-PO spend at 45% — no pre-approval on $1.02M$1.02M flowMedium2 weeksPurchasing
R6Autopilot contracts never re-bid (telecom + advertising)$334K/yrMedium1 monthPurchasing
R7$534K spend with no department attributionReportingMedium1 dayController
R8VB04 — $31K round-number bill dated Dec 25$31,000Medium30 minController
R9Approval queue stalls (55-day pending bill; late interco allocs)$4.5K + P&L timingLow1 hourA/P
R10Benford nonconformity (χ²=48.9) — screening flag onlyUnknownLowIf audited

09What To Do About It

Ordered by urgency, then by return on effort.

1

This week: hold VB397, verify Davidson Leasing, pull the paper on VB04

Three specific transactions (R1, R2, R8). VB397: confirm the $2,995 line with Generation N or correct it. Davidson Leasing: phone-verify bank details using an independently-sourced number before the Sep 2 due date — and take the $1,200 discount while you're at it if paying by Aug 13 had been possible, or negotiate its extension. VB04: retrieve the source document for a $31K round bill dated Christmas Day.

Value: up to $3K recovery + $120K fraud insurance · Effort: half a day total
2

Split the payment policy in two

Pay discount-term bills inside their 10-day window (a 2/10 Net 30 discount is a ~36% annualized return — nothing else you do with cash beats it); schedule everything else at day 28 via payment batches. Today the policy is precisely inverted: 98% of ordinary bills paid 10+ days early, 100% of discount bills paid late.

Value: ~$1,800/yr discounts + ~$6,800/yr float = ~$8,600/yr at current volume — doubles if H2 run-rate holds
Effort: one A/P policy memo + due-date-driven payment batches in NetSuite
3

Re-bid the autopilot contracts

Telephone at $84K/yr (Brocade) and advertising at $250K/yr (FrisCo US) have billed identical amounts for 12 straight months. Telecom is a market where competitive quotes routinely save 20–40%; media buying at $250K/yr justifies an agency review or at minimum a rate benchmark.

Value: realistic $17K–$34K/yr on telecom alone; advertising upside unknown until benchmarked
Effort: 2 RFQs, ~1 month elapsed
4

Set a no-PO threshold + mandatory department

Require a PO (or named contract reference) for any non-inventory purchase over ~$2,500, and make department mandatory on bill entry. The first rule puts pre-approval on ~$800K/yr that currently arrives as a surprise; the second closes the $534K attribution hole so departmental P&Ls mean something.

Value: control + reporting integrity · Effort: one form tweak + one policy rule, ~2 weeks incl. comms
5

De-risk the head, rationalize the tail

For the top 5 vendors (72.6% of spend): document alternates for the 79 single-sourced items, starting with the six leather SKUs that alone carry $424K. For the tail: retire or consolidate the 9 one-bill vendors and route future one-offs through an existing vendor or a P-card.

Value: resilience + negotiating leverage — consolidated tail spend is negotiable spend
Effort: standing agenda item, quarters not weeks
6

Instrument the process so this report runs itself

Three saved searches close the loop: (a) bills in Pending Approval > 7 days; (b) new-vendor first bills > $10K; (c) line rate > 3× trailing-average rate for the same item. Each maps directly to an incident found in this review (55-day stall, Davidson Leasing, VB397). Sonar can build all three on request.

Value: catches next year's versions of this year's findings in real time
Effort: ~1 hour

AAssumptions, Definitions & Caveats

Scope definitions

Computed-metric assumptions

Data-quality observations made during extraction

BSource Queries (SuiteQL)

Every number in this report traces to one of these queries, run live against account TD3016323 on 2026-08-24 via Sonar AI. Paste any of them into the SuiteQL Query Tool to reproduce. Conventions: foreigntotal is negative on vendor bills (wrapped in ABS for display); statuses use single-letter codes (A=Open, B=Paid, D=Pending Approval).

Q1 Monthly spend trend
Feeds §01 chart. Totals shown as ABS in the report.
SELECT TO_CHAR(t.trandate, 'YYYY-MM') AS month,
       COUNT(*) AS bill_count,
       ROUND(SUM(t.foreigntotal), 2) AS total_billed
FROM transaction t
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY TO_CHAR(t.trandate, 'YYYY-MM')
ORDER BY TO_CHAR(t.trandate, 'YYYY-MM')
Q2 Spend by vendor (concentration, tail, recurring cadence)
SELECT v.id AS vendor_id, v.entityid AS vendor,
       COUNT(t.id) AS bills,
       ROUND(SUM(t.foreigntotal), 2) AS total_spend,
       ROUND(AVG(t.foreigntotal), 2) AS avg_bill,
       MIN(TO_CHAR(t.trandate, 'YYYY-MM-DD')) AS first_bill,
       MAX(TO_CHAR(t.trandate, 'YYYY-MM-DD')) AS last_bill
FROM transaction t
JOIN vendor v ON t.entity = v.id
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY v.id, v.entityid
ORDER BY SUM(t.foreigntotal) DESC
Q3 Spend by GL account
Note: account.acctname is NOT_EXPOSED to SuiteQL in this account — use fullname.
SELECT a.accttype, a.acctnumber, a.fullname,
       COUNT(DISTINCT t.id) AS bills,
       ROUND(SUM(tal.amount), 2) AS total_amount
FROM transactionaccountingline tal
JOIN transaction t ON tal.transaction = t.id
JOIN account a ON tal.account = a.id
WHERE t.type = 'VendBill' AND t.posting = 'T'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND a.accttype <> 'AcctPay'
GROUP BY a.accttype, a.acctnumber, a.fullname
ORDER BY SUM(tal.amount) DESC
Q4 PO-backed vs. no-PO split
Header createdfrom errors in this account; line-level works. Inner GROUP BY dedupes before summing — a naive re-join double-counts.
SELECT origin, COUNT(*) AS bills, ROUND(SUM(total), 2) AS total
FROM (
  SELECT t.id, ABS(t.foreigntotal) AS total,
         CASE WHEN MAX(CASE WHEN tl.createdfrom IS NOT NULL
                            THEN 1 ELSE 0 END) = 1
              THEN 'PO-backed' ELSE 'No PO' END AS origin
  FROM transaction t
  JOIN transactionline tl ON tl.transaction = t.id
  WHERE t.type = 'VendBill'
    AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  GROUP BY t.id, ABS(t.foreigntotal)
)
GROUP BY origin
Q5 Payment-timing behavior (DPO, early/late)
SELECT ROUND(AVG(TRUNC(t.closedate) - TRUNC(t.trandate)), 1) AS avg_days_to_pay,
       ROUND(AVG(TRUNC(t.closedate) - TRUNC(t.duedate)), 1) AS avg_days_vs_due,
       SUM(CASE WHEN TRUNC(t.closedate) > TRUNC(t.duedate) THEN 1 ELSE 0 END) AS paid_late,
       SUM(CASE WHEN TRUNC(t.closedate) <= TRUNC(t.duedate) - 10 THEN 1 ELSE 0 END) AS paid_10plus_days_early,
       COUNT(*) AS paid_bills
FROM transaction t
WHERE t.type = 'VendBill' AND t.status = 'B'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND t.duedate IS NOT NULL AND t.closedate IS NOT NULL
Q6 Item purchase-price variance
SELECT i.itemid, i.displayname, COUNT(DISTINCT t.id) AS bills,
       ROUND(MIN(ABS(tl.rate)), 2) AS min_rate,
       ROUND(MAX(ABS(tl.rate)), 2) AS max_rate,
       ROUND((MAX(ABS(tl.rate)) - MIN(ABS(tl.rate)))
             / NULLIF(MIN(ABS(tl.rate)), 0) * 100, 1) AS pct_swing,
       ROUND(SUM(ABS(tl.netamount)), 2) AS total_spend
FROM transaction t
JOIN transactionline tl ON tl.transaction = t.id
     AND tl.mainline = 'F' AND tl.taxline = 'F'
JOIN item i ON i.id = tl.item
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND tl.rate IS NOT NULL AND ABS(tl.rate) > 0
GROUP BY i.itemid, i.displayname
HAVING MAX(ABS(tl.rate)) > MIN(ABS(tl.rate))
ORDER BY (MAX(ABS(tl.rate)) - MIN(ABS(tl.rate)))
         / NULLIF(MIN(ABS(tl.rate)), 0) DESC
FETCH FIRST 15 ROWS ONLY
Q7 Drill-down: INV_2-Layer Copper purchase history
SELECT i.itemid, ROUND(ABS(tl.rate), 2) AS rate,
       ROUND(ABS(tl.netamount), 2) AS amount, tl.quantity,
       t.tranid, TO_CHAR(t.trandate, 'YYYY-MM-DD') AS bill_date,
       v.entityid AS vendor
FROM transaction t
JOIN transactionline tl ON tl.transaction = t.id
     AND tl.mainline = 'F' AND tl.taxline = 'F'
JOIN item i ON i.id = tl.item
JOIN vendor v ON v.id = t.entity
WHERE t.type = 'VendBill' AND i.itemid = 'INV_2-Layer Copper'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
ORDER BY t.trandate
Q8 Round-number bills ≥ $5K (incl. the Christmas bill)
SELECT v.entityid AS vendor, t.tranid,
       TO_CHAR(t.trandate, 'YYYY-MM-DD') AS trandate,
       ROUND(ABS(t.foreigntotal), 2) AS amount
FROM transaction t
JOIN vendor v ON t.entity = v.id
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND MOD(ABS(t.foreigntotal), 1000) = 0
  AND ABS(t.foreigntotal) >= 5000
ORDER BY ABS(t.foreigntotal) DESC
Q9 Monthly cash paid to vendors
SELECT TO_CHAR(t.trandate, 'YYYY-MM') AS month,
       COUNT(*) AS payments,
       ROUND(SUM(ABS(t.foreigntotal)), 2) AS cash_out
FROM transaction t
WHERE t.type = 'VendPymt'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY TO_CHAR(t.trandate, 'YYYY-MM')
ORDER BY TO_CHAR(t.trandate, 'YYYY-MM')
Q10 Payment-terms mix
SELECT COALESCE(tm.name, '(no terms)') AS terms,
       COUNT(*) AS bills,
       ROUND(SUM(ABS(t.foreigntotal)), 2) AS total
FROM transaction t
LEFT JOIN term tm ON t.terms = tm.id
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY COALESCE(tm.name, '(no terms)')
ORDER BY SUM(ABS(t.foreigntotal)) DESC
Q11 Open/pending A/P aging + discount-term bills
Two queries: open-bill aging, and the five bills carrying 10-day discount terms.
SELECT v.entityid AS vendor, t.tranid,
       TO_CHAR(t.trandate, 'YYYY-MM-DD') AS bill_date,
       TO_CHAR(t.duedate, 'YYYY-MM-DD') AS due_date,
       ROUND(t.foreignamountunpaid, 2) AS unpaid,
       TRUNC(SYSDATE) - TRUNC(t.duedate) AS days_past_due, t.status
FROM transaction t
JOIN vendor v ON t.entity = v.id
WHERE t.type = 'VendBill' AND t.status IN ('A', 'D')
  AND t.foreignamountunpaid > 0
ORDER BY t.duedate;

SELECT v.entityid AS vendor, t.tranid, tm.name AS terms, t.status,
       TO_CHAR(t.trandate, 'YYYY-MM-DD') AS bill_date,
       TO_CHAR(t.duedate, 'YYYY-MM-DD') AS due_date,
       ROUND(ABS(t.foreigntotal), 2) AS amount
FROM transaction t
JOIN vendor v ON v.id = t.entity
JOIN term tm ON tm.id = t.terms
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND tm.name LIKE '%10 Net%'
ORDER BY t.trandate
Q12 Top purchased items
SELECT i.itemid, i.itemtype, COUNT(DISTINCT t.id) AS bills,
       ROUND(SUM(ABS(tl.netamount)), 2) AS spend,
       SUM(ABS(tl.quantity)) AS qty
FROM transaction t
JOIN transactionline tl ON tl.transaction = t.id
     AND tl.mainline = 'F' AND tl.taxline = 'F'
JOIN item i ON i.id = tl.item
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY i.itemid, i.itemtype
ORDER BY SUM(ABS(tl.netamount)) DESC
FETCH FIRST 12 ROWS ONLY
Q13 New-vendor watch (first bill ever in last 6 months)
HAVING clause checks first bill in full account history, not just the window.
SELECT v.entityid AS vendor,
       TO_CHAR(MIN(t.trandate), 'YYYY-MM-DD') AS first_bill_ever,
       COUNT(*) AS bills_12mo,
       ROUND(SUM(ABS(t.foreigntotal)), 2) AS spend_12mo
FROM transaction t
JOIN vendor v ON v.id = t.entity
WHERE t.type = 'VendBill'
GROUP BY v.entityid
HAVING MIN(t.trandate) >= TO_DATE('2026-02-24', 'YYYY-MM-DD')
ORDER BY SUM(ABS(t.foreigntotal)) DESC
Q14 Spend by subsidiary
transaction.subsidiary is NOT_EXPOSED in this account — join through the mainline transactionline instead.
SELECT s.name AS subsidiary, COUNT(DISTINCT t.id) AS bills,
       ROUND(SUM(ABS(t.foreigntotal)), 2) AS total
FROM transaction t
JOIN transactionline tl ON tl.transaction = t.id AND tl.mainline = 'T'
JOIN subsidiary s ON s.id = tl.subsidiary
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY s.name
ORDER BY SUM(ABS(t.foreigntotal)) DESC
Q15 Department attribution coverage
SELECT COALESCE(d.name, '(none)') AS department,
       COUNT(DISTINCT t.id) AS bills,
       ROUND(SUM(ABS(tl.netamount)), 2) AS total
FROM transaction t
JOIN transactionline tl ON tl.transaction = t.id
     AND tl.mainline = 'F' AND tl.taxline = 'F'
LEFT JOIN department d ON d.id = tl.department
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY COALESCE(d.name, '(none)')
ORDER BY SUM(ABS(tl.netamount)) DESC
Q16 Payment velocity by month
SELECT TO_CHAR(t.trandate, 'YYYY-MM') AS month,
       ROUND(AVG(TRUNC(t.closedate) - TRUNC(t.trandate)), 1) AS avg_days_to_pay,
       COUNT(*) AS paid_bills
FROM transaction t
WHERE t.type = 'VendBill' AND t.status = 'B'
  AND t.closedate IS NOT NULL
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY TO_CHAR(t.trandate, 'YYYY-MM')
ORDER BY TO_CHAR(t.trandate, 'YYYY-MM')
Q17 PO-to-bill cycle time
SELECT ROUND(AVG(TRUNC(vb.trandate) - TRUNC(po.trandate)), 1) AS avg_po_to_bill_days,
       MIN(TRUNC(vb.trandate) - TRUNC(po.trandate)) AS min_days,
       MAX(TRUNC(vb.trandate) - TRUNC(po.trandate)) AS max_days,
       COUNT(DISTINCT vb.id) AS bills
FROM transaction vb
JOIN transactionline tl ON tl.transaction = vb.id
     AND tl.createdfrom IS NOT NULL
JOIN transaction po ON po.id = tl.createdfrom AND po.type = 'PurchOrd'
WHERE vb.type = 'VendBill'
  AND vb.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
Q18 Weekday pattern + weekend bills by vendor
SELECT TO_CHAR(t.trandate, 'DY') AS weekday, COUNT(*) AS bills,
       ROUND(SUM(ABS(t.foreigntotal)), 2) AS total
FROM transaction t
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY TO_CHAR(t.trandate, 'DY')
ORDER BY COUNT(*) DESC;

SELECT v.entityid AS vendor, COUNT(*) AS weekend_bills,
       ROUND(SUM(ABS(t.foreigntotal)), 2) AS total
FROM transaction t
JOIN vendor v ON t.entity = v.id
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND TO_CHAR(t.trandate, 'DY') IN ('SAT', 'SUN')
GROUP BY v.entityid
ORDER BY SUM(ABS(t.foreigntotal)) DESC
Q19 Single-sourced item exposure
SELECT COUNT(DISTINCT i.id) AS single_sourced_items,
       ROUND(SUM(spend), 2) AS spend
FROM (
  SELECT tl.item AS itemid, COUNT(DISTINCT t.entity) AS vendors,
         SUM(ABS(tl.netamount)) AS spend
  FROM transaction t
  JOIN transactionline tl ON tl.transaction = t.id
       AND tl.mainline = 'F' AND tl.taxline = 'F'
  WHERE t.type = 'VendBill'
    AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
    AND tl.item IS NOT NULL
  GROUP BY tl.item
  HAVING COUNT(DISTINCT t.entity) = 1
) x
JOIN item i ON i.id = x.itemid
-- Companion: total distinct items = 154, vendors = 20 (same query without HAVING)
Q20 Benford first-digit distribution
χ², expected frequencies, and MAD computed post-query (formulas in Appendix A).
SELECT SUBSTR(TO_CHAR(TRUNC(ABS(t.foreigntotal))), 1, 1) AS first_digit,
       COUNT(*) AS cnt
FROM transaction t
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND ABS(t.foreigntotal) >= 1
GROUP BY SUBSTR(TO_CHAR(TRUNC(ABS(t.foreigntotal))), 1, 1)
ORDER BY SUBSTR(TO_CHAR(TRUNC(ABS(t.foreigntotal))), 1, 1)
Q21 Repeated vendor+amount pairs (duplicate/installment screen)
SELECT v.entityid AS vendor, ROUND(ABS(t.foreigntotal), 2) AS amount,
       COUNT(*) AS occurrences,
       MIN(TO_CHAR(t.trandate, 'YYYY-MM-DD')) AS first_date,
       MAX(TO_CHAR(t.trandate, 'YYYY-MM-DD')) AS last_date
FROM transaction t
JOIN vendor v ON t.entity = v.id
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
  AND ABS(t.foreigntotal) >= 1000
GROUP BY v.entityid, ABS(t.foreigntotal)
HAVING COUNT(*) >= 3
ORDER BY ABS(t.foreigntotal) * COUNT(*) DESC
FETCH FIRST 25 ROWS ONLY
Q22 PO pipeline status + bill status mix
Status codes: PurchOrd G=Closed, F=Pending Billing, B=Partially Received, A=Pending Receipt · VendBill A=Open, B=Paid, D=Pending Approval.
SELECT COUNT(*) AS pos, ROUND(SUM(ABS(t.foreigntotal)), 2) AS po_value, t.status
FROM transaction t
WHERE t.type = 'PurchOrd'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY t.status ORDER BY COUNT(*) DESC;

SELECT t.status, COUNT(*) AS cnt,
       ROUND(SUM(t.foreigntotal), 2) AS total,
       ROUND(SUM(t.foreignamountunpaid), 2) AS unpaid
FROM transaction t
WHERE t.type = 'VendBill'
  AND t.trandate >= TO_DATE('2025-09-01', 'YYYY-MM-DD')
GROUP BY t.status ORDER BY COUNT(*) DESC

Reproducibility notes