Merged PR 4907: KPIs Refactor Stage 2 - Decouple AM - Churn/Account Margin

# Description

Decouples Churn/Account Margin model of `int_monthly_aggregated_metrics_history_by_deal_by_time_window` from the model `int_monthly_aggregated_metrics_history_by_deal`.

Changes:
* Removes dependency and reads from KPIs models.
* Removes unused deal stage variable
* Jinja template for time windows with dynamic selection to DRY

This has been tested with dbt audit tools and the md5 for pure refactoring, so output is exactly the same.

# Checklist

- [X] The edited models and dependants run properly with production data.
- [X] The edited models are sufficiently documented.
- [X] The edited models contain PK tests, and I've ran and passed them.
- [X] I have checked for DRY opportunities with other models and docs.
- [X] I've picked the right materialization for the affected models.

# Other

- [ ] Check if a full-refresh is required after this PR is merged.

Related work items: #28947
This commit is contained in:
Oriol Roqué Paniagua 2025-04-03 13:00:04 +00:00
parent a14de4fe3a
commit f6d25f681f

View file

@ -1,548 +1,352 @@
-- HubSpot stage for live deals
{% set live_stage = "Live" %}
{% set churned_state = "05-Churning" %} {% set churned_state = "05-Churning" %}
{% set time_window_aggregations = [
{{ config(materialized="table", unique_key=["date", "id_deal"]) }} {
"time_window_name": "All History",
"preceeding_from": 0,
"preceeding_to": 1,
"include_all_history": True,
},
{
"time_window_name": "Previous 12 months",
"preceeding_from": 12,
"preceeding_to": 1,
"include_all_history": False,
},
{
"time_window_name": "Previous 6 months",
"preceeding_from": 6,
"preceeding_to": 1,
"include_all_history": False,
},
{
"time_window_name": "Previous 3 months",
"preceeding_from": 3,
"preceeding_to": 1,
"include_all_history": False,
},
{
"time_window_name": "Previous month",
"preceeding_from": 1,
"preceeding_to": 1,
"include_all_history": False,
},
] %}
{{ config(materialized="table", unique_key=["date", "id_deal", "time_window"]) }}
with with
int_monthly_aggregated_metrics_history_by_deal as ( int_kpis__dimension_deals as (select * from {{ ref("int_kpis__dimension_deals") }}),
select * from {{ ref("int_monthly_aggregated_metrics_history_by_deal") }}
),
int_hubspot__deal as (select * from {{ ref("int_hubspot__deal") }}), int_hubspot__deal as (select * from {{ ref("int_hubspot__deal") }}),
metric_aggregation_all_history as ( int_kpis__lifecycle_daily_deal as (
select select * from {{ ref("int_kpis__lifecycle_daily_deal") }}
date,
id_deal,
client_type,
business_scope,
main_deal_name,
has_active_pms,
active_pms_list,
active_accommodations_per_deal_segmentation,
main_billing_country_iso_3_per_deal,
deal_lifecycle_state,
'All History' as time_window,
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "min", "id_deal", "date", "", 1, True
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "max", "id_deal", "date", "", 1, True
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"created_bookings", "sum", "id_deal", "date", "", 1, True
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"listings_booked_in_month", "avg", "id_deal", "date", "", 1, True
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_revenue_in_gbp", "sum", "id_deal", "date", "", 1, True
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_guest_payments_in_gbp",
"sum",
"id_deal",
"date",
"",
1,
True,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_operator_net_fees_in_gbp",
"sum",
"id_deal",
"date",
"",
1,
True,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_apis_net_fees_in_gbp", "sum", "id_deal", "date", "", 1, True
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_waiver_paid_back_to_host_in_gbp",
"sum",
"id_deal",
"date",
"",
1,
True,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_amount_paid_in_gbp",
"sum",
"id_deal",
"date",
"",
1,
True,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_payment_count",
"sum",
"id_deal",
"date",
"",
1,
True,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_in_gbp", "sum", "id_deal", "date", "", 1, True
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_post_resolutions_in_gbp",
"sum",
"id_deal",
"date",
"",
1,
True,
)
}}
from int_monthly_aggregated_metrics_history_by_deal
), ),
metric_aggregation_previous_12_months as ( int_kpis__dimension_daily_accommodation as (
select select * from {{ ref("int_kpis__dimension_daily_accommodation") }}
date,
id_deal,
client_type,
business_scope,
main_deal_name,
has_active_pms,
active_pms_list,
active_accommodations_per_deal_segmentation,
main_billing_country_iso_3_per_deal,
deal_lifecycle_state,
'Previous 12 months' as time_window,
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "min", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "max", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"created_bookings", "sum", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"listings_booked_in_month", "avg", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_revenue_in_gbp", "sum", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_guest_payments_in_gbp", "sum", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_operator_net_fees_in_gbp", "sum", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_apis_net_fees_in_gbp", "sum", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_waiver_paid_back_to_host_in_gbp",
"sum",
"id_deal",
"date",
12,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_amount_paid_in_gbp",
"sum",
"id_deal",
"date",
12,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_payment_count",
"sum",
"id_deal",
"date",
12,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_in_gbp", "sum", "id_deal", "date", 12, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_post_resolutions_in_gbp",
"sum",
"id_deal",
"date",
12,
1,
)
}}
from int_monthly_aggregated_metrics_history_by_deal
), ),
metric_aggregation_previous_6_months as ( int_kpis__agg_dates_main_kpis as (
select select *
date, from {{ ref("int_kpis__agg_dates_main_kpis") }}
id_deal, where
client_type, dimension in ('by_deal')
business_scope, and dimension_value <> 'UNSET'
main_deal_name, and is_end_of_month = true
has_active_pms,
active_pms_list,
active_accommodations_per_deal_segmentation,
main_billing_country_iso_3_per_deal,
deal_lifecycle_state,
'Previous 6 months' as time_window,
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "min", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "max", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"created_bookings", "sum", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"listings_booked_in_month", "avg", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_revenue_in_gbp", "sum", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_guest_payments_in_gbp", "sum", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_operator_net_fees_in_gbp", "sum", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_apis_net_fees_in_gbp", "sum", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_waiver_paid_back_to_host_in_gbp",
"sum",
"id_deal",
"date",
6,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_amount_paid_in_gbp",
"sum",
"id_deal",
"date",
6,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_payment_count",
"sum",
"id_deal",
"date",
6,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_in_gbp", "sum", "id_deal", "date", 6, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_post_resolutions_in_gbp",
"sum",
"id_deal",
"date",
6,
1,
)
}}
from int_monthly_aggregated_metrics_history_by_deal
), ),
metric_aggregation_previous_3_months as ( created_bookings as (
select select *
date, from {{ ref("int_kpis__agg_monthly_created_bookings") }}
id_deal, where dimension in ('by_deal') and dimension_value <> 'UNSET'
client_type,
business_scope,
main_deal_name,
has_active_pms,
active_pms_list,
active_accommodations_per_deal_segmentation,
main_billing_country_iso_3_per_deal,
deal_lifecycle_state,
'Previous 3 months' as time_window,
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "min", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"date", "max", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"created_bookings", "sum", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"listings_booked_in_month", "avg", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_revenue_in_gbp", "sum", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_guest_payments_in_gbp", "sum", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_operator_net_fees_in_gbp", "sum", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_apis_net_fees_in_gbp", "sum", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_waiver_paid_back_to_host_in_gbp",
"sum",
"id_deal",
"date",
3,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_amount_paid_in_gbp",
"sum",
"id_deal",
"date",
3,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_payment_count",
"sum",
"id_deal",
"date",
3,
1,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_in_gbp", "sum", "id_deal", "date", 3, 1
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_post_resolutions_in_gbp",
"sum",
"id_deal",
"date",
3,
1,
)
}}
from int_monthly_aggregated_metrics_history_by_deal
), ),
metric_aggregation_previous_1_month as ( listings as (
select *
from {{ ref("int_kpis__agg_daily_listings") }}
where
dimension in ('by_deal')
and dimension_value <> 'UNSET'
and is_end_of_month = true
),
total_and_retained_revenue as (
select *
from {{ ref("int_kpis__agg_monthly_total_and_retained_revenue") }}
where dimension in ('by_deal') and dimension_value <> 'UNSET'
),
guest_payments as (
select *
from {{ ref("int_kpis__agg_monthly_guest_payments") }}
where dimension in ('by_deal') and dimension_value <> 'UNSET'
),
invoiced_revenue as (
select *
from {{ ref("int_kpis__agg_monthly_invoiced_revenue") }}
where dimension in ('by_deal') and dimension_value <> 'UNSET'
),
host_resolutions as (
select *
from {{ ref("int_kpis__agg_monthly_host_resolutions") }}
where dimension in ('by_deal') and dimension_value <> 'UNSET'
),
deal_history_from_previous_months as (
select select
date, d.year,
id_deal, d.month,
client_type, d.date,
business_scope, date_trunc('month', d.date)::date as first_day_month,
main_deal_name, -- DEAL STATIC ATTRIBUTES --
has_active_pms, ikdd.id_deal,
active_pms_list, ikdd.client_type,
active_accommodations_per_deal_segmentation, ikdd.main_deal_name,
main_billing_country_iso_3_per_deal, ikdd.has_active_pms,
deal_lifecycle_state, ikdd.active_pms_list,
'Previous month' as time_window, ikdd.main_billing_country_iso_3_per_deal,
{{ -- DEAL LIFECYCLE --
calculate_aggregation_between_preceeding_x_and_y( deal_lifecycle.deal_lifecycle_state,
"date", "min", "id_deal", "date", 1, 1 -- ACTIVE ACCOMMODATIONS SEGMENTATION --
) coalesce(
}}, dda.active_accommodations_per_deal_segmentation, 'UNSET'
{{ ) as active_accommodations_per_deal_segmentation,
calculate_aggregation_between_preceeding_x_and_y( -- DEAL BUSINESS SCOPE
"date", "max", "id_deal", "date", 1, 1 case
) when ikdd.client_type = 'API'
}}, then 'API'
{{ when ikdd.client_type = 'PLATFORM'
calculate_aggregation_between_preceeding_x_and_y( then
"created_bookings", "sum", "id_deal", "date", 1, 1 case
) when
}}, ikdd.id_deal is not null
{{ and d.date >= ikdd.min_user_in_new_dash_since_date_utc
calculate_aggregation_between_preceeding_x_and_y( then 'New Dash'
"listings_booked_in_month", "avg", "id_deal", "date", 1, 1 else 'Old Dash'
) end
}}, else 'UNSET'
{{ end as business_scope,
calculate_aggregation_between_preceeding_x_and_y( -- METRICS --
"total_revenue_in_gbp", "sum", "id_deal", "date", 1, 1 coalesce(
) total_and_retained_revenue.total_revenue_in_gbp, 0
}}, ) as total_revenue_in_gbp,
{{ coalesce(
calculate_aggregation_between_preceeding_x_and_y( total_and_retained_revenue.revenue_retained_in_gbp, 0
"total_guest_payments_in_gbp", "sum", "id_deal", "date", 1, 1 ) as revenue_retained_in_gbp,
) coalesce(
}}, total_and_retained_revenue.revenue_retained_post_resolutions_in_gbp, 0
{{ ) as revenue_retained_post_resolutions_in_gbp,
calculate_aggregation_between_preceeding_x_and_y( coalesce(
"xero_operator_net_fees_in_gbp", "sum", "id_deal", "date", 1, 1 guest_payments.total_guest_payments_in_gbp, 0
) ) as total_guest_payments_in_gbp,
}}, coalesce(
{{ invoiced_revenue.xero_operator_net_fees_in_gbp, 0
calculate_aggregation_between_preceeding_x_and_y( ) as xero_operator_net_fees_in_gbp,
"xero_apis_net_fees_in_gbp", "sum", "id_deal", "date", 1, 1 coalesce(
) invoiced_revenue.xero_apis_net_fees_in_gbp, 0
}}, ) as xero_apis_net_fees_in_gbp,
{{ coalesce(
calculate_aggregation_between_preceeding_x_and_y( invoiced_revenue.xero_waiver_paid_back_to_host_in_gbp, 0
"xero_waiver_paid_back_to_host_in_gbp", ) as xero_waiver_paid_back_to_host_in_gbp,
"sum", coalesce(
"id_deal", host_resolutions.xero_host_resolution_amount_paid_in_gbp, 0
"date", ) as xero_host_resolution_amount_paid_in_gbp,
1, coalesce(
1, host_resolutions.xero_host_resolution_payment_count, 0
) ) as xero_host_resolution_payment_count,
}}, coalesce(created_bookings.created_bookings, 0) as created_bookings,
{{ listings.listings_booked_in_month
calculate_aggregation_between_preceeding_x_and_y( from int_kpis__agg_dates_main_kpis d
"xero_host_resolution_amount_paid_in_gbp", left join int_kpis__dimension_deals ikdd on d.dimension_value = ikdd.id_deal
"sum", left join
"id_deal", int_kpis__dimension_daily_accommodation as dda
"date", on d.date = dda.date
1, and d.dimension_value = dda.id_deal
1, left join
) int_kpis__lifecycle_daily_deal deal_lifecycle
}}, on d.date = deal_lifecycle.date
{{ and d.dimension_value = deal_lifecycle.id_deal
calculate_aggregation_between_preceeding_x_and_y( left join
"xero_host_resolution_payment_count", created_bookings
"sum", on d.date = created_bookings.end_date
"id_deal", and d.dimension_value = created_bookings.dimension_value
"date", left join
1, listings
1, on d.date = listings.date
) and d.dimension_value = listings.dimension_value
}}, left join
{{ total_and_retained_revenue
calculate_aggregation_between_preceeding_x_and_y( on d.date = total_and_retained_revenue.end_date
"revenue_retained_in_gbp", "sum", "id_deal", "date", 1, 1 and d.dimension_value = total_and_retained_revenue.dimension_value
) left join
}}, guest_payments
{{ on d.date = guest_payments.end_date
calculate_aggregation_between_preceeding_x_and_y( and d.dimension_value = guest_payments.dimension_value
"revenue_retained_post_resolutions_in_gbp", left join
"sum", invoiced_revenue
"id_deal", on d.date = invoiced_revenue.end_date
"date", and d.dimension_value = invoiced_revenue.dimension_value
1, left join
1, host_resolutions
) on d.date = host_resolutions.end_date
}} and d.dimension_value = host_resolutions.dimension_value
from int_monthly_aggregated_metrics_history_by_deal
), ),
metric_aggregation_by_deal as ( metric_aggregation_by_deal as (
select * {% for time_window in time_window_aggregations %}
from metric_aggregation_all_history {% set from = time_window.preceeding_from | int %}
union all {% set to = time_window.preceeding_to | int %}
select * {% set include_history = time_window.include_all_history %}
from metric_aggregation_previous_12_months select
union all date,
select * id_deal,
from metric_aggregation_previous_6_months client_type,
union all business_scope,
select * main_deal_name,
from metric_aggregation_previous_3_months has_active_pms,
union all active_pms_list,
select * active_accommodations_per_deal_segmentation,
from metric_aggregation_previous_1_month main_billing_country_iso_3_per_deal,
deal_lifecycle_state,
'{{ time_window.time_window_name }}' as time_window,
{{
calculate_aggregation_between_preceeding_x_and_y(
"date",
"min",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"date",
"max",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"created_bookings",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"listings_booked_in_month",
"avg",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_revenue_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"total_guest_payments_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_operator_net_fees_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_apis_net_fees_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_waiver_paid_back_to_host_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_amount_paid_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"xero_host_resolution_payment_count",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}},
{{
calculate_aggregation_between_preceeding_x_and_y(
"revenue_retained_post_resolutions_in_gbp",
"sum",
"id_deal",
"date",
from,
to,
include_history,
)
}}
from deal_history_from_previous_months
{% if not loop.last %}
union all
{% endif %}
{% endfor %}
) )
select select
-- Primary key -- Primary key