diff --git a/internal/server/api.go b/internal/server/api.go index 92ccab8..f18055b 100644 --- a/internal/server/api.go +++ b/internal/server/api.go @@ -28,43 +28,11 @@ func (s *Server) newPricingHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { items := s.PriceCache.GetPrices() - // Pick the first yearly and monthly price that we find in the cache - // based on no particular order (since we expect to only have one of each) - var yearly, monthly *payment.Price - for _, price := range items { - price := price // GO WHY ARE YOU THIS WAY - - if price.Annual && yearly == nil { - yearly = price - } - if !price.Annual && monthly == nil { - monthly = price - } - if monthly != nil && yearly != nil { - break - } - } - - prices := &prices{} - if yearly != nil { - prices.Yearly.Price = yearly.Price - for _, discount := range yearly.CouponAmountsOff { - prices.Yearly.Discount = discount - } - } - - if monthly != nil { - prices.Monthly.Price = monthly.Price - for _, discount := range monthly.CouponAmountsOff { - prices.Monthly.Discount = discount - } - } - w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "*") w.Header().Set("Access-Control-Allow-Methods", "GET") - json.NewEncoder(w).Encode(prices) + json.NewEncoder(w).Encode(newPrices(items)) } } @@ -73,7 +41,57 @@ type prices struct { Monthly price `json:"monthly"` } +func newPrices(items []*payment.Price) *prices { + // Pick the first yearly and monthly price that we find in the cache + // based on no particular order (since we expect to only have one of each) + var yearly, monthly *payment.Price + for _, price := range items { + price := price // GO WHY ARE YOU THIS WAY + + if price.Annual && yearly == nil { + yearly = price + } + if !price.Annual && monthly == nil { + monthly = price + } + if monthly != nil && yearly != nil { + break + } + } + + // Convert to our API response types + // When selecting discounts, pick the smallest i.e. most expensive. + prices := &prices{} + if yearly != nil { + prices.Yearly.Price = yearly.Price + + var discount float64 + for _, c := range yearly.CouponAmountsOff { + fd := float64(c) / 100 + if fd < discount || discount == 0 { + discount = float64(c) / 100 + } + } + prices.Yearly.Discounted = prices.Yearly.Price - discount + } + + if monthly != nil { + prices.Monthly.Price = monthly.Price + + var discount float64 + for _, c := range monthly.CouponAmountsOff { + fd := float64(c) / 100 + if fd < discount || discount == 0 { + discount = float64(c) / 100 + } + } + prices.Monthly.Discounted = prices.Monthly.Price - discount + } + + return prices +} + type price struct { - Price float64 `json:"price"` - Discount int64 `json:"discount"` + Price float64 `json:"price"` + Discounted float64 `json:"discount"` } diff --git a/internal/server/api_test.go b/internal/server/api_test.go new file mode 100644 index 0000000..3296d69 --- /dev/null +++ b/internal/server/api_test.go @@ -0,0 +1,45 @@ +package server + +import ( + "testing" + + "github.com/TheLab-ms/profile/internal/payment" + "github.com/stretchr/testify/assert" +) + +func TestNewPrices(t *testing.T) { + items := []*payment.Price{ + { + Price: 123, + CouponAmountsOff: map[string]int64{"foo": 1000, "bar": 300}, + }, + { + Annual: true, + Price: 234, + CouponAmountsOff: map[string]int64{"foo": 1100, "bar": 350}, + }, + { + Annual: true, + Price: 1230, // this won't be picked because it isn't first + }, + { + Price: 2340, // this won't be picked because it isn't first + }, + } + + actual := newPrices(items) + exp := &prices{ + Yearly: price{ + Price: 234, + Discounted: 230.5, + }, + Monthly: price{ + Price: 123, + Discounted: 120, + }, + } + assert.Equal(t, exp, actual) + + // also doesn't panic when empty + newPrices(nil) +}