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

227 lines
6.6 KiB
Go
Raw Normal View History

package pricing
import (
"errors"
"fmt"
"strconv"
"time"
)
2025-06-20 07:51:32 +02:00
type BillingStrategy int // BAM BAM
// should except... on
const (
BILL_ONCE BillingStrategy = iota // is a permanent buying ( predictible )
BILL_PER_WEEK
BILL_PER_MONTH
BILL_PER_YEAR
)
func (t BillingStrategy) IsBillingStrategyAllowed(bs int) (BillingStrategy, bool) {
switch t {
case BILL_ONCE:
return BILL_ONCE, bs == 0
case BILL_PER_WEEK:
case BILL_PER_MONTH:
case BILL_PER_YEAR:
return t, bs != 0
}
return t, false
}
func (t BillingStrategy) String() string {
return [...]string{"BILL_ONCE", "BILL_PER_WEEK", "BILL_PER_MONTH", "BILL_PER_YEAR"}[t]
}
func BillingStrategyList() []BillingStrategy {
return []BillingStrategy{BILL_ONCE, BILL_PER_WEEK, BILL_PER_MONTH, BILL_PER_YEAR}
}
type BuyingStrategy int
2025-06-19 08:11:11 +02:00
// should except... on
const (
2025-06-20 07:51:32 +02:00
PERMANENT BuyingStrategy = iota // is a permanent buying ( predictible )
UNDEFINED_SUBSCRIPTION // a endless subscription ( unpredictible )
SUBSCRIPTION // a defined subscription ( predictible )
// PAY_PER_USE // per request. ( unpredictible )
)
2025-01-17 10:34:44 +01:00
func (t BuyingStrategy) String() string {
2025-06-20 07:51:32 +02:00
return [...]string{"PERMANENT", "UNDEFINED_SUBSCRIPTION", "SUBSCRIPTION"}[t]
}
func (t BuyingStrategy) IsBillingStrategyAllowed(bs BillingStrategy) (BillingStrategy, bool) {
switch t {
case PERMANENT:
return BILL_ONCE, bs == BILL_ONCE
case UNDEFINED_SUBSCRIPTION:
return BILL_PER_MONTH, bs != BILL_ONCE
case SUBSCRIPTION:
/*case PAY_PER_USE:
return bs, true*/
}
return bs, false
2025-01-17 10:34:44 +01:00
}
func BuyingStrategyList() []BuyingStrategy {
2025-06-20 07:51:32 +02:00
return []BuyingStrategy{PERMANENT, UNDEFINED_SUBSCRIPTION, SUBSCRIPTION}
2025-01-17 10:34:44 +01:00
}
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
)
2025-06-19 08:11:11 +02:00
func IsTimeStrategy(i int) bool {
return len(TimePricingStrategyList()) < i
}
2025-01-17 10:34:44 +01:00
func (t TimePricingStrategy) String() string {
return [...]string{"ONCE", "PER SECOND", "PER MINUTE", "PER HOUR", "PER DAY", "PER WEEK", "PER MONTH"}[t]
}
2025-07-04 10:44:14 +02:00
func TimePricingStrategyListStr() []string {
return []string{"ONCE", "PER SECOND", "PER MINUTE", "PER HOUR", "PER DAY", "PER WEEK", "PER MONTH"}
}
2025-01-17 10:34:44 +01:00
func TimePricingStrategyList() []TimePricingStrategy {
return []TimePricingStrategy{ONCE, 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
}
2025-01-17 10:34:44 +01:00
return 0, errors.New("pricing strategy not found")
}
2025-06-19 08:11:11 +02:00
// may suppress in pricing strategy -> to set in map
type PricingStrategy[T Strategy] struct {
2025-01-14 11:28:16 +01:00
Price float64 `json:"price" bson:"price" default:"0"` // Price is the Price of the pricing
Currency string `json:"currency" bson:"currency" default:"USD"` // Currency is the currency 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
}
2026-01-13 16:04:31 +01:00
func (p PricingStrategy[T]) GetPriceHT(amountOfData float64, bookingTimeDuration float64, start time.Time, end *time.Time, variations []*PricingVariation) (float64, error) {
if p.BuyingStrategy == SUBSCRIPTION {
2026-01-13 16:04:31 +01:00
price, err := BookingEstimation(p.GetTimePricingStrategy(), p.Price*float64(amountOfData), bookingTimeDuration, start, end)
if err != nil {
return 0, err
}
if variations != nil {
for _, v := range variations {
price = v.GetPriceHT(price)
}
return price, nil
}
return p.Price, nil
2025-06-20 07:51:32 +02:00
} else if p.BuyingStrategy == PERMANENT {
2026-01-13 16:04:31 +01:00
if variations != nil {
price := p.Price
for _, v := range variations {
price = v.GetPriceHT(price)
}
return price, nil
}
return p.Price, nil
}
2026-01-13 16:04:31 +01:00
if variations != nil {
price := p.Price
for _, v := range variations {
price = v.GetPriceHT(price)
}
return 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
}
2026-01-13 16:04:31 +01:00
type PricingVariation struct {
Inflate bool `json:"inflate" bson:"price"` // Price is the Price of the pricing
Percentage float64 `json:"percent" bson:"percent"` // Currency is the currency of the pricing // Modulation is the modulation of the pricing
Priority int `json:"priority" bson:"priority"`
}
func (pv *PricingVariation) GetPriceHT(priceHT float64) float64 {
value := (priceHT * pv.Percentage) / 100
if pv.Inflate {
return priceHT + value
} else {
return priceHT - value
}
}