137 lines
4.2 KiB
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
|
|
}
|