Transformation Layer Guide
Purpose: Reference for building dbt staging and marts from RAW.
Related: raw-schema-profiles
Source → Staging → Mart Flow
flowchart LR subgraph raw [RAW] QB[POLYTOMIC_QUICKBOOKS] HS[POLYTOMIC_HUBSPOT] CL[CLOCKIFY] OP[OPERATING_IO] end subgraph staging [Staging] stg_qb[stg_quickbooks_*] stg_hs[stg_hubspot_*] stg_cl[stg_clockify_time_entries] stg_op[stg_operating_time_entries] end subgraph marts [Marts] mart_delivery[mart_delivery_time_effort] mart_finance_acct[mart_finance_account_monthly] mart_finance_summary[mart_finance_summary] end QB --> stg_qb HS --> stg_hs CL --> stg_cl OP --> stg_op stg_cl --> mart_delivery stg_op --> mart_delivery stg_qb --> mart_finance_acct mart_finance_acct --> mart_finance_summary
Phase 1: Delivery (Time/Effort)
stg_clockify_time_entries
- Source:
RAW.CLOCKIFY.TIME_ENTRIES - Grain: One row per time entry
- Key columns:
TIME_ENTRY_ID,START_TIME,END_TIME,DURATION_HOURS,USER_NAME,PROJECT_NAME,USER_ID,PROJECT_ID - No JSON flattening — columns are flat
stg_operating_time_entries
- Source:
RAW.OPERATING_IO.RAW_TIME_ENTRIES - Flatten:
RAW_DATA:date,RAW_DATA:personId,RAW_DATA:projectId,RAW_DATA:seconds,RAW_DATA:approvalStatus - Compute hours:
seconds / 3600 - Join: To RAW_PERSONS, RAW_PROJECTS for names (or use Operating as source of truth for allocation %)
mart_delivery_time_effort
- Unify: Clockify + Operating (or pick one)
- Grain: person + project + date + hours
- Consider: Clockify has 14k entries, Operating has 2.5k — may represent different populations (billable vs internal)
Phase 2: Finance
stg_quickbooks_invoices
- Source:
RAW.POLYTOMIC_QUICKBOOKS.INVOICES - Extract:
CUSTOMER_REF:value::TEXT AS customer_id - Filter:
_POLYTOMIC_DELETED_AT IS NULL
stg_quickbooks_bills
- Source:
RAW.POLYTOMIC_QUICKBOOKS.BILLS - Extract:
VENDOR_REF:value::TEXT AS vendor_id
stg_quickbooks_payments
- Source:
RAW.POLYTOMIC_QUICKBOOKS.PAYMENTS
stg_hubspot_deals
- Source:
RAW.POLYTOMIC_HUBSPOT.DEAL_PROPERTY_HISTORY - Pivot: Latest value per DEAL_ID, PROPERTY_NAME
- Key properties: amount, dealstage, closedate, createdate
mart_finance_account_monthly
- Sources:
stg_quickbooks_journal_entries(+ optional Finance+Ops mapping table when present) - Grain:
month + account_id + account_category (+ service_line if mapped) - Purpose: Canonical monthly ledger rollup with
revenue/cogs/operating_expensescategories when mapping exists. Falls back tounmappedwhen mapping is unavailable.
mart_finance_summary
- Sources:
mart_finance_account_monthly,stg_quickbooks_invoices,stg_quickbooks_bills,stg_quickbooks_payments - Grain:
month - Metrics:
revenue_amount,cogs_amount,operating_expenses_amount,accounts_receivable_balance_amount,accounts_payable_balance_amount,cash_received_amount, plus invoice/bill equivalents