diff --git a/models/reporting/general/monthly_account_revenue_impact_from_growth.sql b/models/reporting/general/monthly_account_revenue_impact_from_growth.sql new file mode 100644 index 0000000..38702a1 --- /dev/null +++ b/models/reporting/general/monthly_account_revenue_impact_from_growth.sql @@ -0,0 +1,75 @@ +{% set major_decline_status = "MAJOR DECLINE" %} +with + int_monthly_account_revenue_impact_from_growth as ( + select * from {{ ref("int_monthly_account_revenue_impact_from_growth") }} + ) +select + start_date as start_date, + end_date as end_date, + id_deal as id_deal, + deal as deal, + client_type as client_type, + has_active_pms as has_active_pms, + active_pms_list as active_pms_list, + main_billing_country_iso_3_per_deal as main_billing_country_iso_3_per_deal, + deal_lifecycle_state as deal_lifecycle_state, + deal_hubspot_stage as deal_hubspot_stage, + account_manager as account_manager, + live_date_utc as live_date_utc, + cancellation_date_utc as cancellation_date_utc, + round(growth_score, 8) as growth_score, + round(impact_score_total_revenue, 8) as impact_score_total_revenue, + round( + impact_score_revenue_retained_post_resolutions, 8 + ) as impact_score_revenue_retained_post_resolutions, + categorisation_impact_score_revenue_retained_post_resolutions + as categorisation_impact_score_revenue_retained_post_resolutions, + rank_impact_score_total_revenue as rank_impact_score_total_revenue, + rank_impact_score_revenue_retained_post_resolutions + as rank_impact_score_revenue_retained_post_resolutions, + current_month_total_revenue_in_gbp as current_month_total_revenue_in_gbp, + round( + rolling_12_months_total_revenue_in_gbp, 2 + ) as rolling_12_months_total_revenue_in_gbp, + share_total_revenue_rolling_12_months as share_total_revenue_rolling_12_months, + rank_total_revenue_rolling_12_months as rank_total_revenue_rolling_12_months, + current_month_revenue_retained_post_resolutions_in_gbp + as current_month_revenue_retained_post_resolutions_in_gbp, + round( + rolling_12_months_revenue_retained_post_resolutions_in_gbp, 2 + ) as rolling_12_months_revenue_retained_post_resolutions_in_gbp, + share_revenue_retained_post_resolutions_rolling_12_months + as share_revenue_retained_post_resolutions_rolling_12_months, + rank_revenue_retained_post_resolutions_rolling_12_months + as rank_revenue_retained_post_resolutions_rolling_12_months, + current_month_billable_items as current_month_billable_items, + share_billable_items_current_month as share_billable_items_current_month, + rank_billable_items_current_month as rank_billable_items_current_month, + projection_mean_absolute_error as projection_mean_absolute_error, + projection_mean_absolute_percentage_error + as projection_mean_absolute_percentage_error, + -- Transform boolean values to 0/1 for reporting purposes + case + when are_billable_items_projected then 1 else 0 + end as are_billable_items_projected, + case + when is_growth_score_overridden_due_to_cancellation then 1 else 0 + end as is_growth_score_overridden_due_to_cancellation, + -- Additional columns for reporting purposes + case + when date_trunc('month', start_date) = date_trunc('month', current_date) + then 1 + else 0 + end as is_ongoing_month, + case + when + categorisation_impact_score_revenue_retained_post_resolutions + = '{{ major_decline_status }}' + and lag( + categorisation_impact_score_revenue_retained_post_resolutions, 1 + ) over (partition by id_deal order by end_date asc) + != '{{ major_decline_status }}' + then 1 + else 0 + end as has_account_switched_to_major_decline +from int_monthly_account_revenue_impact_from_growth diff --git a/models/reporting/general/schema.yml b/models/reporting/general/schema.yml index 41d857d..f882d4b 100644 --- a/models/reporting/general/schema.yml +++ b/models/reporting/general/schema.yml @@ -2522,3 +2522,309 @@ models: Relative_increment value multiplied by -1 in case this metric's growth doesn't have a positive impact for Truvi, otherwise is equal to relative_increment. This value is specially created for formatting in PBI + + - name: monthly_account_revenue_impact_from_growth + description: | + This model provides the monthly revenue impact from the growth of + billable items for each deal. The revenue impact is computed as the + product of the growth score and the deal contribution to the total revenue + in the previous 12 months. + + There's 2 impact scores computed depending on the revenue metric, namely: + - impact_score_total_revenue: based on Total Revenue + - impact_score_revenue_retained_post_resolutions: based on Revenue Retained + Post Resolutions + + It is important to note that if we check the ongoing month, the count of + billable items and the corresponding share will be based on the projection, + rather than the actual figure. In this case, the MAE and MAPE of the projected + value are indicated in the model. + + While the growth and impact scores are computed at a monthly basis, their values + will update every day with the latest available projection. + + data_tests: + - dbt_utils.unique_combination_of_columns: + combination_of_columns: + - end_date + - id_deal + - dbt_utils.unique_combination_of_columns: + combination_of_columns: + - start_date + - id_deal + + columns: + - name: start_date + data_type: date + description: | + Start date of the period for which the revenue impact is computed. + Corresponds to the first day of the month. + data_tests: + - not_null + + - name: end_date + data_type: date + description: | + End date of the period for which the revenue impact is computed. + Corresponds to the last day of the month. + data_tests: + - not_null + + - name: id_deal + data_type: string + description: | + Unique ID for a deal, or account. + data_tests: + - not_null + + - name: deal + data_type: string + description: | + Concatenation of the deal ID and the deal name. + + - name: client_type + data_type: string + description: | + Type of the client, PLATFORM or API. + + - name: has_active_pms + data_type: boolean + description: | + Flag indicating if the deal has an active PMS or not. + + - name: active_pms_list + data_type: string + description: | + List of active PMS for the deal. It can be null if the deal has no + active PMS. + + - name: main_billing_country_iso_3_per_deal + data_type: string + description: | + Main billing country for the deal. It can be null. + + - name: deal_lifecycle_state + data_type: string + description: | + Lifecycle state of the deal. + + - name: deal_hubspot_stage + data_type: string + description: | + Hubspot stage of the deal. + + - name: account_manager + data_type: string + description: | + Account manager of the deal. It can be null. + + - name: live_date_utc + data_type: date + description: | + Live date of the deal according to HubSpot. It can be null. + + - name: cancellation_date_utc + data_type: date + description: | + Cancellation date of the deal according to HubSpot. It can be null. + + - name: growth_score + data_type: decimal + description: | + Growth score of the billable items, based on the average between: + - The billable items of a given month vs. the average of the previous + 3 months. + - The share a deal has in terms of billable items of a given month + if compared to the rest of the deals vs. the average of the previous 3 + months. + The growth score is capped between -1 and 1. + It can be overridden to -1 in case the deal is cancelled in the same month. + It cannot be null. + data_tests: + - not_null + - dbt_expectations.expect_column_values_to_be_between: + min_value: -1 + max_value: 1 + strictly: false + + - name: impact_score_total_revenue + data_type: decimal + description: | + Impact score of the growth score on the total revenue. + It is computed as the product of the growth score and the deal + contribution to the total revenue in the previous 12 months. + It cannot be null. + data_tests: + - not_null + - dbt_expectations.expect_column_values_to_be_between: + min_value: -1 + max_value: 1 + strictly: false + + - name: impact_score_revenue_retained_post_resolutions + data_type: decimal + description: | + Impact score of the growth score on the revenue retained post + resolutions. It is computed as the product of the growth score and + the deal contribution to the revenue retained post resolutions in + the previous 12 months. + It cannot be null. + data_tests: + - not_null + - dbt_expectations.expect_column_values_to_be_between: + min_value: -1 + max_value: 1 + strictly: false + + - name: categorisation_impact_score_revenue_retained_post_resolutions + data_type: string + description: | + Categorisation of the impact score on the revenue retained post + resolutions. It cannot be null. + data_tests: + - not_null + - accepted_values: + values: + - MAJOR DECLINE + - DECLINE + - FLAT + - GAIN + - MAJOR GAIN + + - name: rank_impact_score_total_revenue + data_type: integer + description: | + Monthly rank of the deal in terms of impact score on the total revenue. + + - name: rank_impact_score_revenue_retained_post_resolutions + data_type: integer + description: | + Monthly rank of the deal in terms of impact score on the revenue + retained post resolutions. + + - name: current_month_total_revenue_in_gbp + data_type: decimal + description: | + Total revenue in GBP for the current month. + If the month is in progress then this value will be null. + + - name: rolling_12_months_total_revenue_in_gbp + data_type: decimal + description: | + Total revenue in GBP for the previous 12 months. + It can be null. + + - name: share_total_revenue_rolling_12_months + data_type: decimal + description: | + Share of the deal in terms of total revenue in the previous 12 months. + It cannot be null. + data_tests: + - not_null + + - name: rank_total_revenue_rolling_12_months + data_type: integer + description: | + Monthly rank of the deal in terms of total revenue in the previous + 12 months. + + - name: current_month_revenue_retained_post_resolutions_in_gbp + data_type: decimal + description: | + Revenue retained post resolutions in GBP for the current month. + If the month is in progress then this value will be null. + + - name: rolling_12_months_revenue_retained_post_resolutions_in_gbp + data_type: decimal + description: | + Revenue retained post resolutions in GBP for the previous 12 months. + It can be null. + + - name: share_revenue_retained_post_resolutions_rolling_12_months + data_type: decimal + description: | + Share of the deal in terms of revenue retained post resolutions in + the previous 12 months. + It cannot be null. + data_tests: + - not_null + + - name: rank_revenue_retained_post_resolutions_rolling_12_months + data_type: integer + description: | + Monthly rank of the deal in terms of revenue retained post + resolutions in the previous 12 months. + + - name: current_month_billable_items + data_type: integer + description: | + Monthly billable items. If the month is in progress + then this value might be projected. + data_tests: + - dbt_expectations.expect_column_values_to_be_between: + min_value: 0 + strictly: false + + - name: share_billable_items_current_month + data_type: decimal + description: | + Share of the billable items for a given deal in the current month. + If the month is in progress then this value might be projected. + data_tests: + - dbt_expectations.expect_column_values_to_be_between: + min_value: 0 + strictly: false + + - name: rank_billable_items_current_month + data_type: integer + description: | + Monthly rank of the deal in terms of billable items in the current month. + If the month is in progress then this value might be projected. + + - name: projection_mean_absolute_error + data_type: decimal + description: | + Mean absolute error of the projection of the billable items. + It is null if the month is not in progress or value is projected + but there's no prior data to compare the projection against. + data_tests: + - dbt_expectations.expect_column_values_to_be_between: + min_value: 0 + strictly: false + + - name: projection_mean_absolute_percentage_error + data_type: decimal + description: | + Mean absolute percentage error of the projection of the billable items. + It is null if the month is not in progress or value is projected + but there's no prior data to compare the projection against. + data_tests: + - dbt_expectations.expect_column_values_to_be_between: + min_value: 0 + strictly: false + + - name: are_billable_items_projected + data_type: integer + description: | + Flag indicating if the billable items are projected or not. + If the month is in progress then this value might be projected. + It can be null if there's no projection for that deal. + + - name: is_growth_score_overridden_due_to_cancellation + data_type: integer + description: | + Flag indicating if the growth score is overridden to -1 due to + cancellation in the same month. + + - name: is_ongoing_month + data_type: integer + description: | + Flag indicating if the month is in progress or not. + 1 for yes, 0 for no. + + - name: has_account_switched_to_major_decline + data_type: integer + description: | + Flag indicating if the account has switched to major decline in the + current month. + 1 for yes, 0 for no.