Synthetic data, shaped after a European delivery-integration platform, with a UAE arm Canon Ops
World clock Fri 23:00:00 CEST paused · 20×

Definitions

The definitions the agent and Ask both run on. Each has an owner, a version, SQL and tests. Edits make a new version.

Stage gap

stage_gap unit: companies canonical: shared

Where the three active-client counts disagree, and what each disagreement is worth. Finance, Growth and Ops own it together: it is the reconciliation behind the active-client Venn. Each merchant falls in at most one gap; the amount is AED per month at list prices, or AED invoiced this period.

sharedCFO, CGO and COO · shared v1canonical

Four disjoint gaps between signed (contract, not churned), live (first order received), ordering (an order in the last ordering_days days) and billed (a positive invoice issued this period). signed_not_live: signed, no first order, nothing billed; worth the monthly subscription once live. live_not_billed: live but quiet (no order in ordering_days) and not billed; worth the inactivity fee. ordering_not_billed: ordering but not billed; worth the monthly subscription. billed_not_ordering: billed but no order in ordering_days; worth what was invoiced. Subscriptions are list prices per store per month; invoice amounts are converted to AED with a fixed table of illustrative rates.

latest change: First version.

  • pass count_betweenobserved 159, expected between 50.0 and 600.0
  • pass uniqueobserved {'duplicates': 0}, expected merchant_id unique
  • pass not_nullobserved {'null_cells': 0}, expected no NULLs in ['gap', 'amount_aed']
SQL, rendered for now
WITH fx(currency, aed_per_unit) AS (
  VALUES ('AED', 1.0), ('SAR', 0.97933), ('QAR', 1.00893), ('KWD', 11.9512), ('BHD', 9.76729),
         ('GBP', 4.88443), ('EUR', 4.27118), ('USD', 3.6725), ('INR', 0.0437)
),
list_price(plan, subscription_aed) AS (
  VALUES ('starter', 349.0), ('growth', 649.0), ('enterprise', 1149.0)
),
stores AS (
  SELECT merchant_id, count(*) AS stores
  FROM branches
  WHERE opened_at IS NULL OR opened_at <= TIMESTAMP 'Fri 23:00:00'
  GROUP BY merchant_id
),
ordering AS (
  SELECT b.merchant_id FROM orders_daily d JOIN branches b ON b.id = d.branch_id
  WHERE d.day >= CAST(TIMESTAMP 'Fri 23:00:00' - INTERVAL (30) DAY AS DATE)
    AND d.day < CAST(TIMESTAMP 'Fri 23:00:00' AS DATE) AND d.orders > 0
  UNION
  SELECT b.merchant_id FROM orders o JOIN branches b ON b.id = o.branch_id
  WHERE o.placed_at >= TIMESTAMP 'Fri 23:00:00' - INTERVAL (30) DAY AND o.placed_at < TIMESTAMP 'Fri 23:00:00'
    AND o.status <> 'rejected'
),
billed AS (
  SELECT i.merchant_id, round(sum(i.amount * fx.aed_per_unit), 2) AS invoiced_aed
  FROM invoices i
  JOIN fx ON fx.currency = i.currency
  WHERE i.issued_at >= TIMESTAMP 'Thu 00:00:00 (15 days ago)' AND i.issued_at < TIMESTAMP 'Fri 23:00:00' AND i.amount > 0
  GROUP BY i.merchant_id
),
states AS (
  SELECT m.id AS merchant_id, m.name, mk.code AS market, m.plan,
         greatest(coalesce(s.stores, 0), 1) AS stores,
         m.first_order_at < TIMESTAMP 'Fri 23:00:00' AS live,
         o.merchant_id IS NOT NULL AS ordering,
         bl.merchant_id IS NOT NULL AS billed,
         bl.invoiced_aed, coalesce(lp.subscription_aed, 0) AS subscription_aed
  FROM merchants m
  LEFT JOIN markets mk ON mk.id = m.market_id
  LEFT JOIN stores s ON s.merchant_id = m.id
  LEFT JOIN (SELECT DISTINCT merchant_id FROM ordering) o ON o.merchant_id = m.id
  LEFT JOIN billed bl ON bl.merchant_id = m.id
  LEFT JOIN list_price lp ON lp.plan = m.plan
  WHERE m.contract_signed_at < TIMESTAMP 'Fri 23:00:00'
    AND (m.churned_at IS NULL OR m.churned_at >= TIMESTAMP 'Fri 23:00:00')
),
gaps AS (
  SELECT *,
         CASE WHEN billed AND NOT ordering THEN 'billed_not_ordering'
              WHEN ordering AND NOT billed THEN 'ordering_not_billed'
              WHEN coalesce(live, FALSE) AND NOT ordering AND NOT billed THEN 'live_not_billed'
              WHEN NOT coalesce(live, FALSE) AND NOT ordering AND NOT billed THEN 'signed_not_live'
         END AS gap
  FROM states
)
SELECT gap, merchant_id, name, market, plan, stores, live, ordering, billed,
       CASE gap WHEN 'billed_not_ordering' THEN 'invoiced_this_period'
                WHEN 'live_not_billed' THEN 'inactivity_fee_per_month'
                ELSE 'subscription_per_month' END AS amount_kind,
       round(CASE gap WHEN 'billed_not_ordering' THEN invoiced_aed
                      WHEN 'live_not_billed' THEN 149.0 * stores
                      ELSE subscription_aed * stores END, 2) AS amount_aed
FROM gaps
WHERE gap IS NOT NULL
ORDER BY gap, merchant_id

Parameters

change one, see what changes tonight, then save it as a new version with a note
now 30 · used by shared
now 149.0 · used by shared

History

append-only; nothing is edited in place
  1. definitionCFO, CGO and COO shared v1 First version.