satellite/payments/stripe: apply egress discount to project charges

The project charge information used by the satellite frontend to
compute project cost estimates has been updated to account for
configured egress discounts.

Resolves storj/storj-private#215

Change-Id: Ic90b015d65f5bea104ac96fb0cea545b3f9f1f8f
This commit is contained in:
Jeremy Wharton 2023-04-04 04:10:25 -05:00 committed by Storj Robot
parent 16ccffb6f7
commit 34b2a369f7
3 changed files with 26 additions and 18 deletions

View File

@ -14,12 +14,12 @@ import (
type ProjectCharge struct {
accounting.ProjectUsage
// StorageGbHrs shows how much cents we should pay for storing GB*Hrs.
StorageGbHrs int64 `json:"storagePrice"`
// Egress shows how many cents we should pay for Egress.
Egress int64 `json:"egressPrice"`
// SegmentCount shows how many cents we should pay for objects count.
SegmentCount int64 `json:"segmentPrice"`
// StorageMBMonthCents is how many cents we should pay for storing MB*months.
StorageMBMonthCents int64 `json:"storagePrice"`
// EgressMBCents is how many cents we should pay for megabytes of egress.
EgressMBCents int64 `json:"egressPrice"`
// SegmentMonthCents is how many cents we should pay for objects count.
SegmentMonthCents int64 `json:"segmentPrice"`
}
// ProjectChargesResponse represents a collection of project usage charges grouped by project ID and partner name.

View File

@ -146,14 +146,15 @@ func (accounts *accounts) ProjectCharges(ctx context.Context, userID uuid.UUID,
for partner, usage := range usages {
priceModel := accounts.GetProjectUsagePriceModel(partner)
price := accounts.service.calculateProjectUsagePrice(usage.Egress, usage.Storage, usage.SegmentCount, priceModel)
usage.Egress = applyEgressDiscount(usage, priceModel)
price := accounts.service.calculateProjectUsagePrice(usage, priceModel)
partnerCharges[partner] = payments.ProjectCharge{
ProjectUsage: usage,
Egress: price.Egress.IntPart(),
SegmentCount: price.Segments.IntPart(),
StorageGbHrs: price.Storage.IntPart(),
EgressMBCents: price.Egress.IntPart(),
SegmentMonthCents: price.Segments.IntPart(),
StorageMBMonthCents: price.Storage.IntPart(),
}
}

View File

@ -539,10 +539,7 @@ func (service *Service) InvoiceItemsFromProjectUsage(projName string, partnerUsa
priceModel := service.Accounts().GetProjectUsagePriceModel(partner)
usage := partnerUsages[partner]
usage.Egress -= int64(math.Round(usage.Storage / hoursPerMonth * priceModel.EgressDiscountRatio))
if usage.Egress < 0 {
usage.Egress = 0
}
usage.Egress = applyEgressDiscount(usage, priceModel)
prefix := "Project " + projName
if partner != "" {
@ -891,11 +888,11 @@ func (price projectUsagePrice) TotalInt64() int64 {
}
// calculateProjectUsagePrice calculate project usage price.
func (service *Service) calculateProjectUsagePrice(egress int64, storage, segments float64, pricing payments.ProjectUsagePriceModel) projectUsagePrice {
func (service *Service) calculateProjectUsagePrice(usage accounting.ProjectUsage, pricing payments.ProjectUsagePriceModel) projectUsagePrice {
return projectUsagePrice{
Storage: pricing.StorageMBMonthCents.Mul(storageMBMonthDecimal(storage)).Round(0),
Egress: pricing.EgressMBCents.Mul(egressMBDecimal(egress)).Round(0),
Segments: pricing.SegmentMonthCents.Mul(segmentMonthDecimal(segments)).Round(0),
Storage: pricing.StorageMBMonthCents.Mul(storageMBMonthDecimal(usage.Storage)).Round(0),
Egress: pricing.EgressMBCents.Mul(egressMBDecimal(usage.Egress)).Round(0),
Segments: pricing.SegmentMonthCents.Mul(segmentMonthDecimal(usage.SegmentCount)).Round(0),
}
}
@ -928,3 +925,13 @@ func segmentMonthDecimal(segments float64) decimal.Decimal {
func doesProjectRecordHaveNoUsage(record ProjectRecord) bool {
return record.Storage == 0 && record.Egress == 0 && record.Segments == 0
}
// applyEgressDiscount returns the amount of egress that we should charge for by subtracting
// the discounted amount.
func applyEgressDiscount(usage accounting.ProjectUsage, model payments.ProjectUsagePriceModel) int64 {
egress := usage.Egress - int64(math.Round(usage.Storage/hoursPerMonth*model.EgressDiscountRatio))
if egress < 0 {
egress = 0
}
return egress
}