mirror of
https://github.com/andwati/telecom-platform.git
synced 2026-10-23 13:12:16 +00:00
feat: Add rate plan type system with comprehensive domain models, allowances, subscriptions, and analytics support
- Add RatePlan struct with carrier, region, pricing, allowances, features, discounts, and validity fields - Add PlanType enum with prepaid, postpaid, hybrid, pay-as-you-go, and unlimited options - Add PlanStatus enum with draft, active, inactive, archived, and suspended states - Add BillingCycle enum with daily, weekly, monthly, quarterly, and yearly options - Add DataAllowance, VoiceAllowance, and
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
package rateplan
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type RatePlan struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
Name string `json:"name" db:"name"`
|
||||
Description string `json:"description" db:"description"`
|
||||
CarrierID string `json:"carrier_id" db:"carrier_id"`
|
||||
Region string `json:"region" db:"region"`
|
||||
PlanType PlanType `json:"plan_type" db:"plan_type"`
|
||||
Status PlanStatus `json:"status" db:"status"`
|
||||
BasePrice float64 `json:"base_price" db:"base_price"`
|
||||
Currency string `json:"currency" db:"currency"`
|
||||
BillingCycle BillingCycle `json:"billing_cycle" db:"billing_cycle"`
|
||||
DataAllowance *DataAllowance `json:"data_allowance,omitempty" db:"data_allowance"`
|
||||
VoiceAllowance *VoiceAllowance `json:"voice_allowance,omitempty" db:"voice_allowance"`
|
||||
SMSAllowance *SMSAllowance `json:"sms_allowance,omitempty" db:"sms_allowance"`
|
||||
OverageRates *OverageRates `json:"overage_rates,omitempty" db:"overage_rates"`
|
||||
Features []PlanFeature `json:"features,omitempty" db:"features"`
|
||||
ActivationFee float64 `json:"activation_fee" db:"activation_fee"`
|
||||
EarlyTermination *EarlyTermination `json:"early_termination,omitempty" db:"early_termination"`
|
||||
Discounts []Discount `json:"discounts,omitempty" db:"discounts"`
|
||||
ValidFrom time.Time `json:"valid_from" db:"valid_from"`
|
||||
ValidTo *time.Time `json:"valid_to,omitempty" db:"valid_to"`
|
||||
Priority int `json:"priority" db:"priority"`
|
||||
IsActive bool `json:"is_active" db:"is_active"`
|
||||
Metadata map[string]any `json:"metadata,omitempty" db:"metadata"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
type PlanType string
|
||||
|
||||
const (
|
||||
PlanTypePrepaid PlanType = "prepaid"
|
||||
PlanTypePostpaid PlanType = "postpaid"
|
||||
PlanTypeHybrid PlanType = "hybrid"
|
||||
PlanTypePayAsYouGo PlanType = "pay_as_you_go"
|
||||
PlanTypeUnlimited PlanType = "unlimited"
|
||||
)
|
||||
|
||||
type PlanStatus string
|
||||
|
||||
const (
|
||||
PlanStatusDraft PlanStatus = "draft"
|
||||
PlanStatusActive PlanStatus = "active"
|
||||
PlanStatusInactive PlanStatus = "inactive"
|
||||
PlanStatusArchived PlanStatus = "archived"
|
||||
PlanStatusSuspended PlanStatus = "suspended"
|
||||
)
|
||||
|
||||
type BillingCycle string
|
||||
|
||||
const (
|
||||
BillingCycleDaily BillingCycle = "daily"
|
||||
BillingCycleWeekly BillingCycle = "weekly"
|
||||
BillingCycleMonthly BillingCycle = "monthly"
|
||||
BillingCycleQuarterly BillingCycle = "quarterly"
|
||||
BillingCycleYearly BillingCycle = "yearly"
|
||||
)
|
||||
|
||||
type DataAllowance struct {
|
||||
Type DataAllowanceType `json:"type"`
|
||||
Amount int64 `json:"amount"` // in MB or GB depending on type
|
||||
Unit string `json:"unit"` // "MB", "GB", "TB"
|
||||
Unlimited bool `json:"unlimited"`
|
||||
SpeedLimit *int64 `json:"speed_limit,omitempty"` // in Kbps
|
||||
}
|
||||
|
||||
type DataAllowanceType string
|
||||
|
||||
const (
|
||||
DataAllowanceTypeDaily DataAllowanceType = "daily"
|
||||
DataAllowanceTypeMonthly DataAllowanceType = "monthly"
|
||||
DataAllowanceTypeCycle DataAllowanceType = "cycle"
|
||||
DataAllowanceTypeLifetime DataAllowanceType = "lifetime"
|
||||
)
|
||||
|
||||
type VoiceAllowance struct {
|
||||
Type VoiceAllowanceType `json:"type"`
|
||||
Minutes int64 `json:"minutes"`
|
||||
Unlimited bool `json:"unlimited"`
|
||||
Destinations []string `json:"destinations,omitempty"` // country codes
|
||||
}
|
||||
|
||||
type VoiceAllowanceType string
|
||||
|
||||
const (
|
||||
VoiceAllowanceTypeDaily VoiceAllowanceType = "daily"
|
||||
VoiceAllowanceTypeMonthly VoiceAllowanceType = "monthly"
|
||||
VoiceAllowanceTypeCycle VoiceAllowanceType = "cycle"
|
||||
VoiceAllowanceTypeUnlimited VoiceAllowanceType = "unlimited"
|
||||
)
|
||||
|
||||
type SMSAllowance struct {
|
||||
Type SMSAllowanceType `json:"type"`
|
||||
Messages int64 `json:"messages"`
|
||||
Unlimited bool `json:"unlimited"`
|
||||
Destinations []string `json:"destinations,omitempty"` // country codes
|
||||
}
|
||||
|
||||
type SMSAllowanceType string
|
||||
|
||||
const (
|
||||
SMSAllowanceTypeDaily SMSAllowanceType = "daily"
|
||||
SMSAllowanceTypeMonthly SMSAllowanceType = "monthly"
|
||||
SMSAllowanceTypeCycle SMSAllowanceType = "cycle"
|
||||
SMSAllowanceTypeUnlimited SMSAllowanceType = "unlimited"
|
||||
)
|
||||
|
||||
type OverageRates struct {
|
||||
DataRate float64 `json:"data_rate"` // per MB
|
||||
VoiceRate float64 `json:"voice_rate"` // per minute
|
||||
SMSRate float64 `json:"sms_rate"` // per message
|
||||
Currency string `json:"currency"`
|
||||
}
|
||||
|
||||
type PlanFeature struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Config map[string]interface{} `json:"config,omitempty"`
|
||||
}
|
||||
|
||||
type EarlyTermination struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
FeeType string `json:"fee_type"` // "fixed", "percentage", "remaining_months"
|
||||
FeeAmount float64 `json:"fee_amount"` // for fixed fee type
|
||||
FeePercentage float64 `json:"fee_percentage"` // for percentage fee type
|
||||
MinMonths int `json:"min_months"` // minimum months before termination fee applies
|
||||
}
|
||||
|
||||
type Discount struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type DiscountType `json:"type"`
|
||||
Value float64 `json:"value"`
|
||||
ValidFrom time.Time `json:"valid_from"`
|
||||
ValidTo *time.Time `json:"valid_to,omitempty"`
|
||||
Conditions string `json:"conditions,omitempty"`
|
||||
IsActive bool `json:"is_active"`
|
||||
}
|
||||
|
||||
type DiscountType string
|
||||
|
||||
const (
|
||||
DiscountTypePercentage DiscountType = "percentage"
|
||||
DiscountTypeFixed DiscountType = "fixed"
|
||||
DiscountTypeRecurring DiscountType = "recurring"
|
||||
)
|
||||
|
||||
// RatePlanUsage tracks actual usage against a rate plan
|
||||
type RatePlanUsage struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
RatePlanID string `json:"rate_plan_id" db:"rate_plan_id"`
|
||||
ProfileID string `json:"profile_id" db:"profile_id"`
|
||||
CycleStart time.Time `json:"cycle_start" db:"cycle_start"`
|
||||
CycleEnd time.Time `json:"cycle_end" db:"cycle_end"`
|
||||
DataUsed int64 `json:"data_used" db:"data_used"` // in MB
|
||||
VoiceUsed int64 `json:"voice_used" db:"voice_used"` // in minutes
|
||||
SMSUsed int64 `json:"sms_used" db:"sms_used"` // count
|
||||
LastUpdated time.Time `json:"last_updated" db:"last_updated"`
|
||||
}
|
||||
|
||||
// RatePlanSubscription represents an active subscription to a rate plan
|
||||
type RatePlanSubscription struct {
|
||||
ID string `json:"id" db:"id"`
|
||||
ProfileID string `json:"profile_id" db:"profile_id"`
|
||||
RatePlanID string `json:"rate_plan_id" db:"rate_plan_id"`
|
||||
Status SubscriptionStatus `json:"status" db:"status"`
|
||||
StartedAt time.Time `json:"started_at" db:"started_at"`
|
||||
EndedAt *time.Time `json:"ended_at,omitempty" db:"ended_at"`
|
||||
BillingCycle BillingCycle `json:"billing_cycle" db:"billing_cycle"`
|
||||
NextBillingDate time.Time `json:"next_billing_date" db:"next_billing_date"`
|
||||
AutoRenew bool `json:"auto_renew" db:"auto_renew"`
|
||||
CurrentCycle time.Time `json:"current_cycle" db:"current_cycle"`
|
||||
AppliedDiscounts []string `json:"applied_discounts,omitempty" db:"applied_discounts"`
|
||||
Metadata map[string]any `json:"metadata,omitempty" db:"metadata"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
// SubscriptionStatus defines the status of a subscription
|
||||
type SubscriptionStatus string
|
||||
|
||||
const (
|
||||
SubscriptionStatusActive SubscriptionStatus = "active"
|
||||
SubscriptionStatusSuspended SubscriptionStatus = "suspended"
|
||||
SubscriptionStatusCancelled SubscriptionStatus = "cancelled"
|
||||
SubscriptionStatusExpired SubscriptionStatus = "expired"
|
||||
SubscriptionStatusPending SubscriptionStatus = "pending"
|
||||
)
|
||||
|
||||
// RatePlanFilter defines filtering options for rate plan queries
|
||||
type RatePlanFilter struct {
|
||||
CarrierID string `json:"carrier_id,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
PlanType PlanType `json:"plan_type,omitempty"`
|
||||
Status PlanStatus `json:"status,omitempty"`
|
||||
MinPrice float64 `json:"min_price,omitempty"`
|
||||
MaxPrice float64 `json:"max_price,omitempty"`
|
||||
IsActive *bool `json:"is_active,omitempty"`
|
||||
ValidFrom *time.Time `json:"valid_from,omitempty"`
|
||||
ValidTo *time.Time `json:"valid_to,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
SortBy string `json:"sort_by,omitempty"`
|
||||
SortOrder string `json:"sort_order,omitempty"`
|
||||
}
|
||||
|
||||
// RatePlanCostCalculation represents the result of cost calculation
|
||||
type RatePlanCostCalculation struct {
|
||||
RatePlanID string `json:"rate_plan_id"`
|
||||
BaseCost float64 `json:"base_cost"`
|
||||
OverageCost float64 `json:"overage_cost"`
|
||||
DiscountCost float64 `json:"discount_cost"`
|
||||
TotalCost float64 `json:"total_cost"`
|
||||
Currency string `json:"currency"`
|
||||
Breakdown map[string]any `json:"breakdown"`
|
||||
CalculatedAt time.Time `json:"calculated_at"`
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package rateplan
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// SubscriptionFilter defines filtering options for subscription queries
|
||||
type SubscriptionFilter struct {
|
||||
Status SubscriptionStatus `json:"status,omitempty"`
|
||||
RatePlanID string `json:"rate_plan_id,omitempty"`
|
||||
StartedAfter *time.Time `json:"started_after,omitempty"`
|
||||
StartedBefore *time.Time `json:"started_before,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
}
|
||||
|
||||
// UsageAnalyticsFilter defines filtering options for usage analytics
|
||||
type UsageAnalyticsFilter struct {
|
||||
RatePlanID string `json:"rate_plan_id,omitempty"`
|
||||
CarrierID string `json:"carrier_id,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
GroupBy string `json:"group_by,omitempty"` // "day", "week", "month"
|
||||
}
|
||||
|
||||
// RevenueAnalyticsFilter defines filtering options for revenue analytics
|
||||
type RevenueAnalyticsFilter struct {
|
||||
RatePlanID string `json:"rate_plan_id,omitempty"`
|
||||
CarrierID string `json:"carrier_id,omitempty"`
|
||||
Region string `json:"region,omitempty"`
|
||||
StartDate time.Time `json:"start_date"`
|
||||
EndDate time.Time `json:"end_date"`
|
||||
GroupBy string `json:"group_by,omitempty"` // "day", "week", "month"
|
||||
}
|
||||
|
||||
// UsageAnalytics contains usage statistics
|
||||
type UsageAnalytics struct {
|
||||
TotalDataUsed int64 `json:"total_data_used"`
|
||||
TotalVoiceUsed int64 `json:"total_voice_used"`
|
||||
TotalSMSUsed int64 `json:"total_sms_used"`
|
||||
ActiveUsers int `json:"active_users"`
|
||||
AverageUsage map[string]float64 `json:"average_usage"`
|
||||
UsageByPlan map[string]int64 `json:"usage_by_plan"`
|
||||
UsageByRegion map[string]int64 `json:"usage_by_region"`
|
||||
TimelineData []TimelineDataPoint `json:"timeline_data"`
|
||||
}
|
||||
|
||||
// RevenueAnalytics contains revenue statistics
|
||||
type RevenueAnalytics struct {
|
||||
TotalRevenue float64 `json:"total_revenue"`
|
||||
RevenueByPlan map[string]float64 `json:"revenue_by_plan"`
|
||||
RevenueByCarrier map[string]float64 `json:"revenue_by_carrier"`
|
||||
RevenueByRegion map[string]float64 `json:"revenue_by_region"`
|
||||
AverageRevenue map[string]float64 `json:"average_revenue"`
|
||||
TimelineData []TimelineDataPoint `json:"timeline_data"`
|
||||
}
|
||||
|
||||
// TimelineDataPoint represents a data point in time series
|
||||
type TimelineDataPoint struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Value float64 `json:"value"`
|
||||
Label string `json:"label,omitempty"`
|
||||
}
|
||||
Reference in New Issue
Block a user