Skip to content

Commit

Permalink
Add discounts to the dashboard
Browse files Browse the repository at this point in the history
The discounts come in the form of Stripe coupons.
The description can be edited in Stripe.
Currently, we have just a 10% and 15% coupon
based on the total campaign size.

They appear in:

- The create/edit flight screens (for staff).
  The discounts are not automatically applied yet.
  When a flight is renewed, the discount is renewed by default.
- They appear in the memo section of invoices
- They are displayed in the flight metadata to advertisers
  • Loading branch information
davidfischer committed Oct 10, 2023
1 parent b3df592 commit df2825c
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 16 deletions.
28 changes: 14 additions & 14 deletions adserver/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,10 @@ def action_create_draft_invoice(self, request, queryset):
)
return

# Any flight with the discount will result in the discount being in the memo
invoice_discount = None
total_cost = 0 # In US cents

for flight in flights:
message_components = ["Advertising", flight.name]
unit_amount = 0
Expand All @@ -641,16 +644,13 @@ def action_create_draft_invoice(self, request, queryset):
unit_amount = flight.cpc * 100 # Convert to US cents
quantity = flight.sold_clicks
elif flight.cpm:
priced_by_view = bool(flight.sold_impressions % 1000)
if priced_by_view:
print(unit_amount, quantity)
unit_amount = flight.cpm / 10 # Convert to US cents
message_components.append("${:.2f} CPM".format(flight.cpm))
quantity = flight.sold_impressions
else:
unit_amount = flight.cpm * 100 # Convert to US cents
message_components.append("per 1k impressions")
quantity = flight.sold_impressions // 1000
# Convert CPM to US cents (eg. $4.25 CPM -> 0.425 cents)
unit_amount = flight.cpm / 10
message_components.append("${:.2f} CPM".format(flight.cpm))
quantity = flight.sold_impressions

if flight.discount:
invoice_discount = flight.discount

total_cost += unit_amount * quantity

Expand All @@ -670,14 +670,14 @@ def action_create_draft_invoice(self, request, queryset):
)

# https://stripe.com/docs/api/invoices/create
description = "Thanks for your business!"
if invoice_discount:
description = f"Includes {invoice_discount} discount. " + description
inv = stripe.Invoice.create(
customer=advertiser.djstripe_customer.id,
auto_advance=False, # Draft invoice
collection_method="send_invoice",
# Check just under 3k just in case there's a rounding issue
description="Includes 10% volume discount"
if total_cost >= 290_000
else "Thanks for your business!",
description=description,
custom_fields=[
{"name": "Advertiser", "value": advertiser.slug[:30]},
{
Expand Down
12 changes: 10 additions & 2 deletions adserver/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class Meta:
"targeting_parameters",
"traffic_fill",
"traffic_cap",
"discount",
)


Expand Down Expand Up @@ -238,7 +239,8 @@ def __init__(self, *args, **kwargs):
),
css_class="my-3",
),
# NOTE: remove this when this form is made for non-staff users
# NOTE: remove these when this form is made for non-staff users
Field("discount"),
Field("priority_multiplier"),
Fieldset(
_("Flight targeting"),
Expand Down Expand Up @@ -345,6 +347,7 @@ class Meta:
"sold_clicks",
"cpm",
"sold_impressions",
"discount",
"priority_multiplier",
)
widgets = {
Expand Down Expand Up @@ -536,7 +539,12 @@ def save(self, commit=True):
instance = super().save(commit)

# Copy flight fields that aren't part of the form
for field in ("targeting_parameters", "priority_multiplier", "traffic_cap"):
for field in (
"targeting_parameters",
"priority_multiplier",
"traffic_cap",
"discount",
):
setattr(instance, field, getattr(self.old_flight, field))
instance.save()

Expand Down
39 changes: 39 additions & 0 deletions adserver/migrations/0088_linked_discounts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 4.2.4 on 2023-10-10 22:08
import django.db.models.deletion
from django.db import migrations
from django.db import models


class Migration(migrations.Migration):

dependencies = [
("djstripe", "0012_2_8"),
("adserver", "0087_publisher_allow_multiple_placements"),
]

operations = [
migrations.AddField(
model_name="flight",
name="discount",
field=models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="djstripe.coupon",
),
),
migrations.AddField(
model_name="historicalflight",
name="discount",
field=models.ForeignKey(
blank=True,
db_constraint=False,
default=None,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="djstripe.coupon",
),
),
]
7 changes: 7 additions & 0 deletions adserver/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,13 @@ class Flight(TimeStampedModel, IndestructibleModel):
verbose_name=_("Stripe invoices"),
blank=True,
)
discount = models.ForeignKey(
djstripe_models.Coupon,
on_delete=models.SET_NULL,
blank=True,
null=True,
default=None,
)

history = HistoricalRecords()

Expand Down
4 changes: 4 additions & 0 deletions adserver/templates/adserver/includes/flight-metadata.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
<dt>{% trans 'Cost per 1,000 impressions (CPM)' %}</dt>
<dd>${{ flight.cpm|floatformat:2 }}</dd>
{% endif %}
{% if flight.discount %}
<dt title="{% trans 'The price above includes this discount.' %}" data-toggle="tooltip" data-placement="left">{% trans 'Discount' %}</dt>
<dd>{{ flight.discount }}</dd>
{% endif %}
{% if flight.start_date %}
<dt>{% trans 'Estimated start date' %}</dt>
<dd>{{ flight.start_date }}</dd>
Expand Down

0 comments on commit df2825c

Please sign in to comment.