package discount import ( "time" "cloud.o-forge.io/core/oc-lib/models/utils" "cloud.o-forge.io/core/oc-lib/tools" ) type DiscountType int const ( PERCENTAGE DiscountType = iota // réduction en pourcentage FIXED_AMOUNT // réduction montant fixe ) func (d DiscountType) String() string { return [...]string{"percentage", "fixed_amount"}[d] } func DiscountTypeList() []DiscountType { return []DiscountType{PERCENTAGE, FIXED_AMOUNT} } type DiscountScope int const ( SCOPE_ALL DiscountScope = iota // applicable à tout SCOPE_RESOURCE_TYPE // applicable à un type de ressource SCOPE_RESOURCE // applicable à une ressource spécifique SCOPE_SUBSCRIPTION // applicable aux souscriptions ) func (d DiscountScope) String() string { return [...]string{"all", "resource_type", "resource", "subscription"}[d] } // Discount représente une réduction applicable sur les ressources ou abonnements. type Discount struct { utils.AbstractObject Code string `json:"code,omitempty" bson:"code,omitempty"` DiscountType DiscountType `json:"discount_type" bson:"discount_type"` Scope DiscountScope `json:"scope" bson:"scope"` Value float64 `json:"value" bson:"value"` // pourcentage (0-100) ou montant fixe Currency string `json:"currency,omitempty" bson:"currency,omitempty"` // pour FIXED_AMOUNT ResourceTypes []tools.DataType `json:"resource_types,omitempty" bson:"resource_types,omitempty"` // si SCOPE_RESOURCE_TYPE ResourceIDs []string `json:"resource_ids,omitempty" bson:"resource_ids,omitempty"` // si SCOPE_RESOURCE ValidFrom *time.Time `json:"valid_from,omitempty" bson:"valid_from,omitempty"` ValidUntil *time.Time `json:"valid_until,omitempty" bson:"valid_until,omitempty"` MaxUsage int `json:"max_usage,omitempty" bson:"max_usage,omitempty"` // 0 = illimité CurrentUsage int `json:"current_usage" bson:"current_usage"` MinAmount float64 `json:"min_amount,omitempty" bson:"min_amount,omitempty"` // montant minimum du bill pour appliquer Active bool `json:"active" bson:"active" default:"true"` } // IsValid vérifie si la réduction est applicable au moment présent. func (d *Discount) IsValid(billAmount float64) bool { now := time.Now().UTC() if !d.Active { return false } if d.MaxUsage > 0 && d.CurrentUsage >= d.MaxUsage { return false } if d.ValidFrom != nil && now.Before(*d.ValidFrom) { return false } if d.ValidUntil != nil && now.After(*d.ValidUntil) { return false } if d.MinAmount > 0 && billAmount < d.MinAmount { return false } return true } // Apply applique la réduction sur un prix HT et retourne le prix réduit. func (d *Discount) Apply(priceHT float64) float64 { switch d.DiscountType { case PERCENTAGE: return priceHT - (priceHT * d.Value / 100) case FIXED_AMOUNT: result := priceHT - d.Value if result < 0 { return 0 } return result } return priceHT } // DiscountAmount retourne le montant de la réduction sans l'appliquer. func (d *Discount) DiscountAmount(priceHT float64) float64 { switch d.DiscountType { case PERCENTAGE: return priceHT * d.Value / 100 case FIXED_AMOUNT: if d.Value > priceHT { return priceHT } return d.Value } return 0 } // AppliesToResource vérifie si cette réduction s'applique à une ressource donnée. func (d *Discount) AppliesToResource(resourceID string, resourceType tools.DataType) bool { switch d.Scope { case SCOPE_ALL: return true case SCOPE_RESOURCE: for _, id := range d.ResourceIDs { if id == resourceID { return true } } case SCOPE_RESOURCE_TYPE: for _, t := range d.ResourceTypes { if t == resourceType { return true } } } return false } // IncrementUsage incrémente le compteur d'utilisation. func (d *Discount) IncrementUsage() { d.CurrentUsage++ } func (d *Discount) GetAccessor(request *tools.APIRequest) utils.Accessor { return NewAccessor(request) } func (d *Discount) StoreDraftDefault() { d.IsDraft = true } func (d *Discount) CanUpdate(set utils.DBObject) (bool, utils.DBObject) { return d.IsDraft, set } func (d *Discount) CanDelete() bool { return d.IsDraft || d.CurrentUsage == 0 }