2024-12-12 16:25:47 +01:00
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 }
}
2024-12-12 16:25:47 +01:00
type BuyingStrategy int
2025-06-19 08:11:11 +02:00
// should except... on
2024-12-12 16:25:47 +01:00
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 )
2024-12-12 16:25:47 +01:00
)
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
}
2024-12-12 16:25:47 +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 ]
}
func TimePricingStrategyList ( ) [ ] TimePricingStrategy {
return [ ] TimePricingStrategy { ONCE , PER_SECOND , PER_MINUTE , PER_HOUR , PER_DAY , PER_WEEK , PER_MONTH }
}
2024-12-12 16:25:47 +01:00
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" )
2024-12-12 16:25:47 +01:00
}
2025-06-19 08:11:11 +02:00
// may suppress in pricing strategy -> to set in map
2024-12-12 16:25:47 +01:00
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
2024-12-12 16:25:47 +01:00
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 ] ) 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 )
2025-06-20 07:51:32 +02:00
} else if p . BuyingStrategy == PERMANENT {
2024-12-12 16:25:47 +01:00
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
}