oc-lib/models/common/pricing/pricing_strategy.go

137 lines
4.2 KiB
Go

package pricing
import (
"errors"
"fmt"
"strconv"
"time"
)
type BuyingStrategy int
const (
UNLIMITED BuyingStrategy = iota
SUBSCRIPTION
PAY_PER_USE
)
type Strategy interface {
GetStrategy() string
GetStrategyValue() int
}
type TimePricingStrategy int
const (
ONCE TimePricingStrategy = iota
PER_SECOND
PER_MINUTE
PER_HOUR
PER_DAY
PER_WEEK
PER_MONTH
)
func (t TimePricingStrategy) GetStrategy() string {
return [...]string{"ONCE", "PER_SECOND", "PER_MINUTE", "PER_HOUR", "PER_DAY", "PER_WEEK", "PER_MONTH"}[t]
}
func (t TimePricingStrategy) GetStrategyValue() int {
return int(t)
}
func getAverageTimeInSecond(averageTimeInSecond float64, start time.Time, end *time.Time) float64 {
now := time.Now()
after := now.Add(time.Duration(averageTimeInSecond) * time.Second)
fromAverageDuration := after.Sub(now).Seconds()
var tEnd time.Time
if end == nil {
tEnd = start.Add(1 * time.Hour)
} else {
tEnd = *end
}
fromDateDuration := tEnd.Sub(start).Seconds()
if fromAverageDuration > fromDateDuration {
return fromAverageDuration
}
return fromDateDuration
}
func BookingEstimation(t TimePricingStrategy, price float64, locationDurationInSecond float64, start time.Time, end *time.Time) (float64, error) {
locationDurationInSecond = getAverageTimeInSecond(locationDurationInSecond, start, end)
priceStr := fmt.Sprintf("%v", price)
p, err := strconv.ParseFloat(priceStr, 64)
if err != nil {
return 0, err
}
switch t {
case ONCE:
return p, nil
case PER_HOUR:
return p * float64(locationDurationInSecond/3600), nil
case PER_MINUTE:
return p * float64(locationDurationInSecond/60), nil
case PER_SECOND:
return p * locationDurationInSecond, nil
case PER_DAY:
return p * float64(locationDurationInSecond/86400), nil
case PER_WEEK:
return p * float64(locationDurationInSecond/604800), nil
case PER_MONTH:
return p * float64(locationDurationInSecond/2592000), nil
}
return 0, errors.New("Pricing strategy not found")
}
// hmmmm
type PricingStrategy[T Strategy] struct {
Price float64 `json:"Price" bson:"Price" default:"0"` // Price is the Price of the pricing
BuyingStrategy BuyingStrategy `json:"buying_strategy" bson:"buying_strategy" default:"0"` // BuyingStrategy is the buying strategy of the pricing
TimePricingStrategy TimePricingStrategy `json:"time_pricing_strategy" bson:"time_pricing_strategy" default:"0"` // TimePricingStrategy is the time pricing strategy of the pricing
OverrideStrategy T `json:"override_strategy" bson:"override_strategy" default:"-1"` // Modulation is the modulation of the pricing
}
func (p PricingStrategy[T]) SetStrategy(Price float64, BuyingStrategy BuyingStrategy, TimePricingStrategy TimePricingStrategy) error {
if TimePricingStrategy == ONCE && (BuyingStrategy != UNLIMITED || BuyingStrategy != PAY_PER_USE) {
return errors.New("time pricing strategy can only be set to ONCE if buying strategy is UNLIMITED or PAY_PER_USE")
} else if BuyingStrategy == SUBSCRIPTION && (TimePricingStrategy == ONCE) {
return errors.New("subscription duration in second must be set if buying strategy is SUBSCRIPTION")
}
p.Price = Price
p.BuyingStrategy = BuyingStrategy
p.TimePricingStrategy = TimePricingStrategy
return nil
}
func (p PricingStrategy[T]) SetSpecificPerUseStrategy(strategy T) error {
if p.BuyingStrategy == UNLIMITED {
return errors.New("UNLIMITED buying strategy can't have a specific strategy, Price is set on buying")
}
p.OverrideStrategy = strategy
return nil
}
// QUANTITY can be how many of gb core per example
func (p PricingStrategy[T]) GetPrice(amountOfData float64, bookingTimeDuration float64, start time.Time, end *time.Time) (float64, error) {
if p.BuyingStrategy == SUBSCRIPTION {
return BookingEstimation(p.GetTimePricingStrategy(), p.Price*float64(amountOfData), bookingTimeDuration, start, end)
} else if p.BuyingStrategy == UNLIMITED {
return p.Price, nil
}
return p.Price * float64(amountOfData), nil
}
func (p PricingStrategy[T]) GetBuyingStrategy() BuyingStrategy {
return p.BuyingStrategy
}
func (p PricingStrategy[T]) GetTimePricingStrategy() TimePricingStrategy {
return p.TimePricingStrategy
}
func (p PricingStrategy[T]) GetOverrideStrategy() T {
return p.OverrideStrategy
}