mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Initialize git repository - Add comprehensive .gitignore for Go projects - Install golangci-lint v2.6.0 (latest v2) globally - Configure .golangci.yml with appropriate linters and formatters - Fix all formatting issues (gofmt) - Fix all errcheck issues (unchecked errors) - Adjust complexity threshold for validation functions - All checks passing: build, test, vet, lint
109 lines
4.0 KiB
Go
109 lines
4.0 KiB
Go
package customer
|
|
|
|
import (
|
|
"github.com/damirmukimov/city_resource_graph/models/params"
|
|
)
|
|
|
|
// CustomerMetrics represents customer adoption metrics for a given year.
|
|
type CustomerMetrics struct {
|
|
TotalOrgs int `json:"total_orgs"` // Total active organizations (after churn)
|
|
PayingOrgs int `json:"paying_orgs"` // Active paying organizations
|
|
FreeOrgs int `json:"free_orgs"` // Active free tier organizations
|
|
PayingShare float64 `json:"paying_share"` // Percentage paying (0.0-1.0)
|
|
NewAcquisitions int `json:"new_acquisitions"` // New organizations acquired this year
|
|
ChurnedOrgs int `json:"churned_orgs"` // Organizations that churned this year
|
|
CumulativeOrgs int `json:"cumulative_orgs"` // Cumulative organizations ever acquired
|
|
}
|
|
|
|
// TierDistribution represents the distribution of paying customers across tiers.
|
|
type TierDistribution struct {
|
|
Basic int `json:"basic"` // Number of Basic tier customers
|
|
Business int `json:"business"` // Number of Business tier customers
|
|
Enterprise int `json:"enterprise"` // Number of Enterprise tier customers
|
|
Total int `json:"total"` // Total paying customers
|
|
}
|
|
|
|
// ChurnMetrics represents churn and retention metrics per tier.
|
|
type ChurnMetrics struct {
|
|
Basic TierChurn `json:"basic"`
|
|
Business TierChurn `json:"business"`
|
|
Enterprise TierChurn `json:"enterprise"`
|
|
}
|
|
|
|
// TierChurn represents churn metrics for a single tier.
|
|
type TierChurn struct {
|
|
AnnualChurn float64 `json:"annual_churn"` // Annual churn rate (0.0-1.0)
|
|
Retention float64 `json:"retention"` // Retention rate (1.0 - churn)
|
|
AvgLifetimeMonths int `json:"avg_lifetime_months"` // Average customer lifetime in months
|
|
}
|
|
|
|
// DefaultChurnMetrics returns default churn metrics per tier.
|
|
func DefaultChurnMetrics() ChurnMetrics {
|
|
return ChurnMetrics{
|
|
Basic: TierChurn{
|
|
AnnualChurn: 0.15, // 15%
|
|
Retention: 0.85, // 85%
|
|
AvgLifetimeMonths: 48, // 4 years (conservative)
|
|
},
|
|
Business: TierChurn{
|
|
AnnualChurn: 0.10, // 10%
|
|
Retention: 0.90, // 90%
|
|
AvgLifetimeMonths: 64, // 5.3 years (conservative)
|
|
},
|
|
Enterprise: TierChurn{
|
|
AnnualChurn: 0.05, // 5%
|
|
Retention: 0.95, // 95%
|
|
AvgLifetimeMonths: 80, // 6.7 years (conservative)
|
|
},
|
|
}
|
|
}
|
|
|
|
// CalculateCustomerMetrics computes customer adoption metrics for a given year.
|
|
func CalculateCustomerMetrics(year int, p *params.Params) CustomerMetrics {
|
|
totalOrgs := p.Adoption.TotalOrgs.GetYear(year)
|
|
payingShare := p.Adoption.PayingShare.GetYear(year)
|
|
|
|
payingOrgs := int(float64(totalOrgs) * payingShare)
|
|
freeOrgs := totalOrgs - payingOrgs
|
|
|
|
// For churn modeling, estimate new acquisitions vs cumulative
|
|
// In a simplified model, assume all customers are "new" for the target year
|
|
// Churn rates are used in LTV calculations rather than reducing active customers
|
|
newAcquisitions := totalOrgs
|
|
churnedOrgs := 0 // Not modeled as reducing active base in this simplified approach
|
|
cumulativeOrgs := totalOrgs // Simplified - doesn't track across years
|
|
|
|
return CustomerMetrics{
|
|
TotalOrgs: totalOrgs,
|
|
PayingOrgs: payingOrgs,
|
|
FreeOrgs: freeOrgs,
|
|
PayingShare: payingShare,
|
|
NewAcquisitions: newAcquisitions,
|
|
ChurnedOrgs: churnedOrgs,
|
|
CumulativeOrgs: cumulativeOrgs,
|
|
}
|
|
}
|
|
|
|
// CalculateTierDistribution computes the distribution of paying customers across tiers.
|
|
func CalculateTierDistribution(year int, payingOrgs int, p *params.Params) TierDistribution {
|
|
tierMix := p.Pricing.TierMix.GetYear(year)
|
|
|
|
basic := int(float64(payingOrgs) * tierMix.Basic)
|
|
business := int(float64(payingOrgs) * tierMix.Business)
|
|
enterprise := int(float64(payingOrgs) * tierMix.Enterprise)
|
|
|
|
// Handle rounding - ensure total matches
|
|
total := basic + business + enterprise
|
|
if total != payingOrgs {
|
|
// Adjust basic tier to account for rounding differences
|
|
basic += payingOrgs - total
|
|
}
|
|
|
|
return TierDistribution{
|
|
Basic: basic,
|
|
Business: business,
|
|
Enterprise: enterprise,
|
|
Total: payingOrgs,
|
|
}
|
|
}
|