Skip to content

Commit 2a5a014

Browse files
authored
Epsilon: Currency conversion (prebid#3199)
1 parent 6dcde09 commit 2a5a014

File tree

6 files changed

+82
-12
lines changed

6 files changed

+82
-12
lines changed

src/main/java/org/prebid/server/bidder/epsilon/EpsilonBidder.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.prebid.server.bidder.model.BidderError;
1919
import org.prebid.server.bidder.model.HttpRequest;
2020
import org.prebid.server.bidder.model.Result;
21+
import org.prebid.server.currency.CurrencyConversionService;
2122
import org.prebid.server.exception.PreBidException;
2223
import org.prebid.server.json.DecodeException;
2324
import org.prebid.server.json.JacksonMapper;
@@ -39,6 +40,10 @@
3940

4041
public class EpsilonBidder implements Bidder<BidRequest> {
4142

43+
private static final String BIDDER_CURRENCY = "USD";
44+
45+
private final CurrencyConversionService currencyConversionService;
46+
4247
private static final TypeReference<ExtPrebid<?, ExtImpEpsilon>> EPSILON_EXT_TYPE_REFERENCE =
4348
new TypeReference<>() {
4449
};
@@ -59,10 +64,14 @@ public class EpsilonBidder implements Bidder<BidRequest> {
5964
private final boolean generateBidId;
6065
private final JacksonMapper mapper;
6166

62-
public EpsilonBidder(String endpointUrl, boolean generateBidId, JacksonMapper mapper) {
67+
public EpsilonBidder(String endpointUrl,
68+
boolean generateBidId,
69+
JacksonMapper mapper,
70+
CurrencyConversionService currencyConversionService) {
6371
this.endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpointUrl));
6472
this.generateBidId = generateBidId;
6573
this.mapper = Objects.requireNonNull(mapper);
74+
this.currencyConversionService = Objects.requireNonNull(currencyConversionService);
6675
}
6776

6877
@Override
@@ -84,22 +93,35 @@ private BidRequest createOutgoingRequest(BidRequest bidRequest) {
8493
for (int i = 0; i < requestImps.size(); i++) {
8594
final Imp imp = requestImps.get(i);
8695
final ExtImpEpsilon impExt = parseImpExt(imp, i);
87-
modifiedImps.add(modifyImp(imp, impExt));
96+
final BigDecimal bidFloor = resolveBidFloor(bidRequest,
97+
imp.getBidfloorcur(),
98+
getBidFloor(imp.getBidfloor(), impExt.getBidfloor()));
99+
modifiedImps.add(modifyImp(imp, impExt, bidFloor));
88100
}
89101

90102
final Imp firstImp = requestImps.getFirst();
91103
final ExtImpEpsilon extImp = parseImpExt(firstImp, 0);
92104
final String siteId = extImp.getSiteId();
93105
final Site requestSite = bidRequest.getSite();
94106
final App requestApp = bidRequest.getApp();
95-
107+
final List<String> cur = bidRequest.getCur();
96108
return bidRequest.toBuilder()
97109
.site(updateSite(requestSite, siteId))
98110
.app(requestSite == null ? updateApp(requestApp, siteId) : requestApp)
99111
.imp(modifiedImps)
112+
.cur(Collections.singletonList(BIDDER_CURRENCY))
100113
.build();
101114
}
102115

116+
private BigDecimal resolveBidFloor(BidRequest bidRequest, String bidfloorcur, BigDecimal bidfloor) {
117+
if (BidderUtil.isValidPrice(bidfloor)
118+
&& !StringUtils.equalsIgnoreCase(bidfloorcur, BIDDER_CURRENCY)
119+
&& StringUtils.isNotBlank(bidfloorcur)) {
120+
return currencyConversionService.convertCurrency(bidfloor, bidRequest, bidfloorcur, BIDDER_CURRENCY);
121+
}
122+
return bidfloor;
123+
}
124+
103125
private ExtImpEpsilon parseImpExt(Imp imp, int impIndex) {
104126
final ExtImpEpsilon extImp;
105127
try {
@@ -122,14 +144,15 @@ private static App updateApp(App app, String siteId) {
122144
return app == null ? null : app.toBuilder().id(siteId).build();
123145
}
124146

125-
private static Imp modifyImp(Imp imp, ExtImpEpsilon impExt) {
147+
private static Imp modifyImp(Imp imp, ExtImpEpsilon impExt, BigDecimal bidfloor) {
126148
final Banner banner = imp.getBanner();
127149
final Video video = imp.getVideo();
128150

129151
return imp.toBuilder()
130152
.displaymanager(DISPLAY_MANAGER)
131153
.displaymanagerver(DISPLAY_MANAGER_VER)
132-
.bidfloor(getBidFloor(imp.getBidfloor(), impExt.getBidfloor()))
154+
.bidfloor(bidfloor)
155+
.bidfloorcur(BIDDER_CURRENCY)
133156
.tagid(getTagId(imp.getTagid(), impExt.getTagId()))
134157
.secure(getSecure(imp, impExt))
135158
.banner(modifyBanner(banner, impExt.getPosition()))

src/main/java/org/prebid/server/spring/config/bidder/EpsilonConfiguration.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import lombok.NoArgsConstructor;
66
import org.prebid.server.bidder.BidderDeps;
77
import org.prebid.server.bidder.epsilon.EpsilonBidder;
8+
import org.prebid.server.currency.CurrencyConversionService;
89
import org.prebid.server.json.JacksonMapper;
910
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties;
1011
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler;
@@ -34,8 +35,9 @@ EpsilonConfigurationProperties configurationProperties() {
3435

3536
@Bean
3637
BidderDeps epsilonBidderDeps(EpsilonConfigurationProperties epsilonConfigurationProperties,
37-
@NotBlank @Value("${external-url}") String externalUrl,
38-
JacksonMapper mapper) {
38+
@NotBlank @Value("${external-url}") String externalUrl,
39+
JacksonMapper mapper,
40+
CurrencyConversionService currencyConversionService) {
3941

4042
return BidderDepsAssembler.forBidder(BIDDER_NAME)
4143
.withConfig(epsilonConfigurationProperties)
@@ -44,7 +46,8 @@ BidderDeps epsilonBidderDeps(EpsilonConfigurationProperties epsilonConfiguration
4446
new EpsilonBidder(
4547
config.getEndpoint(),
4648
epsilonConfigurationProperties.getGenerateBidId(),
47-
mapper))
49+
mapper,
50+
currencyConversionService))
4851
.assemble();
4952
}
5053

src/main/resources/bidder-config/epsilon.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
adapters:
22
epsilon:
3-
endpoint: http://api.hb.ad.cpe.dotomi.com/s2s/header/24
3+
endpoint: http://api.hb.ad.cpe.dotomi.com/cvx/server/hb/ortb/25
44
aliases:
55
conversant:
66
usersync:

src/test/java/org/prebid/server/bidder/epsilon/EpsilonBidderTest.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,21 @@
1010
import com.iab.openrtb.response.Bid;
1111
import com.iab.openrtb.response.BidResponse;
1212
import com.iab.openrtb.response.SeatBid;
13+
import org.assertj.core.api.AssertionsForClassTypes;
14+
import org.junit.Before;
15+
import org.junit.Rule;
1316
import org.junit.Test;
17+
import org.mockito.Mock;
18+
import org.mockito.junit.MockitoJUnit;
19+
import org.mockito.junit.MockitoRule;
1420
import org.prebid.server.VertxTest;
1521
import org.prebid.server.bidder.model.BidderBid;
1622
import org.prebid.server.bidder.model.BidderCall;
1723
import org.prebid.server.bidder.model.BidderError;
1824
import org.prebid.server.bidder.model.HttpRequest;
1925
import org.prebid.server.bidder.model.HttpResponse;
2026
import org.prebid.server.bidder.model.Result;
27+
import org.prebid.server.currency.CurrencyConversionService;
2128
import org.prebid.server.proto.openrtb.ext.ExtPrebid;
2229
import org.prebid.server.proto.openrtb.ext.request.epsilon.ExtImpEpsilon;
2330

@@ -32,6 +39,9 @@
3239
import static org.assertj.core.api.Assertions.assertThat;
3340
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
3441
import static org.assertj.core.api.Assertions.tuple;
42+
import static org.mockito.ArgumentMatchers.any;
43+
import static org.mockito.ArgumentMatchers.anyString;
44+
import static org.mockito.BDDMockito.given;
3545
import static org.prebid.server.proto.openrtb.ext.response.BidType.banner;
3646
import static org.prebid.server.proto.openrtb.ext.response.BidType.video;
3747

@@ -41,12 +51,23 @@ public class EpsilonBidderTest extends VertxTest {
4151
private static final String UUID_REGEX = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}"
4252
+ "-[0-9a-fA-F]{12}";
4353

44-
private EpsilonBidder target = new EpsilonBidder(ENDPOINT_URL, false, jacksonMapper);
54+
@Rule
55+
public final MockitoRule mockitoRule = MockitoJUnit.rule();
56+
57+
@Mock
58+
private CurrencyConversionService currencyConversionService;
59+
60+
private EpsilonBidder target;
61+
62+
@Before
63+
public void setUp() {
64+
target = new EpsilonBidder(ENDPOINT_URL, false, jacksonMapper, currencyConversionService);
65+
}
4566

4667
@Test
4768
public void creationShouldFailOnInvalidEndpointUrl() {
4869
assertThatIllegalArgumentException()
49-
.isThrownBy(() -> new EpsilonBidder("invalid_url", false, jacksonMapper));
70+
.isThrownBy(() -> new EpsilonBidder("invalid_url", false, jacksonMapper, currencyConversionService));
5071
}
5172

5273
@Test
@@ -595,7 +616,7 @@ public void makeBidsShouldReturnVideoBidIfRequestImpHasVideo() throws JsonProces
595616
@Test
596617
public void makeBidsShouldUpdateBidWithUUIDIfGenerateBidIdIsTrue() throws JsonProcessingException {
597618
// given
598-
target = new EpsilonBidder(ENDPOINT_URL, true, jacksonMapper);
619+
target = new EpsilonBidder(ENDPOINT_URL, true, jacksonMapper, currencyConversionService);
599620
final BidderCall<BidRequest> httpCall = givenHttpCall(
600621
givenBidRequest(builder -> builder.id("123")
601622
.banner(Banner.builder().build())),
@@ -652,6 +673,27 @@ public void makeHttpRequestsShouldNotSetImpBidFloorFromImpExt() {
652673
.containsExactly(BigDecimal.valueOf(-1.00));
653674
}
654675

676+
@Test
677+
public void makeHttpRequestsShouldReturnConvertedBidFloorCurrency() {
678+
// given
679+
given(currencyConversionService.convertCurrency(any(), any(), anyString(), anyString()))
680+
.willReturn(BigDecimal.ONE);
681+
682+
final BidRequest bidRequest = givenBidRequest(
683+
impBuilder -> impBuilder.bidfloor(BigDecimal.TEN).bidfloorcur("EUR"));
684+
685+
// when
686+
final Result<List<HttpRequest<BidRequest>>> result = target.makeHttpRequests(bidRequest);
687+
688+
// then
689+
assertThat(result.getErrors()).isEmpty();
690+
assertThat(result.getValue())
691+
.extracting(HttpRequest::getPayload)
692+
.flatExtracting(BidRequest::getImp)
693+
.extracting(Imp::getBidfloor, Imp::getBidfloorcur)
694+
.containsOnly(AssertionsForClassTypes.tuple(BigDecimal.ONE, "USD"));
695+
}
696+
655697
private static BidRequest givenBidRequest(
656698
Function<BidRequest.BidRequestBuilder, BidRequest.BidRequestBuilder> bidRequestCustomizer,
657699
Function<Imp.ImpBuilder, Imp.ImpBuilder> impCustomizer,

src/test/resources/org/prebid/server/it/openrtb2/epsilon/alias/test-epsilon-bid-request.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"w": 300,
99
"h": 600
1010
},
11+
"bidfloorcur": "USD",
1112
"displaymanager": "prebid-s2s",
1213
"displaymanagerver": "2.0.0",
1314
"ext": {

src/test/resources/org/prebid/server/it/openrtb2/epsilon/test-epsilon-bid-request.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"w": 300,
99
"h": 600
1010
},
11+
"bidfloorcur": "USD",
1112
"displaymanager": "prebid-s2s",
1213
"displaymanagerver": "2.0.0",
1314
"ext": {

0 commit comments

Comments
 (0)