diff --git a/floors/enforce.go b/floors/enforce.go index 1f50dd2b1d9..9318c9d278e 100644 --- a/floors/enforce.go +++ b/floors/enforce.go @@ -137,7 +137,7 @@ func enforceFloorToBids(bidRequestWrapper *openrtb_ext.RequestWrapper, seatBids } bidPrice := rate * bid.Bid.Price - if reqImp.BidFloor > bidPrice { + if (bidPrice + floorPrecision) < reqImp.BidFloor { rejectedBid := &entities.PbsOrtbSeatBid{ Currency: seatBid.Currency, Seat: seatBid.Seat, diff --git a/floors/enforce_test.go b/floors/enforce_test.go index bb5d44341ef..725ac22b193 100644 --- a/floors/enforce_test.go +++ b/floors/enforce_test.go @@ -196,6 +196,71 @@ func TestEnforceFloorToBids(t *testing.T) { }, expErrs: []error{}, }, + { + name: "Bids with price less than bidfloor with floorsPrecision", + args: args{ + bidRequestWrapper: func() *openrtb_ext.RequestWrapper { + bw := openrtb_ext.RequestWrapper{ + BidRequest: &openrtb2.BidRequest{ + ID: "some-request-id", + Imp: []openrtb2.Imp{ + {ID: "some-impression-id-1", BidFloor: 1, BidFloorCur: "USD"}, + {ID: "some-impression-id-2", BidFloor: 2, BidFloorCur: "USD"}, + }, + }, + } + bw.RebuildRequest() + return &bw + }(), + seatBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ + "pubmatic": { + Bids: []*entities.PbsOrtbBid{ + {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 0.998, ImpID: "some-impression-id-1"}}, + {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, + }, + Seat: "pubmatic", + Currency: "USD", + }, + "appnexus": { + Bids: []*entities.PbsOrtbBid{ + {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.8, ImpID: "some-impression-id-1"}}, + {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, + }, + Seat: "appnexus", + Currency: "USD", + }, + }, + conversions: currency.Conversions(convert{}), + enforceDealFloors: false, + }, + expEligibleBids: map[openrtb_ext.BidderName]*entities.PbsOrtbSeatBid{ + "pubmatic": { + Bids: []*entities.PbsOrtbBid{ + {Bid: &openrtb2.Bid{ID: "some-bid-1", Price: 0.998, ImpID: "some-impression-id-1"}}, + {Bid: &openrtb2.Bid{ID: "some-bid-2", Price: 1.5, DealID: "deal_Id", ImpID: "some-impression-id-2"}}, + }, + Seat: "pubmatic", + Currency: "USD", + }, + "appnexus": { + Bids: []*entities.PbsOrtbBid{ + {Bid: &openrtb2.Bid{ID: "some-bid-12", Price: 2.2, ImpID: "some-impression-id-2"}}, + }, + Seat: "appnexus", + Currency: "USD", + }, + }, + expRejectedBids: []*entities.PbsOrtbSeatBid{ + { + Seat: "appnexus", + Currency: "USD", + Bids: []*entities.PbsOrtbBid{ + {Bid: &openrtb2.Bid{ID: "some-bid-11", Price: 0.8, ImpID: "some-impression-id-1"}}, + }, + }, + }, + expErrs: []error{}, + }, { name: "Bids with different currency with enforceDealFloor true", args: args{ @@ -1154,7 +1219,6 @@ func TestUpdateEnforcePBS(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got := updateEnforcePBS(tt.args.enforceFloors, tt.args.reqExt) assert.Equal(t, tt.want, got, tt.name) - }) } } diff --git a/floors/floors.go b/floors/floors.go index f9e13ec05fd..52591915058 100644 --- a/floors/floors.go +++ b/floors/floors.go @@ -16,15 +16,16 @@ type Price struct { } const ( - defaultCurrency string = "USD" - defaultDelimiter string = "|" - catchAll string = "*" - skipRateMin int = 0 - skipRateMax int = 100 - modelWeightMax int = 100 - modelWeightMin int = 1 - enforceRateMin int = 0 - enforceRateMax int = 100 + defaultCurrency string = "USD" + defaultDelimiter string = "|" + catchAll string = "*" + skipRateMin int = 0 + skipRateMax int = 100 + modelWeightMax int = 100 + modelWeightMin int = 1 + enforceRateMin int = 0 + enforceRateMax int = 100 + floorPrecision float64 = 0.01 ) // EnrichWithPriceFloors checks for floors enabled in account and request and selects floors data from dynamic fetched if present