Queries · q221 · Chief Financial Officer · week 2, night 1
“Does the 16-40% quarterly gap between payments-based and order_returns-based refund totals come from refunds simply landing in a later quarter than the original purchase, rather than from missing or double-counted data?”
Fictional people at a fictional company, each played by a language-model agent. Who they are and what they are told
Week 2
The external auditors start the 2025 year-end audit in two weeks. They will want to see that the money adds up across the whole chain: what shoppers paid, what was refunded or credited, what merchants received in payouts, what Tidewick kept, and that invoices agree with all of it. They will also trace sample transactions end to end.
The manager, at the start of week 2
Subject: Good progress — but the audit clock is now the priority
Kofi,
Thanks — this is useful, and I appreciate you flagging the caveats rather than smoothing them over. A few reactions and then where I want to focus next week.
What stood out:
The big new driver: external audit starts in two weeks. They'll want to walk the full money trail — what a shopper paid, what was refunded or credited back, what the merchant was paid out, what we kept as our fee, and that it all agrees with the invoices and accounts — and they'll pick sample transactions and trace them start to finish. I'd rather we got ahead of that than react to it.
Questions for this week, in priority order:
Audit readiness (#1) is the one I most need — please make that the lead request even if it means FX and B2B receivables slip another week.
Thanks, Tobias
The analyst · week 2, night 1, request 2 of 3
Audit readiness is explicitly the lead ask, so I'm using one dense report to walk a sample of real transactions end-to-end — payment → refund → merchant payout (gross/fee/net) → ledger balance — in one place, since that's literally what the auditors will do when they pick sample transactions. I folded the payout settlement check and the ledger tie-out into a single payment-grain report (12 columns, at the comfortable limit) rather than two separate reports, to leave room tonight for the other two priorities.
For priority #2 (refund figure discrepancy), my working hypothesis going in is that this is a structural date-field mismatch rather than a data error: payments.amount_refunded gets bucketed by the original purchase's captured_at quarter, while order_returns.refund_total gets bucketed by refunded_at (when the refund actually happened) — and Yuki's finding that refunds typically land ~3 weeks after settlement supports refunds routinely crossing a quarter boundary. I'm testing that directly by measuring the lag between purchase quarter and refund quarter for 2025 returns, which should explain most of the 16-40% swings without needing a full reconciliation.
For #4 (room permitting), I'm sizing the uncapped-coupon-reuse gap Oliver flagged, since "no usage/per-customer limit exists" is only a control gap in euros if people are actually exploiting it — I want €-at-risk from repeat redemptions by the same customer, comparable in kind to the €57k free-delivery number, so Tobias can judge scale before deciding if it goes to the auditors.
#3 (plan-fee revenue) gets no slot tonight: I rechecked the schema and confirmed there is no table that could hold Tidewick's own platform-plan billing of merchants (plans/subscriptions/invoices here are each merchant's billing of their own customers) — this is a true data gap, not something a cleverer query can solve, so I'll report that status in prose and recommend sourcing it from the corporate billing/finance system instead.
The engineer · 1 dry run on the empty schema, then the submission
WITH base AS ( SELECT t0.id AS return_id, t0.order_id, t0.refund_total, t0.currency_code, t0.refunded_at FROM order_returns t0 WHERE t0.status = 'refunded' AND t0.refunded_at >= DATE '2025-01-01' AND t0.refunded_at < DATE '2026-01-01' ), first_payment AS ( SELECT t1.order_id, MIN(t1.captured_at) AS first_captured_at FROM payments t1 WHERE t1.captured_at IS NOT NULL GROUP BY t1.order_id ), joined AS ( SELECT b.return_id, b.refund_total, b.currency_code, b.refunded_at, o.id AS order_id, fp.first_captured_at FROM base b LEFT JOIN orders o ON o.id = b.order_id LEFT JOIN first_payment fp ON fp.order_id = o.id ), rated AS ( SELECT j.*, CASE WHEN j.currency_code = 'EUR' THEN 1.0 ELSE er.rate END AS fx_rate FROM joined j LEFT JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = j.currency_code AND er.as_of = CAST(j.refunded_at AS date) ), categorized AS ( SELECT r.*, CASE WHEN r.fx_rate IS NULL OR r.fx_rate = 0 THEN NULL ELSE r.refund_total / r.fx_rate END AS refund_amount_eur, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE (EXTRACT(YEAR FROM r.refunded_at)*4 + EXTRACT(QUARTER FROM r.refunded_at)) - (EXTRACT(YEAR FROM r.first_captured_at)*4 + EXTRACT(QUARTER FROM r.first_captured_at)) END AS quarter_diff, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE EXTRACT(EPOCH FROM (r.refunded_at - r.first_captured_at)) / 86400.0 END AS lag_days FROM rated r ), bucketed AS ( SELECT c.*, CASE WHEN c.quarter_diff IS NULL THEN 'no matching payment found' WHEN c.quarter_diff <= 0 THEN 'same quarter as purchase' WHEN c.quarter_diff = 1 THEN 'purchase 1 quarter earlier' ELSE 'purchase 2+ quarters earlier' END AS lag_category FROM categorized c ) SELECT b.lag_category, COUNT(*) AS return_count, ROUND(SUM(b.refund_amount_eur), 2) AS refund_amount_eur, ROUND(100.0 * SUM(b.refund_amount_eur) / SUM(SUM(b.refund_amount_eur)) OVER (), 2) AS pct_of_total_2025_refund_amount, ROUND(AVG(b.lag_days), 1) AS avg_lag_days FROM bucketed b GROUP BY b.lag_category ORDER BY return_count DESC, b.lag_category ASC
“Query compiles and returns the expected columns. Submitting.”
“Submitted. The report buckets 2025 refunded order_returns into four lag categories (same quarter, 1Q earlier, 2+Q earlier, no match), matching each return to its order's earliest captured payment, converting refund totals to EUR via the daily EUR→currency rate, and computing count, EUR amount, % of total, and average lag in days per bucket — which should let the CFO's team see how much of the payments-vs-returns gap is just timing lag versus genuinely unmatched data.”
As Kofi Mensah saw it, from the small dataset the agents worked on
lag_category | return_count | refund_amount_eur | pct_of_total_2025_refund_amount | avg_lag_days ---------------------------+--------------+-------------------+---------------------------------+------------- same quarter as purchase | 2529 | 366023.32 | 78.55 | 21.1 purchase 1 quarter earlier | 786 | 93035.48 | 19.96 | 24.7 no matching payment found | 3 | 6937.12 | 1.49 | NULL (3 rows)
The memo and the queries that followed; links found by title, so inferred
It builds on:
Changed only where the benchmark needs the same result on every system
WITH base AS ( SELECT t0.id AS return_id, t0.order_id, t0.refund_total, t0.currency_code, t0.refunded_at SELECT t0.id AS return_id, t0.order_id AS order_id, t0.refund_total AS refund_total, t0.currency_code AS currency_code, t0.refunded_at AS refunded_at FROM order_returns t0 WHERE t0.status = 'refunded' AND t0.refunded_at >= DATE '2025-01-01' AND t0.refunded_at < DATE '2026-01-01'),first_payment AS ( SELECT t1.order_id, MIN(t1.captured_at) AS first_captured_at SELECT t1.order_id AS order_id, MIN(t1.captured_at) AS first_captured_at FROM payments t1 WHERE t1.captured_at IS NOT NULL GROUP BY t1.order_id),joined AS ( SELECT b.return_id, b.refund_total, b.currency_code, b.refunded_at, b.return_id AS return_id, b.refund_total AS refund_total, b.currency_code AS currency_code, b.refunded_at AS refunded_at, o.id AS order_id, fp.first_captured_at fp.first_captured_at AS first_captured_at FROM base b LEFT JOIN orders o ON o.id = b.order_id LEFT JOIN first_payment fp ON fp.order_id = o.id),rated AS ( SELECT j.*, CASE WHEN j.currency_code = 'EUR' THEN 1.0 ELSE er.rate END AS fx_rate FROM joined j LEFT JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = j.currency_code AND er.as_of = CAST(j.refunded_at AS date)),categorized AS ( SELECT r.*, CASE WHEN r.fx_rate IS NULL OR r.fx_rate = 0 THEN NULL ELSE r.refund_total / r.fx_rate END AS refund_amount_eur, CASE WHEN r.fx_rate IS NULL OR r.fx_rate = 0 THEN NULL ELSE CAST(r.refund_total / r.fx_rate AS NUMERIC(18,6)) END AS refund_amount_eur, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE (EXTRACT(YEAR FROM r.refunded_at)*4 + EXTRACT(QUARTER FROM r.refunded_at)) - (EXTRACT(YEAR FROM r.first_captured_at)*4 + EXTRACT(QUARTER FROM r.first_captured_at)) END AS quarter_diff, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE EXTRACT(EPOCH FROM (r.refunded_at - r.first_captured_at)) / 86400.0 ELSE {{seconds_between(r.first_captured_at, r.refunded_at)}} / 86400.0 END AS lag_days FROM rated r),bucketed AS ( SELECT c.*, CASE WHEN c.quarter_diff IS NULL THEN 'no matching payment found' WHEN c.quarter_diff <= 0 THEN 'same quarter as purchase' WHEN c.quarter_diff = 1 THEN 'purchase 1 quarter earlier' ELSE 'purchase 2+ quarters earlier' END AS lag_category FROM categorized c)SELECT b.lag_category, b.lag_category AS lag_category, COUNT(*) AS return_count, ROUND(SUM(b.refund_amount_eur), 2) AS refund_amount_eur, ROUND(100.0 * SUM(b.refund_amount_eur) / SUM(SUM(b.refund_amount_eur)) OVER (), 2) AS pct_of_total_2025_refund_amount, ROUND(AVG(b.lag_days), 1) AS avg_lag_days SUM(b.refund_amount_eur) AS refund_amount_eur, 100.0 * SUM(b.refund_amount_eur) / SUM(SUM(b.refund_amount_eur)) OVER () AS pct_of_total_2025_refund_amount, AVG(b.lag_days) AS avg_lag_daysFROM bucketed bGROUP BY b.lag_categoryORDER BY return_count DESC, b.lag_category ASCORDER BY return_count DESC NULLS FIRST, b.lag_category ASC NULLS LAST
WITH base AS ( SELECT t0.id AS return_id, t0.order_id AS order_id, t0.refund_total AS refund_total, t0.currency_code AS currency_code, t0.refunded_at AS refunded_at FROM order_returns t0 WHERE t0.status = 'refunded' AND t0.refunded_at >= DATE '2025-01-01' AND t0.refunded_at < DATE '2026-01-01' ), first_payment AS ( SELECT t1.order_id AS order_id, MIN(t1.captured_at) AS first_captured_at FROM payments t1 WHERE t1.captured_at IS NOT NULL GROUP BY t1.order_id ), joined AS ( SELECT b.return_id AS return_id, b.refund_total AS refund_total, b.currency_code AS currency_code, b.refunded_at AS refunded_at, o.id AS order_id, fp.first_captured_at AS first_captured_at FROM base b LEFT JOIN orders o ON o.id = b.order_id LEFT JOIN first_payment fp ON fp.order_id = o.id ), rated AS ( SELECT j.*, CASE WHEN j.currency_code = 'EUR' THEN 1.0 ELSE er.rate END AS fx_rate FROM joined j LEFT JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = j.currency_code AND er.as_of = CAST(j.refunded_at AS date) ), categorized AS ( SELECT r.*, CASE WHEN r.fx_rate IS NULL OR r.fx_rate = 0 THEN NULL ELSE CAST(r.refund_total / r.fx_rate AS NUMERIC(18,6)) END AS refund_amount_eur, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE (EXTRACT(YEAR FROM r.refunded_at)*4 + EXTRACT(QUARTER FROM r.refunded_at)) - (EXTRACT(YEAR FROM r.first_captured_at)*4 + EXTRACT(QUARTER FROM r.first_captured_at)) END AS quarter_diff, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE CAST(EXTRACT(EPOCH FROM (r.refunded_at - r.first_captured_at)) AS NUMERIC(18,6)) / 86400.0 END AS lag_days FROM rated r ), bucketed AS ( SELECT c.*, CASE WHEN c.quarter_diff IS NULL THEN 'no matching payment found' WHEN c.quarter_diff <= 0 THEN 'same quarter as purchase' WHEN c.quarter_diff = 1 THEN 'purchase 1 quarter earlier' ELSE 'purchase 2+ quarters earlier' END AS lag_category FROM categorized c ) SELECT b.lag_category AS lag_category, COUNT(*) AS return_count, SUM(b.refund_amount_eur) AS refund_amount_eur, 100.0 * SUM(b.refund_amount_eur) / SUM(SUM(b.refund_amount_eur)) OVER () AS pct_of_total_2025_refund_amount, AVG(b.lag_days) AS avg_lag_days FROM bucketed b GROUP BY b.lag_category ORDER BY return_count DESC NULLS FIRST, b.lag_category ASC NULLS LAST
WITH base AS ( SELECT t0.id AS return_id, t0.order_id AS order_id, t0.refund_total AS refund_total, t0.currency_code AS currency_code, t0.refunded_at AS refunded_at FROM order_returns t0 WHERE t0.status = 'refunded' AND t0.refunded_at >= DATE '2025-01-01' AND t0.refunded_at < DATE '2026-01-01' ), first_payment AS ( SELECT t1.order_id AS order_id, MIN(t1.captured_at) AS first_captured_at FROM payments t1 WHERE t1.captured_at IS NOT NULL GROUP BY t1.order_id ), joined AS ( SELECT b.return_id AS return_id, b.refund_total AS refund_total, b.currency_code AS currency_code, b.refunded_at AS refunded_at, o.id AS order_id, fp.first_captured_at AS first_captured_at FROM base b LEFT JOIN orders o ON o.id = b.order_id LEFT JOIN first_payment fp ON fp.order_id = o.id ), rated AS ( SELECT j.*, CASE WHEN j.currency_code = 'EUR' THEN 1.0 ELSE er.rate END AS fx_rate FROM joined j LEFT JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = j.currency_code AND er.as_of = CAST(j.refunded_at AS date) ), categorized AS ( SELECT r.*, CASE WHEN r.fx_rate IS NULL OR r.fx_rate = 0 THEN NULL ELSE CAST(r.refund_total / r.fx_rate AS NUMERIC(18,6)) END AS refund_amount_eur, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE (EXTRACT(YEAR FROM r.refunded_at)*4 + EXTRACT(QUARTER FROM r.refunded_at)) - (EXTRACT(YEAR FROM r.first_captured_at)*4 + EXTRACT(QUARTER FROM r.first_captured_at)) END AS quarter_diff, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE CAST(divideDecimal(toDecimal128(dateDiff('microsecond', r.first_captured_at, r.refunded_at), 0), toDecimal128(1000000, 0), 6) AS Nullable(Decimal(18, 6))) / 86400.0 END AS lag_days FROM rated r ), bucketed AS ( SELECT c.*, CASE WHEN c.quarter_diff IS NULL THEN 'no matching payment found' WHEN c.quarter_diff <= 0 THEN 'same quarter as purchase' WHEN c.quarter_diff = 1 THEN 'purchase 1 quarter earlier' ELSE 'purchase 2+ quarters earlier' END AS lag_category FROM categorized c ) SELECT b.lag_category AS lag_category, COUNT(*) AS return_count, SUM(b.refund_amount_eur) AS refund_amount_eur, 100.0 * SUM(b.refund_amount_eur) / SUM(SUM(b.refund_amount_eur)) OVER () AS pct_of_total_2025_refund_amount, AVG(b.lag_days) AS avg_lag_days FROM bucketed b GROUP BY b.lag_category ORDER BY return_count DESC NULLS FIRST, b.lag_category ASC NULLS LAST
The agents' own records, as the role play wrote them; only the personal data of the person who ran it is redacted
Report request from Kofi Mensah (analyst for the Chief Financial Officer):
Title: Refund Attribution Lag: Purchase Quarter vs Refund Quarter, 2025
Question: Does the 16-40% quarterly gap between payments-based and order_returns-based refund totals come from refunds simply landing in a later quarter than the original purchase, rather than from missing or double-counted data?
Grain: one lag category, for order_returns refunded in 2025
Columns:
- lag_category ('same quarter as purchase', 'purchase 1 quarter earlier', 'purchase 2+ quarters earlier', 'no matching payment found')
- return_count
- refund_amount_eur
- pct_of_total_2025_refund_amount
- avg_lag_days (refunded_at minus the originating payment's captured_at)
Details: Source: order_returns with status='refunded' and refunded_at in calendar year 2025, LEFT JOIN orders on order_returns.order_id, LEFT JOIN payments on payments.order_id = orders.id (if an order has multiple payments, use the earliest captured_at). Convert order_returns.refund_total to EUR via exchange_rates (base_code='EUR', quote_code=order_returns.currency_code, as_of=date(refunded_at)). Compute the calendar quarter of refunded_at and the calendar quarter of the matched payment's captured_at; bucket into the four lag_category values based on how many quarters apart they are (or 'no matching payment found' if the join fails). avg_lag_days is the average of (refunded_at - captured_at) in days within each bucket (null for the no-match bucket). Order by return_count descending.
Check your query with the warehouse's dry_run tool, then hand it in with submit.dry_runWITH base AS ( SELECT t0.id AS return_id, t0.order_id, t0.refund_total, t0.currency_code, t0.refunded_at FROM order_returns t0 WHERE t0.status = 'refunded' AND t0.refunded_at >= DATE '2025-01-01' AND t0.refunded_at < DATE '2026-01-01' ), first_payment AS ( SELECT t1.order_id, MIN(t1.captured_at) AS first_captured_at FROM payments t1 WHERE t1.captured_at IS NOT NULL GROUP BY t1.order_id ), joined AS ( SELECT b.return_id, b.refund_total, b.currency_code, b.refunded_at, o.id AS order_id, fp.first_captured_at FROM base b LEFT JOIN orders o ON o.id = b.order_id LEFT JOIN first_payment fp ON fp.order_id = o.id ), rated AS ( SELECT j.*, CASE WHEN j.currency_code = 'EUR' THEN 1.0 ELSE er.rate END AS fx_rate FROM joined j LEFT JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = j.currency_code AND er.as_of = CAST(j.refunded_at AS date) ), categorized AS ( SELECT r.*, CASE WHEN r.fx_rate IS NULL OR r.fx_rate = 0 THEN NULL ELSE r.refund_total / r.fx_rate END AS refund_amount_eur, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE (EXTRACT(YEAR FROM r.refunded_at)*4 + EXTRACT(QUARTER FROM r.refunded_at)) - (EXTRACT(YEAR FROM r.first_captured_at)*4 + EXTRACT(QUARTER FROM r.first_captured_at)) END AS quarter_diff, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE EXTRACT(EPOCH FROM (r.refunded_at - r.first_captured_at)) / 86400.0 END AS lag_days FROM rated r ), bucketed AS ( SELECT c.*, CASE WHEN c.quarter_diff IS NULL THEN 'no matching payment found' WHEN c.quarter_diff <= 0 THEN 'same quarter as purchase' WHEN c.quarter_diff = 1 THEN 'purchase 1 quarter earlier' ELSE 'purchase 2+ quarters earlier' END AS lag_category FROM categorized c ) SELECT b.lag_category, COUNT(*) AS return_count, ROUND(SUM(b.refund_amount_eur), 2) AS refund_amount_eur, ROUND(100.0 * SUM(b.refund_amount_eur) / SUM(SUM(b.refund_amount_eur)) OVER (), 2) AS pct_of_total_2025_refund_amount, ROUND(AVG(b.lag_days), 1) AS avg_lag_days FROM bucketed b GROUP BY b.lag_category ORDER BY return_count DESC, b.lag_category ASC
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: lag_category, return_count, refund_amount_eur, pct_of_total_2025_refund_amount, avg_lag_days
submitWITH base AS ( SELECT t0.id AS return_id, t0.order_id, t0.refund_total, t0.currency_code, t0.refunded_at FROM order_returns t0 WHERE t0.status = 'refunded' AND t0.refunded_at >= DATE '2025-01-01' AND t0.refunded_at < DATE '2026-01-01' ), first_payment AS ( SELECT t1.order_id, MIN(t1.captured_at) AS first_captured_at FROM payments t1 WHERE t1.captured_at IS NOT NULL GROUP BY t1.order_id ), joined AS ( SELECT b.return_id, b.refund_total, b.currency_code, b.refunded_at, o.id AS order_id, fp.first_captured_at FROM base b LEFT JOIN orders o ON o.id = b.order_id LEFT JOIN first_payment fp ON fp.order_id = o.id ), rated AS ( SELECT j.*, CASE WHEN j.currency_code = 'EUR' THEN 1.0 ELSE er.rate END AS fx_rate FROM joined j LEFT JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = j.currency_code AND er.as_of = CAST(j.refunded_at AS date) ), categorized AS ( SELECT r.*, CASE WHEN r.fx_rate IS NULL OR r.fx_rate = 0 THEN NULL ELSE r.refund_total / r.fx_rate END AS refund_amount_eur, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE (EXTRACT(YEAR FROM r.refunded_at)*4 + EXTRACT(QUARTER FROM r.refunded_at)) - (EXTRACT(YEAR FROM r.first_captured_at)*4 + EXTRACT(QUARTER FROM r.first_captured_at)) END AS quarter_diff, CASE WHEN r.first_captured_at IS NULL THEN NULL ELSE EXTRACT(EPOCH FROM (r.refunded_at - r.first_captured_at)) / 86400.0 END AS lag_days FROM rated r ), bucketed AS ( SELECT c.*, CASE WHEN c.quarter_diff IS NULL THEN 'no matching payment found' WHEN c.quarter_diff <= 0 THEN 'same quarter as purchase' WHEN c.quarter_diff = 1 THEN 'purchase 1 quarter earlier' ELSE 'purchase 2+ quarters earlier' END AS lag_category FROM categorized c ) SELECT b.lag_category, COUNT(*) AS return_count, ROUND(SUM(b.refund_amount_eur), 2) AS refund_amount_eur, ROUND(100.0 * SUM(b.refund_amount_eur) / SUM(SUM(b.refund_amount_eur)) OVER (), 2) AS pct_of_total_2025_refund_amount, ROUND(AVG(b.lag_days), 1) AS avg_lag_days FROM bucketed b GROUP BY b.lag_category ORDER BY return_count DESC, b.lag_category ASC
Submitted to tonight's batch. Your work on this request is done.