package revenue import ( "github.com/damirmukimov/city_resource_graph/models/customer" "github.com/damirmukimov/city_resource_graph/models/params" ) // RevenueBreakdown represents all revenue streams for a given year. // Revenue paths are separated into distinct components as specified. type RevenueBreakdown struct { // Path 1: SaaS Subscription Revenue Subscription SubscriptionRevenue `json:"subscription"` // Path 2: Market/Transaction Revenue Transaction TransactionRevenue `json:"transaction"` // Path 3: Public/Municipal Revenue Municipal MunicipalRevenue `json:"municipal"` // Path 4: Implementation Services Revenue Implementation ImplementationRevenue `json:"implementation"` // Total across all paths Total float64 `json:"total"` } // SubscriptionRevenue represents SaaS subscription revenue. type SubscriptionRevenue struct { BasicARR float64 `json:"basic_arr"` // Annual recurring revenue from Basic tier BusinessARR float64 `json:"business_arr"` // Annual recurring revenue from Business tier EnterpriseARR float64 `json:"enterprise_arr"` // Annual recurring revenue from Enterprise tier TotalARR float64 `json:"total_arr"` // Total subscription ARR } // TransactionRevenue represents marketplace and transaction revenue. type TransactionRevenue struct { IntroRevenue float64 `json:"intro_revenue"` // Introduction fees revenue ServiceRevenue float64 `json:"service_revenue"` // Service marketplace commission GroupRevenue float64 `json:"group_revenue"` // Group buying commission Total float64 `json:"total"` // Total transaction revenue } // MunicipalRevenue represents municipal license and data licensing revenue. type MunicipalRevenue struct { LicenseRevenue float64 `json:"license_revenue"` // Municipal license fees DataLicensing float64 `json:"data_licensing"` // Data licensing revenue Total float64 `json:"total"` // Total municipal revenue } // ImplementationRevenue represents implementation services revenue. type ImplementationRevenue struct { Matches float64 `json:"matches"` // Total matches (derived) PaidImpls float64 `json:"paid_impls"` // Paid implementations (derived) Total float64 `json:"total"` // Total implementation revenue } // CalculateRevenue computes all revenue streams for a given year. func CalculateRevenue(year int, custMetrics customer.CustomerMetrics, tierDist customer.TierDistribution, p *params.Params) RevenueBreakdown { // Path 1: SaaS Subscription Revenue subRev := calculateSubscriptionRevenue(year, tierDist, p) // Path 2: Market/Transaction Revenue txRev := calculateTransactionRevenue(year, p) // Path 3: Public/Municipal Revenue munRev := calculateMunicipalRevenue(year, p) // Path 4: Implementation Services Revenue implRev := calculateImplementationRevenue(custMetrics, p) total := subRev.TotalARR + txRev.Total + munRev.Total + implRev.Total return RevenueBreakdown{ Subscription: subRev, Transaction: txRev, Municipal: munRev, Implementation: implRev, Total: total, } } // calculateSubscriptionRevenue computes SaaS subscription revenue. // Formula: ARR_tier = Customers_tier × Monthly_Price × 12 × (1 + Blended_Uplift) func calculateSubscriptionRevenue(year int, tierDist customer.TierDistribution, p *params.Params) SubscriptionRevenue { basicARR := float64(tierDist.Basic) * p.Pricing.Basic * 12.0 * (1.0 + p.Pricing.BlendedUplift.Basic) businessARR := float64(tierDist.Business) * p.Pricing.Business * 12.0 * (1.0 + p.Pricing.BlendedUplift.Business) enterpriseARR := float64(tierDist.Enterprise) * p.Pricing.Enterprise * 12.0 * (1.0 + p.Pricing.BlendedUplift.Enterprise) return SubscriptionRevenue{ BasicARR: basicARR, BusinessARR: businessARR, EnterpriseARR: enterpriseARR, TotalARR: basicARR + businessARR + enterpriseARR, } } // calculateTransactionRevenue computes marketplace and transaction revenue. // Formula: // - Intro Revenue = Intros × Avg_Fee × Conversion_Rate // - Service Revenue = Service_GMV × Commission_Rate // - Group Revenue = Group_GMV × Commission_Rate func calculateTransactionRevenue(year int, p *params.Params) TransactionRevenue { txp := p.Transactions introRev := float64(txp.IntrosPerYear.GetYear(year)) * txp.AvgIntroFee * txp.IntroConversion.GetYear(year) serviceRev := txp.ServiceGMV.GetYear(year) * txp.ServiceCommission groupRev := txp.GroupGMV.GetYear(year) * txp.GroupCommission return TransactionRevenue{ IntroRevenue: introRev, ServiceRevenue: serviceRev, GroupRevenue: groupRev, Total: introRev + serviceRev + groupRev, } } // calculateMunicipalRevenue computes municipal license and data licensing revenue. // Formula: // - License Revenue = Cities × Avg_License // - Data Licensing = Data_Licensing_Value func calculateMunicipalRevenue(year int, p *params.Params) MunicipalRevenue { mp := p.Municipal licenseRev := float64(mp.Cities.GetYear(year)) * mp.AvgLicense.GetYear(year) dataLicensing := mp.DataLicensing.GetYear(year) return MunicipalRevenue{ LicenseRevenue: licenseRev, DataLicensing: dataLicensing, Total: licenseRev + dataLicensing, } } // calculateImplementationRevenue computes implementation services revenue. // Formula: // - Matches = Total_Orgs × Matches_Per_Org // - Paid_Impls = Matches × Paid_Share // - Revenue = Paid_Impls × Avg_Fee func calculateImplementationRevenue(custMetrics customer.CustomerMetrics, p *params.Params) ImplementationRevenue { ip := p.ImplServices matches := float64(custMetrics.TotalOrgs) * ip.MatchesPerOrg paidImpls := matches * ip.PaidShare revenue := paidImpls * ip.AvgFee return ImplementationRevenue{ Matches: matches, PaidImpls: paidImpls, Total: revenue, } } // GetPlatformOnlyRevenue returns revenue from SaaS + Municipal only. // This excludes transaction and implementation revenue. func GetPlatformOnlyRevenue(rev RevenueBreakdown) float64 { return rev.Subscription.TotalARR + rev.Municipal.Total } // GetFullRevenue returns total revenue including all paths. func GetFullRevenue(rev RevenueBreakdown) float64 { return rev.Total }