| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| key: invoice_lines |
| label: Customer invoice lines (with commission agent) |
| entity: account.move.line |
|
|
| |
| |
| |
|
|
| scope: |
| documents: "posted customer invoices AND credit notes (move_type out_invoice/out_refund, parent_state posted)" |
| lines: >- |
| PRODUCT lines only (display_type = 'product'). Commission rows attach to 'cogs' lines too β |
| 96,936 of the 147,160 rows with a 2025 invoice_date. β MEASURED 2026-07-29, and NOT what it |
| first appears: dropping this filter does NOT move revenue or the customer count, because |
| non-product lines ('cogs', 'payment_term', 'line_note') all carry price_subtotal = 0 and |
| those customers already have product lines. The ~80% inflation is real for commission ROW |
| COUNTS (147,160 vs 50,191 product-line rows) and would corrupt any count-of-LINES measure β |
| it is a GRAIN guard, not a money guard. Keep it; just don't claim it protects the totals. |
| channels: >- |
| business unit comes from the ORIGINATING SALE ORDER (Fisch=5, Royal=6), because |
| account.move carries no BU (every invoice sits on team 1 "Sales"). Lines with no sale order |
| (direct invoices) have a NULL business unit and are KEPT, not dropped. |
| excluded: >- |
| Nothing is excluded by partner. GIFTWARE DEALS (Amazon) sits on its own team (7), so a |
| Fisch or Royal filter already excludes it β no partner-name exclusion needed here. |
| basis: "untaxed line subtotals (price_subtotal); credit-note lines are NEGATED by the metric" |
| date_field: "line date (= invoice date)" |
|
|
| grain: >- |
| one row per posted customer-invoice product line. The commission table is one row per |
| (line Γ agent), so it is joined DEDUPLICATED to at most one row per line β otherwise the 74 |
| two-agent lines would double-count revenue. |
| |
| store: |
| table: account_move_line |
| alias: l |
| |
| |
| |
| |
| |
| |
| join: >- |
| LEFT JOIN res_partner rp ON rp.id = l.partner_id |
| LEFT JOIN sale_order_line sol ON sol.id = l.sale_line_id |
| LEFT JOIN sale_order so ON so.id = sol.order_id |
| LEFT JOIN ( |
| SELECT object_id, agent_id, agent_name, is_true_agent, is_converted_salesman |
| FROM ( |
| SELECT a.object_id, a.agent_id, a.agent_name, |
| COALESCE(ap.agent, FALSE) AS is_true_agent, |
| COALESCE(ap.salesman_as_agent, FALSE) AS is_converted_salesman, |
| ROW_NUMBER() OVER (PARTITION BY a.object_id |
| ORDER BY COALESCE(ap.agent, FALSE) DESC, a.agent_id) AS rn |
| FROM account_invoice_line_agent a |
| LEFT JOIN res_partner ap ON ap.id = a.agent_id |
| ) ranked WHERE rn = 1 |
| ) ca ON ca.object_id = l.id |
| date_col: "l.date" |
| team_col: "so.team_id" |
| scope_sql: >- |
| l.parent_state = 'posted' AND l.move_type IN ('out_invoice','out_refund') |
| AND l.display_type = 'product' |
| dims: |
| partner: {col: "l.partner_id", name_col: "l.partner_name", label: "Customer"} |
| product: {col: "l.product_id", name_col: "l.product_name", label: "Product"} |
| team: |
| col: "so.team_id" |
| name_col: "CASE so.team_id WHEN 5 THEN 'Fisch' WHEN 6 THEN 'Royal' WHEN 7 THEN 'Giftware Deals (Amazon)' WHEN 1 THEN 'Sales (generic)' ELSE 'No sale order' END" |
| label: "Business unit" |
| |
| |
| agent: |
| col: "CASE WHEN ca.is_true_agent THEN ca.agent_id END" |
| name_col: "CASE WHEN ca.is_true_agent THEN ca.agent_name END" |
| label: "Agent (invoice line)" |
| |
| commission_name: |
| col: "ca.agent_id" |
| name_col: "ca.agent_name" |
| label: "Commission name (agent OR salesperson)" |
| agent_role: |
| col: "CASE WHEN ca.agent_id IS NULL THEN 'none' WHEN ca.is_true_agent THEN 'agent' ELSE 'salesperson' END" |
| name_col: "CASE WHEN ca.agent_id IS NULL THEN 'Nobody' WHEN ca.is_true_agent THEN 'Agent' ELSE 'Salesperson (not an agent)' END" |
| label: "Role on the line" |
| |
| allocation: |
| col: "CASE WHEN ca.is_true_agent THEN 'agent' WHEN ca.agent_id IS NOT NULL THEN 'salesperson' ELSE 'none' END" |
| name_col: "CASE WHEN ca.is_true_agent THEN 'Allocated to an agent' WHEN ca.agent_id IS NOT NULL THEN 'Salesperson only' ELSE 'Not allocated' END" |
| label: "Agent allocation" |
| |
| |
| |
| agent_origin: |
| col: "CASE WHEN ca.is_true_agent AND ca.is_converted_salesman THEN 'converted' WHEN ca.is_true_agent THEN 'external' END" |
| name_col: "CASE WHEN ca.is_true_agent AND ca.is_converted_salesman THEN 'Agent (converted salesman)' WHEN ca.is_true_agent THEN 'Agent (external)' END" |
| label: "Agent origin" |
|
|
| ai_context: > |
| Posted customer-invoice PRODUCT lines with the per-line commission agent. Use this topic for: |
| "which customers are assigned to an agent based on the invoice line", "what sales are NOT |
| allocated to an agent", commission questions, and any agent question phrased about invoices or |
| billing. Use `sales_lines` instead for "sales" in the ordinary sense (confirmed order lines) and |
| for book/relationship ownership. |
| β TWO AGENT SOURCES, DIFFERENT PEOPLE β say which you used. Here = per-line commission |
| (account.invoice.line.agent). There (`sales_lines.agent`) = the customer-master book |
| (res.partner.agent_ids). JACOB BRISK, Samuel Shif, Yuda Stern and Billy Petruccelli appear ONLY |
| on invoice lines; Moishe Rubenstein, Avi Ash and Sang Ching ONLY on the customer master. |
| β A NAME ON A COMMISSION LINE IS NOT NECESSARILY AN AGENT. "Anna" and "Shantal Erlich" are |
| internal SALESPEOPLE (res.partner.agent = False, each with an Odoo login, salesperson of record |
| on 1,253 / 184 confirmed orders) who carry commission lines anyway. The `agent` dim already |
| excludes them β they show up under `commission_name` with agent_role 'salesperson'. NEVER |
| report them as agents; if a question says "agent", they are not one. |
| THE ALLOCATION PARTITION: the `allocation` dim is MECE and sums to the total β 'Allocated to an |
| agent' / 'Salesperson only' / 'Not allocated'. When asked "what is not allocated to an agent", |
| give the strict figure (salesperson + none) AND say what the narrower no-commission-at-all |
| figure is, because the two readings differ materially and the questioner may mean either. |
| BUSINESS UNIT comes from the originating sale order, so a line with no sale order has a NULL |
| business unit β present that as "no sale order (direct invoice)" and keep it in company totals. |
| Fisch is team 5. CREDIT NOTES are included and the revenue metric negates them; a positive |
| refund total means the negation was lost. |
| MEASURED BASELINE for FISCH 2025 (use to sanity-check any answer): total $4,443,244.34 over |
| 68,540 lines and 979 customers, splitting exactly into $2,995,664.75 allocated to agents, |
| $361,198.24 salesperson-only, and $1,086,381.35 not allocated. 518 customers have a real agent |
| on at least one line. Martin Pasternak alone is $2,155,660.64. |
| A CUSTOMER IS NOT ALL-OR-NOTHING: 403 of those 518 customers are MIXED (some lines carry an |
| agent, some do not), so "sales BY agent-assigned customers" ($3,187,771.31) is a different |
| number from "sales ALLOCATED to an agent" ($2,995,664.75). Answer whichever was asked and say |
| which one it is; they do not subtract to each other. |
| |