| # Metrics: gl β raw-GL basis metrics (topic gl_lines), matching modules/expenses.py definitions | |
| # EXACTLY (the parity anchor): opex = Ξ£ balance of posted lines to expense-type accounts | |
| # ('expense','expense_depreciation'), COGS ('expense_direct_cost') EXCLUDED; gl_revenue = income | |
| # accounts negated. Filtered measures use store_filter_sql (aliases: l=line, m=move, a=account). | |
| topic: gl_lines | |
| metrics: | |
| - key: opex | |
| label: Operating expense | |
| agg: sum | |
| field: balance | |
| store_filter_sql: "a.account_type IN ('expense', 'expense_depreciation')" | |
| format: usd | |
| description: "Posted operating expense from the GL (all expense-type accounts; COGS excluded) β the Expenses dashboard's basis." | |
| ai_context: "Company-level; includes payroll JEs/depreciation/fees that never hit vendor bills. Watch close-lag: the newest month is often still being booked." | |
| validate: | |
| method: gl_opex | |
| note: "Store-path opex must equal the live Odoo aggregate (posted, expense-type accounts) to the cent." | |
| - key: gl_cogs | |
| label: COGS (GL) | |
| agg: sum | |
| field: balance | |
| store_filter_sql: "a.account_type = 'expense_direct_cost'" | |
| format: usd | |
| description: "Cost of goods sold on the GL basis (expense_direct_cost accounts)." | |
| ai_context: "Distinct from the sales-margin COGS (revenue - margin on order lines) β different basis, reconcile deliberately, never mix silently." | |
| - key: gl_revenue | |
| label: Revenue (GL) | |
| agg: sum | |
| field: balance | |
| negate: true | |
| store_filter_sql: "a.account_type IN ('income', 'income_other')" | |
| format: usd | |
| description: "GL-basis revenue: income-type account balances, negated to read positively." | |
| ai_context: "ALL-channel and accrual-basis β will not equal wholesale order revenue (sales_lines); that difference is structural (Amazon channel + timing), not an error." | |