Skip to content
This repository was archived by the owner on Jan 26, 2023. It is now read-only.

Commit aa2512c

Browse files
bean/gh-365_serve_ads_from_tags (#373)
1 parent 7d97b9c commit aa2512c

File tree

11 files changed

+207
-94
lines changed

11 files changed

+207
-94
lines changed

lib/ad_service/query/for_display.ex

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule AdService.Query.ForDisplay do
22
import Ecto.Query
33
alias AdService.UnrenderedAdvertisement
44
alias CodeFund.Campaigns
5-
alias CodeFund.Schema.{Audience, Campaign, Creative, Impression, Property}
5+
alias CodeFund.Schema.{Campaign, Creative, Impression, Property}
66

77
def fallback_ad_by_property_id(property_id) do
88
from(property in Property,
@@ -30,22 +30,52 @@ defmodule AdService.Query.ForDisplay do
3030
|> UnrenderedAdvertisement.one()
3131
end
3232

33-
def build(%Audience{} = audience, client_country, ip_address, excluded_advertisers \\ []) do
33+
def build(%Property{} = property, client_country, ip_address, excluded_advertisers \\ []) do
3434
from(
3535
creative in Creative,
3636
join: campaign in Campaign,
3737
on: campaign.creative_id == creative.id,
3838
join: large_image_asset in assoc(creative, :large_image_asset),
3939
left_join: small_image_asset in assoc(creative, :small_image_asset),
4040
left_join: wide_image_asset in assoc(creative, :wide_image_asset),
41-
join: audience in assoc(campaign, :audience),
4241
distinct: campaign.id
4342
)
4443
|> where_country_in(client_country)
4544
|> AdService.Query.TimeManagement.where_accepted_hours_for_ip_address(ip_address)
4645
|> AdService.Query.TimeManagement.where_not_allowed_on_weekends(ip_address)
4746
|> with_daily_budget()
48-
|> where([_creative, campaign, ...], campaign.audience_id == ^audience.id)
47+
|> where(
48+
[_creative, campaign, ...],
49+
fragment(
50+
"? && ?::varchar[]",
51+
campaign.included_programming_languages,
52+
^property.programming_languages
53+
)
54+
)
55+
|> where(
56+
[_creative, campaign, ...],
57+
fragment(
58+
"? && ?::varchar[]",
59+
campaign.included_topic_categories,
60+
^property.topic_categories
61+
)
62+
)
63+
|> where(
64+
[_creative, campaign, ...],
65+
fragment(
66+
"not ? && ?::varchar[]",
67+
campaign.excluded_programming_languages,
68+
^property.programming_languages
69+
)
70+
)
71+
|> where(
72+
[_creative, campaign, ...],
73+
fragment(
74+
"not ? && ?::varchar[]",
75+
campaign.excluded_topic_categories,
76+
^property.topic_categories
77+
)
78+
)
4979
|> where(
5080
[_creative, campaign, ...],
5181
campaign.id not in ^Campaigns.list_of_ids_for_companies(excluded_advertisers)

lib/ad_service/server.ex

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ defmodule AdService.Server do
1313
with {:ok, :no_cache_found} <- AdService.Impression.Cache.lookup(conn.remote_ip, property_id),
1414
{:ok, %{country: client_country}} <-
1515
Framework.Geolocation.find_by_ip(conn.remote_ip, :city),
16-
%Property{status: 1, audience: audience} = property
17-
when not is_nil(audience) <-
18-
Properties.get_property!(property_id) |> CodeFund.Repo.preload([:user, :audience]),
16+
%Property{status: 1} = property <-
17+
Properties.get_property!(property_id) |> CodeFund.Repo.preload([:user]),
1918
:ok <- Framework.Browser.certify_human(conn),
2019
{:ok, ad_tuple} <-
2120
AdService.Query.ForDisplay.build(
22-
audience,
21+
property,
2322
client_country,
2423
conn.remote_ip,
2524
property.excluded_advertisers

lib/code_fund/audiences/audiences.ex

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,6 @@ defmodule CodeFund.Audiences do
133133
Audience.changeset(audience, %{})
134134
end
135135

136-
def get_all_display_rates(%Audience{} = audience) do
137-
AdService.Query.ForDisplay.build(audience, nil, nil)
138-
|> CodeFund.Repo.all()
139-
|> AdService.Math.Basic.get_all_display_rates()
140-
end
141-
142136
defp filter_config(:audiences) do
143137
defconfig do
144138
text(:name)

lib/code_fund/properties/properties.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ defmodule CodeFund.Properties do
139139
def get_property_by_name!(name),
140140
do: Repo.get_by!(Property, name: name) |> Repo.preload([:user, :audience, :template])
141141

142-
def get_all_display_rates(%Property{audience: audience}) when not is_nil(audience) do
143-
AdService.Query.ForDisplay.build(audience, nil, nil)
142+
def get_all_display_rates(%Property{} = property) do
143+
AdService.Query.ForDisplay.build(property, nil, nil)
144144
|> CodeFund.Repo.all()
145145
|> AdService.Math.Basic.get_all_display_rates()
146146
end

lib/code_fund_web/templates/audience/index.html.eex

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
<th>Fallback Campaign</th>
2525
<th><%= table_link(@conn, "Programming Languages", :programming_languages) %></th>
2626
<th><%= table_link(@conn, "Topic Categories", :topic_categories) %></th>
27-
<th>Advertisers</th>
2827
<th></th>
2928
</tr>
3029
</thead>
@@ -35,13 +34,6 @@
3534
<td><%= if audience.campaigns, do: audience.campaigns.name, else: "None" %></td>
3635
<td><%= truncate(audience.programming_languages |> Enum.join(", ")) %></td>
3736
<td><%= truncate(audience.topic_categories |> Enum.join(", ")) %></td>
38-
<td>
39-
<ul class="list-unstyled">
40-
<%= for advertiser <- CodeFund.Audiences.get_all_display_rates(audience) do %>
41-
<li><strong><%= Number.Percentage.number_to_percentage(advertiser.display_rate, precision: 1) %></strong> <%= advertiser.campaign_name %></li>
42-
<% end %>
43-
</ul>
44-
</td>
4537
<td class="text-right p-2">
4638
<%= link 'Show', to: audience_path(@conn, :show, audience), class: "btn btn-outline-info btn-sm" %>
4739
<%= link 'Edit', to: audience_path(@conn, :edit, audience), class: "btn btn-outline-primary btn-sm" %>

lib/code_fund_web/templates/property/index.html.eex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
<%= if has_any_role? @conn, ["admin", "developer"] do %>
5555
<th>Excluded Advertisers</th>
5656
<% end %>
57+
<%= if has_any_role? @conn, ["admin"] do %>
58+
<th>Advertisers</th>
59+
<% end %>
5760
<th></th>
5861
</tr>
5962
</thead>
@@ -73,6 +76,15 @@
7376
<%= if has_any_role? @conn, ["admin", "developer"] do %>
7477
<td><%= property.excluded_advertisers |> Enum.join(", ") %></td>
7578
<% end %>
79+
<%= if has_any_role? @conn, ["admin"] do %>
80+
<td>
81+
<ul class="list-unstyled">
82+
<%= for advertiser <- CodeFund.Properties.get_all_display_rates(property) do %>
83+
<li><strong><%= Number.Percentage.number_to_percentage(advertiser.display_rate, precision: 1) %></strong> <%= advertiser.campaign_name %></li>
84+
<% end %>
85+
</ul>
86+
</td>
87+
<% end %>
7688
<td class="text-right p-2">
7789
<%= link 'Show', to: property_path(@conn, :show, property), class: "btn btn-outline-info btn-sm" %>
7890
<%= link 'Edit', to: property_path(@conn, :edit, property), class: "btn btn-outline-primary btn-sm" %>

test/ad_service/query/for_display_test.exs

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,22 @@ defmodule AdService.Query.ForDisplayTest do
2929
topic_categories: ["Development"]
3030
})
3131

32+
property =
33+
insert(:property, %{
34+
programming_languages: ["Ruby", "C"],
35+
topic_categories: ["Programming"]
36+
})
37+
38+
insert(:property, %{
39+
programming_languages: ["Ruby", "C"],
40+
topic_categories: ["Development"]
41+
})
42+
43+
insert(:property, %{
44+
programming_languages: ["Ruby", "Rust"],
45+
topic_categories: ["Programming"]
46+
})
47+
3248
campaign =
3349
insert(
3450
:campaign,
@@ -40,6 +56,10 @@ defmodule AdService.Query.ForDisplayTest do
4056
end_date: Timex.now() |> Timex.shift(days: 1) |> DateTime.to_naive(),
4157
creative: creative,
4258
audience: audience,
59+
included_programming_languages: ["Ruby"],
60+
included_topic_categories: ["Programming"],
61+
excluded_programming_languages: ["Rust"],
62+
excluded_topic_categories: ["Development"],
4363
included_countries: ["US"],
4464
user: insert(:user, company: "Acme")
4565
)
@@ -54,6 +74,10 @@ defmodule AdService.Query.ForDisplayTest do
5474
end_date: Timex.now() |> Timex.shift(days: -1) |> DateTime.to_naive(),
5575
creative: creative,
5676
audience: audience,
77+
included_programming_languages: ["Rust"],
78+
included_topic_categories: ["Development"],
79+
excluded_programming_languages: ["Ruby"],
80+
excluded_topic_categories: ["Programming"],
5781
included_countries: ["US"]
5882
)
5983

@@ -66,6 +90,10 @@ defmodule AdService.Query.ForDisplayTest do
6690
end_date: Timex.now() |> Timex.shift(days: 1) |> DateTime.to_naive(),
6791
total_spend: Decimal.new(100),
6892
creative: creative,
93+
included_programming_languages: ["Rust"],
94+
included_topic_categories: ["Development"],
95+
excluded_programming_languages: ["Ruby"],
96+
excluded_topic_categories: ["Programming"],
6997
included_countries: ["IN"],
7098
audience: insert(:audience, %{programming_languages: ["Java", "Rust"]})
7199
)
@@ -80,12 +108,23 @@ defmodule AdService.Query.ForDisplayTest do
80108
end_date: Timex.now() |> Timex.shift(days: 1) |> DateTime.to_naive(),
81109
creative: creative,
82110
audience: audience,
111+
included_programming_languages: ["Rust"],
112+
included_topic_categories: ["Development"],
113+
excluded_programming_languages: ["Ruby"],
114+
excluded_topic_categories: ["Programming"],
83115
included_countries: ["CN"]
84116
)
85117

86118
[cdn_host: cdn_host] = Application.get_env(:code_fund, Framework.FileStorage)
87119

88-
{:ok, %{audience: audience, creative: creative, campaign: campaign, cdn_host: cdn_host}}
120+
{:ok,
121+
%{
122+
audience: audience,
123+
creative: creative,
124+
campaign: campaign,
125+
cdn_host: cdn_host,
126+
property: property
127+
}}
89128
end
90129

91130
describe "fallback_ad_by_property_id/1" do
@@ -122,13 +161,13 @@ defmodule AdService.Query.ForDisplayTest do
122161
end
123162

124163
describe "build/1" do
125-
test "get_by_property_filters excludes indicated countries", %{audience: audience} do
126-
refute AdService.Query.ForDisplay.build(audience, "CN", nil, ["Foobar"])
164+
test "get_by_property_filters excludes indicated countries", %{property: property} do
165+
refute AdService.Query.ForDisplay.build(property, "CN", nil, ["Foobar"])
127166
|> CodeFund.Repo.one()
128167
end
129168

130169
test "it returns advertisements by audience, included country and excluded advertisers", %{
131-
audience: audience,
170+
property: property,
132171
campaign: campaign,
133172
creative: creative
134173
} do
@@ -141,13 +180,16 @@ defmodule AdService.Query.ForDisplayTest do
141180
start_date: Timex.now() |> Timex.shift(days: -1) |> DateTime.to_naive(),
142181
end_date: Timex.now() |> Timex.shift(days: 1) |> DateTime.to_naive(),
143182
creative: creative,
144-
audience: audience,
183+
included_programming_languages: ["Ruby"],
184+
included_topic_categories: ["Programming"],
185+
excluded_programming_languages: ["Rust"],
186+
excluded_topic_categories: ["Development"],
145187
included_countries: ["US"],
146188
user: insert(:user, company: "Foobar")
147189
)
148190

149191
advertisement =
150-
AdService.Query.ForDisplay.build(audience, "US", nil, ["Foobar"])
192+
AdService.Query.ForDisplay.build(property, "US", nil, ["Foobar"])
151193
|> CodeFund.Repo.one()
152194

153195
small_image_asset = CodeFund.Schema.Asset |> Repo.get!(creative.small_image_asset.id)
@@ -178,7 +220,7 @@ defmodule AdService.Query.ForDisplayTest do
178220
end
179221

180222
test "it excludes campaigns which are not allowed on the weekends when its a weekend", %{
181-
audience: audience,
223+
property: property,
182224
creative: creative
183225
} do
184226
CodeFund.Schema.Campaign
@@ -195,22 +237,25 @@ defmodule AdService.Query.ForDisplayTest do
195237
end_date: Timex.now() |> Timex.shift(days: 1) |> DateTime.to_naive(),
196238
creative: creative,
197239
weekdays_only: true,
198-
audience: audience,
240+
included_programming_languages: ["Ruby"],
241+
included_topic_categories: ["Programming"],
242+
excluded_programming_languages: ["Rust"],
243+
excluded_topic_categories: ["Development"],
199244
included_countries: ["US"],
200245
user: insert(:user, company: "Acme")
201246
)
202247

203248
TimeMachinex.ManagedClock.set(DateTime.from_naive!(~N[2018-09-22 11:00:00], "Etc/UTC"))
204249

205250
advertisement =
206-
AdService.Query.ForDisplay.build(audience, "US", {72, 229, 28, 185}, ["Foobar"])
251+
AdService.Query.ForDisplay.build(property, "US", {72, 229, 28, 185}, ["Foobar"])
207252
|> CodeFund.Repo.one()
208253

209254
refute advertisement
210255
end
211256

212257
test "it will exclude campaigns that are over their daily budget", %{
213-
audience: audience,
258+
property: property,
214259
creative: creative
215260
} do
216261
CodeFund.Schema.Campaign
@@ -227,15 +272,18 @@ defmodule AdService.Query.ForDisplayTest do
227272
start_date: Timex.now() |> Timex.shift(days: -1) |> DateTime.to_naive(),
228273
end_date: Timex.now() |> Timex.shift(days: 1) |> DateTime.to_naive(),
229274
creative: creative,
230-
audience: audience,
275+
included_programming_languages: ["Ruby"],
276+
included_topic_categories: ["Programming"],
277+
excluded_programming_languages: ["Rust"],
278+
excluded_topic_categories: ["Development"],
231279
included_countries: ["US"],
232280
user: insert(:user, company: "Acme")
233281
)
234282

235283
insert(:impression, campaign: campaign, revenue_amount: Decimal.new(9.5))
236284

237285
advertisement =
238-
AdService.Query.ForDisplay.build(audience, "US", nil, ["Foobar"]) |> CodeFund.Repo.one()
286+
AdService.Query.ForDisplay.build(property, "US", nil, ["Foobar"]) |> CodeFund.Repo.one()
239287

240288
refute advertisement
241289
end

0 commit comments

Comments
 (0)