support: Set discounted price instead percentage for customers.

This allows us to set the price of a plan exactly as discussed with
the customer.
This commit is contained in:
Aman Agrawal
2024-05-06 04:12:15 +00:00
committed by Tim Abbott
parent ed5e0fa141
commit 7203661d99
26 changed files with 722 additions and 287 deletions

View File

@@ -0,0 +1,89 @@
# Generated by Django 5.0.5 on 2024-05-03 06:50
from decimal import Decimal
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
# It's generally unsafe to import product code from migrations,
# because the migration will be run with the **current** version of
# that code, not the version at the time of the migration. But because
# this migration will only be run for Zulip Cloud, this is OK.
from corporate.lib.stripe import get_price_per_license
def calculate_discounted_price_per_license(
original_price_per_license: int, discount: Decimal
) -> int:
# There are no fractional cents in Stripe, so round down to nearest integer.
return int(float(original_price_per_license * (1 - discount / 100)) + 0.00001)
def calculate_discounted_price(apps: StateApps, schema_editor: BaseDatabaseSchemaEditor) -> None:
"""Migrates existing customers with a configured default discount to
instead have discounted prices for their configured required_plan_tier.
Does not operate on CustomerPlan fields, since those are already
resolved into a price.
"""
BILLING_SCHEDULE_ANNUAL = 1
BILLING_SCHEDULE_MONTHLY = 2
Customer = apps.get_model("corporate", "Customer")
customers_to_update = []
for customer in Customer.objects.all():
if not customer.required_plan_tier or not customer.default_discount:
continue
annual_price_per_license = get_price_per_license(
customer.required_plan_tier, BILLING_SCHEDULE_ANNUAL
)
customer.annual_discounted_price = calculate_discounted_price_per_license(
annual_price_per_license, customer.default_discount
)
monthly_price_per_license = get_price_per_license(
customer.required_plan_tier, BILLING_SCHEDULE_MONTHLY
)
customer.monthly_discounted_price = calculate_discounted_price_per_license(
monthly_price_per_license, customer.default_discount
)
customers_to_update.append(customer)
print(
f"\nChanging price for {customer.id}: {customer.default_discount} => {customer.annual_discounted_price}/{customer.monthly_discounted_price}"
)
Customer.objects.bulk_update(
customers_to_update, ["annual_discounted_price", "monthly_discounted_price"]
)
class Migration(migrations.Migration):
dependencies = [
("corporate", "0042_invoice_is_created_for_free_trial_upgrade_and_more"),
]
operations = [
migrations.AddField(
model_name="customer",
name="annual_discounted_price",
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name="customer",
name="monthly_discounted_price",
field=models.IntegerField(default=0),
),
# Populate the new discounted price fields based on existing default discount.
migrations.RunPython(calculate_discounted_price),
migrations.RemoveField(
model_name="customer",
name="default_discount",
),
# This automatically converts the decimal to string so we don't need to do anything here.
migrations.AlterField(
model_name="customerplan",
name="discount",
field=models.TextField(null=True),
),
]