snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:05:30 +05:00
commit 64898b2c79
8999 changed files with 1757358 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
# Generated by Django 1.11.14 on 2018-09-25 12:02
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("zerver", "0189_userprofile_add_some_emojisets"),
]
operations = [
migrations.CreateModel(
name="BillingProcessor",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("state", models.CharField(max_length=20)),
("last_modified", models.DateTimeField(auto_now=True)),
(
"log_row",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.RealmAuditLog"
),
),
(
"realm",
models.OneToOneField(
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
),
),
],
),
migrations.CreateModel(
name="Coupon",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("percent_off", models.SmallIntegerField(unique=True)),
("stripe_coupon_id", models.CharField(max_length=255, unique=True)),
],
),
migrations.CreateModel(
name="Customer",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_customer_id", models.CharField(max_length=255, unique=True)),
("has_billing_relationship", models.BooleanField(default=False)),
(
"realm",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE, to="zerver.Realm"
),
),
],
),
migrations.CreateModel(
name="Plan",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("nickname", models.CharField(max_length=40, unique=True)),
("stripe_plan_id", models.CharField(max_length=255, unique=True)),
],
),
]

View File

@@ -0,0 +1,378 @@
# Generated by Django 5.0.7 on 2024-08-13 20:29
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
replaces = [
("corporate", "0001_initial"),
("corporate", "0002_customer_default_discount"),
("corporate", "0003_customerplan"),
("corporate", "0004_licenseledger"),
("corporate", "0005_customerplan_invoicing"),
("corporate", "0006_nullable_stripe_customer_id"),
("corporate", "0007_remove_deprecated_fields"),
("corporate", "0008_nullable_next_invoice_date"),
("corporate", "0009_customer_sponsorship_pending"),
("corporate", "0010_customerplan_exempt_from_from_license_number_check"),
("corporate", "0011_move_exempt_from_from_license_number_check_to_customer_model"),
("corporate", "0012_zulipsponsorshiprequest"),
("corporate", "0013_alter_zulipsponsorshiprequest_org_website"),
("corporate", "0014_customerplan_end_date"),
("corporate", "0015_event_paymentintent_session"),
("corporate", "0016_customer_add_remote_server_field"),
(
"corporate",
"0017_rename_exempt_from_from_license_number_check_customer_exempt_from_license_number_check",
),
("corporate", "0018_customer_cloud_xor_self_hosted"),
("corporate", "0019_zulipsponsorshiprequest_expected_total_users_and_more"),
("corporate", "0020_add_remote_realm_customers"),
("corporate", "0021_remove_session_payment_intent"),
("corporate", "0022_session_is_manual_license_management_upgrade_session"),
("corporate", "0023_zulipsponsorshiprequest_customer"),
("corporate", "0024_zulipsponsorshiprequest_fill_customer_data"),
("corporate", "0025_alter_zulipsponsorshiprequest_customer"),
("corporate", "0026_remove_zulipsponsorshiprequest_realm"),
("corporate", "0027_alter_zulipsponsorshiprequest_requested_by"),
("corporate", "0028_zulipsponsorshiprequest_requested_plan"),
("corporate", "0029_session_tier"),
("corporate", "0030_alter_zulipsponsorshiprequest_requested_plan"),
("corporate", "0031_customer_flat_discount_and_more"),
("corporate", "0032_customer_minimum_licenses"),
("corporate", "0033_customerplan_invoice_overdue_email_sent"),
("corporate", "0034_customer_discount_required_tier"),
("corporate", "0035_update_legacy_plan_next_invoice_date"),
("corporate", "0036_fix_customer_plans_scheduled_after_legacy_plan"),
("corporate", "0037_customerplanoffer"),
("corporate", "0038_customerplanoffer_sent_invoice_id_invoice"),
("corporate", "0039_backfill_end_date_for_fixed_price_plans"),
("corporate", "0040_customerplan_reminder_to_review_plan_email_sent"),
("corporate", "0041_fix_plans_on_free_trial_with_changes_in_schedule"),
("corporate", "0042_invoice_is_created_for_free_trial_upgrade_and_more"),
("corporate", "0043_remove_customer_default_discount_and_more"),
("corporate", "0044_convert_ids_to_bigints"),
]
initial = True
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("zerver", "0001_initial"),
# Requires RemoteRealm model for foreign keys.
("zilencer", "0035_remoterealmcount_remote_realm_and_more"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Customer",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_customer_id", models.CharField(max_length=255, null=True, unique=True)),
(
"realm",
models.OneToOneField(
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
("sponsorship_pending", models.BooleanField(default=False)),
("exempt_from_license_number_check", models.BooleanField(default=False)),
(
"remote_server",
models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="zilencer.remotezulipserver",
),
),
(
"remote_realm",
models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="zilencer.remoterealm",
),
),
("flat_discount", models.IntegerField(default=2000)),
("flat_discounted_months", models.IntegerField(default=0)),
("minimum_licenses", models.PositiveIntegerField(null=True)),
("required_plan_tier", models.SmallIntegerField(null=True)),
("annual_discounted_price", models.IntegerField(default=0)),
("monthly_discounted_price", models.IntegerField(default=0)),
],
),
migrations.CreateModel(
name="CustomerPlan",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("automanage_licenses", models.BooleanField(default=False)),
("charge_automatically", models.BooleanField(default=False)),
("price_per_license", models.IntegerField(null=True)),
("fixed_price", models.IntegerField(null=True)),
("discount", models.TextField(null=True)),
("billing_cycle_anchor", models.DateTimeField()),
("billing_schedule", models.SmallIntegerField()),
("next_invoice_date", models.DateTimeField(db_index=True, null=True)),
("tier", models.SmallIntegerField()),
("status", models.SmallIntegerField(default=1)),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
("invoicing_status", models.SmallIntegerField(default=1)),
("end_date", models.DateTimeField(null=True)),
("invoice_overdue_email_sent", models.BooleanField(default=False)),
("reminder_to_review_plan_email_sent", models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name="CustomerPlanOffer",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("fixed_price", models.IntegerField(null=True)),
("tier", models.SmallIntegerField()),
("status", models.SmallIntegerField()),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
("sent_invoice_id", models.CharField(max_length=255, null=True)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="Event",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_event_id", models.CharField(max_length=255)),
("type", models.CharField(max_length=255)),
("status", models.SmallIntegerField(default=1)),
("object_id", models.PositiveIntegerField(db_index=True)),
("handler_error", models.JSONField(default=None, null=True)),
(
"content_type",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="contenttypes.contenttype"
),
),
],
),
migrations.CreateModel(
name="Invoice",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_invoice_id", models.CharField(max_length=255, unique=True)),
("status", models.SmallIntegerField()),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
("is_created_for_free_trial_upgrade", models.BooleanField(default=False)),
(
"plan",
models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="corporate.customerplan",
),
),
],
),
migrations.CreateModel(
name="LicenseLedger",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("is_renewal", models.BooleanField(default=False)),
("event_time", models.DateTimeField()),
("licenses", models.IntegerField()),
("licenses_at_next_renewal", models.IntegerField(null=True)),
(
"plan",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customerplan"
),
),
],
),
migrations.CreateModel(
name="PaymentIntent",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_payment_intent_id", models.CharField(max_length=255, unique=True)),
("status", models.SmallIntegerField()),
("last_payment_error", models.JSONField(default=None, null=True)),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
],
),
migrations.CreateModel(
name="Session",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_session_id", models.CharField(max_length=255, unique=True)),
("type", models.SmallIntegerField()),
("status", models.SmallIntegerField(default=1)),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
(
"is_manual_license_management_upgrade_session",
models.BooleanField(default=False),
),
("tier", models.SmallIntegerField(null=True)),
],
),
migrations.CreateModel(
name="ZulipSponsorshipRequest",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"org_type",
models.PositiveSmallIntegerField(
choices=[
(0, "Unspecified"),
(10, "Business"),
(20, "Open-source project"),
(30, "Education (non-profit)"),
(35, "Education (for-profit)"),
(40, "Research"),
(50, "Event or conference"),
(60, "Non-profit (registered)"),
(70, "Government"),
(80, "Political group"),
(90, "Community"),
(100, "Personal"),
(1000, "Other"),
],
default=0,
),
),
("org_website", models.URLField(blank=True, null=True)),
("org_description", models.TextField(default="")),
(
"requested_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
("expected_total_users", models.TextField(default="")),
("paid_users_count", models.TextField(default="")),
("paid_users_description", models.TextField(default="")),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
(
"requested_plan",
models.CharField(
choices=[
("", "UNSPECIFIED"),
("Community", "COMMUNITY"),
("Basic", "BASIC"),
("Business", "BUSINESS"),
],
default="",
max_length=50,
),
),
],
),
# Operation cannot be squashed, because it's a reverse foreign
# key (`LicenseLedger` has a `CustomerPlan` column), and
# squashing it into the CreateModel would require creating a
# dependency loop.
migrations.AddField(
model_name="customerplan",
name="invoiced_through",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="corporate.LicenseLedger",
),
),
# Django's squashmigrations tooling seems unable to squash
# this operation into CreateModel. Likely it's possible to do
# so manually, but it's just a single operation.
migrations.AddConstraint(
model_name="customer",
constraint=models.CheckConstraint(
condition=models.Q(
("realm__isnull", False),
("remote_server__isnull", False),
("remote_realm__isnull", False),
_connector="OR",
),
name="has_associated_model_object",
),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.16 on 2018-12-12 20:19
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="customer",
name="default_discount",
field=models.DecimalField(decimal_places=4, max_digits=7, null=True),
),
]

View File

@@ -0,0 +1,42 @@
# Generated by Django 1.11.16 on 2018-12-22 21:05
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0002_customer_default_discount"),
]
operations = [
migrations.CreateModel(
name="CustomerPlan",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("licenses", models.IntegerField()),
("automanage_licenses", models.BooleanField(default=False)),
("charge_automatically", models.BooleanField(default=False)),
("price_per_license", models.IntegerField(null=True)),
("fixed_price", models.IntegerField(null=True)),
("discount", models.DecimalField(decimal_places=4, max_digits=6, null=True)),
("billing_cycle_anchor", models.DateTimeField()),
("billing_schedule", models.SmallIntegerField()),
("billed_through", models.DateTimeField()),
("next_billing_date", models.DateTimeField(db_index=True)),
("tier", models.SmallIntegerField()),
("status", models.SmallIntegerField(default=1)),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.Customer"
),
),
],
),
]

View File

@@ -0,0 +1,34 @@
# Generated by Django 1.11.18 on 2019-01-19 05:01
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0003_customerplan"),
]
operations = [
migrations.CreateModel(
name="LicenseLedger",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("is_renewal", models.BooleanField(default=False)),
("event_time", models.DateTimeField()),
("licenses", models.IntegerField()),
("licenses_at_next_renewal", models.IntegerField(null=True)),
(
"plan",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.CustomerPlan"
),
),
],
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 1.11.18 on 2019-01-28 13:04
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0004_licenseledger"),
]
operations = [
migrations.RenameField(
model_name="customerplan",
old_name="next_billing_date",
new_name="next_invoice_date",
),
migrations.RemoveField(
model_name="customerplan",
name="billed_through",
),
migrations.AddField(
model_name="customerplan",
name="invoiced_through",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="corporate.LicenseLedger",
),
),
migrations.AddField(
model_name="customerplan",
name="invoicing_status",
field=models.SmallIntegerField(default=1),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.18 on 2019-01-29 01:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0005_customerplan_invoicing"),
]
operations = [
migrations.AlterField(
model_name="customer",
name="stripe_customer_id",
field=models.CharField(max_length=255, null=True, unique=True),
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 1.11.18 on 2019-01-31 22:16
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("corporate", "0006_nullable_stripe_customer_id"),
]
operations = [
migrations.RemoveField(
model_name="billingprocessor",
name="log_row",
),
migrations.RemoveField(
model_name="billingprocessor",
name="realm",
),
migrations.DeleteModel(
name="Coupon",
),
migrations.DeleteModel(
name="Plan",
),
migrations.RemoveField(
model_name="customer",
name="has_billing_relationship",
),
migrations.RemoveField(
model_name="customerplan",
name="licenses",
),
migrations.DeleteModel(
name="BillingProcessor",
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 1.11.20 on 2019-04-11 00:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0007_remove_deprecated_fields"),
]
operations = [
migrations.AlterField(
model_name="customerplan",
name="next_invoice_date",
field=models.DateTimeField(db_index=True, null=True),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 2.2.13 on 2020-06-09 12:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0008_nullable_next_invoice_date"),
]
operations = [
migrations.AddField(
model_name="customer",
name="sponsorship_pending",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 3.2.2 on 2021-06-08 08:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0009_customer_sponsorship_pending"),
]
operations = [
migrations.AddField(
model_name="customerplan",
name="exempt_from_from_license_number_check",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,27 @@
# Generated by Django 3.2.4 on 2021-06-18 18:39
from django.db import migrations, models
class Migration(migrations.Migration):
"""
We haven't set the values for this field for the relevant organizations
as of this moment, so we can simply drop the column from CustomerPlan
and add it to Customer without worrying about losing the values.
"""
dependencies = [
("corporate", "0010_customerplan_exempt_from_from_license_number_check"),
]
operations = [
migrations.RemoveField(
model_name="customerplan",
name="exempt_from_from_license_number_check",
),
migrations.AddField(
model_name="customer",
name="exempt_from_from_license_number_check",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,62 @@
# Generated by Django 3.2.5 on 2021-07-15 17:15
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("zerver", "0333_alter_realm_org_type"),
("corporate", "0011_move_exempt_from_from_license_number_check_to_customer_model"),
]
operations = [
migrations.CreateModel(
name="ZulipSponsorshipRequest",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"org_type",
models.PositiveSmallIntegerField(
choices=[
(0, "Unspecified"),
(10, "Business"),
(20, "Open-source project"),
(30, "Education (non-profit)"),
(35, "Education (for-profit)"),
(40, "Research"),
(50, "Event or conference"),
(60, "Non-profit (registered)"),
(70, "Government"),
(80, "Political group"),
(90, "Community"),
(100, "Personal"),
(1000, "Other"),
],
default=0,
),
),
("org_website", models.URLField()),
("org_description", models.TextField(default="")),
(
"realm",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
(
"requested_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
),
),
],
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 3.2.5 on 2021-08-06 19:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0012_zulipsponsorshiprequest"),
]
operations = [
migrations.AlterField(
model_name="zulipsponsorshiprequest",
name="org_website",
field=models.URLField(blank=True, null=True),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 3.2.6 on 2021-09-17 10:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0013_alter_zulipsponsorshiprequest_org_website"),
]
operations = [
migrations.AddField(
model_name="customerplan",
name="end_date",
field=models.DateTimeField(null=True),
),
]

View File

@@ -0,0 +1,84 @@
# Generated by Django 3.2.9 on 2021-11-04 16:23
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("corporate", "0014_customerplan_end_date"),
]
operations = [
migrations.CreateModel(
name="PaymentIntent",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_payment_intent_id", models.CharField(max_length=255, unique=True)),
("status", models.SmallIntegerField()),
("last_payment_error", models.JSONField(default=None, null=True)),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
],
),
migrations.CreateModel(
name="Session",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_session_id", models.CharField(max_length=255, unique=True)),
("type", models.SmallIntegerField()),
("status", models.SmallIntegerField(default=1)),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
(
"payment_intent",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="corporate.paymentintent",
),
),
],
),
migrations.CreateModel(
name="Event",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_event_id", models.CharField(max_length=255)),
("type", models.CharField(max_length=255)),
("status", models.SmallIntegerField(default=1)),
("object_id", models.PositiveIntegerField(db_index=True)),
("handler_error", models.JSONField(default=None, null=True)),
(
"content_type",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="contenttypes.contenttype"
),
),
],
),
]

View File

@@ -0,0 +1,31 @@
# Generated by Django 3.2.9 on 2021-11-27 00:08
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zilencer", "0018_remoterealmauditlog"),
("zerver", "0370_realm_enable_spectator_access"),
("corporate", "0015_event_paymentintent_session"),
]
operations = [
migrations.AddField(
model_name="customer",
name="remote_server",
field=models.OneToOneField(
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="zilencer.remotezulipserver",
),
),
migrations.AlterField(
model_name="customer",
name="realm",
field=models.OneToOneField(
null=True, on_delete=django.db.models.deletion.CASCADE, to="zerver.realm"
),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.2 on 2023-04-10 18:22
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("corporate", "0016_customer_add_remote_server_field"),
]
operations = [
migrations.RenameField(
model_name="customer",
old_name="exempt_from_from_license_number_check",
new_name="exempt_from_license_number_check",
),
]

View File

@@ -0,0 +1,24 @@
# Generated by Django 4.2.1 on 2023-05-30 03:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"corporate",
"0017_rename_exempt_from_from_license_number_check_customer_exempt_from_license_number_check",
),
]
operations = [
migrations.AddConstraint(
model_name="customer",
constraint=models.CheckConstraint(
condition=models.Q(
("realm__isnull", False), ("remote_server__isnull", False), _connector="XOR"
),
name="cloud_xor_self_hosted",
),
),
]

View File

@@ -0,0 +1,27 @@
# Generated by Django 4.2.6 on 2023-11-11 14:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0018_customer_cloud_xor_self_hosted"),
]
operations = [
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="expected_total_users",
field=models.TextField(default=""),
),
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="paid_users_count",
field=models.TextField(default=""),
),
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="paid_users_description",
field=models.TextField(default=""),
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 4.2.7 on 2023-11-17 20:11
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zilencer", "0035_remoterealmcount_remote_realm_and_more"),
("corporate", "0019_zulipsponsorshiprequest_expected_total_users_and_more"),
]
operations = [
migrations.RemoveConstraint(
model_name="customer",
name="cloud_xor_self_hosted",
),
migrations.AddField(
model_name="customer",
name="remote_realm",
field=models.OneToOneField(
null=True, on_delete=django.db.models.deletion.CASCADE, to="zilencer.remoterealm"
),
),
migrations.AddConstraint(
model_name="customer",
constraint=models.CheckConstraint(
condition=models.Q(
("realm__isnull", False),
("remote_server__isnull", False),
("remote_realm__isnull", False),
_connector="OR",
),
name="has_associated_model_object",
),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 4.2.7 on 2023-11-18 14:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("corporate", "0020_add_remote_realm_customers"),
]
operations = [
migrations.RemoveField(
model_name="session",
name="payment_intent",
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.2.7 on 2023-11-21 11:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0021_remove_session_payment_intent"),
]
operations = [
migrations.AddField(
model_name="session",
name="is_manual_license_management_upgrade_session",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 4.2.7 on 2023-11-26 16:00
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0022_session_is_manual_license_management_upgrade_session"),
]
operations = [
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="customer",
field=models.ForeignKey(
null=True, on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
]

View File

@@ -0,0 +1,19 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("corporate", "0023_zulipsponsorshiprequest_customer"),
]
operations = [
migrations.RunSQL(
"""
UPDATE corporate_zulipsponsorshiprequest
SET customer_id = (
SELECT id FROM corporate_customer WHERE corporate_customer.realm_id = corporate_zulipsponsorshiprequest.realm_id
)
""",
elidable=True,
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 4.2.7 on 2023-11-26 16:13
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0024_zulipsponsorshiprequest_fill_customer_data"),
]
operations = [
migrations.AlterField(
model_name="zulipsponsorshiprequest",
name="customer",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
]

View File

@@ -0,0 +1,16 @@
# Generated by Django 4.2.7 on 2023-11-26 16:14
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("corporate", "0025_alter_zulipsponsorshiprequest_customer"),
]
operations = [
migrations.RemoveField(
model_name="zulipsponsorshiprequest",
name="realm",
),
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 4.2.7 on 2023-11-28 16:00
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("corporate", "0026_remove_zulipsponsorshiprequest_realm"),
]
operations = [
migrations.AlterField(
model_name="zulipsponsorshiprequest",
name="requested_by",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 4.2.8 on 2023-12-08 18:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0027_alter_zulipsponsorshiprequest_requested_by"),
]
operations = [
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="requested_plan",
field=models.CharField(
choices=[("", "UNSPECIFIED"), ("Community", "COMMUNITY"), ("Business", "BUSINESS")],
default="",
max_length=50,
),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.2.8 on 2023-12-18 09:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0028_zulipsponsorshiprequest_requested_plan"),
]
operations = [
migrations.AddField(
model_name="session",
name="tier",
field=models.SmallIntegerField(null=True),
),
]

View File

@@ -0,0 +1,26 @@
# Generated by Django 4.2.8 on 2023-12-19 11:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0029_session_tier"),
]
operations = [
migrations.AlterField(
model_name="zulipsponsorshiprequest",
name="requested_plan",
field=models.CharField(
choices=[
("", "UNSPECIFIED"),
("Community", "COMMUNITY"),
("Basic", "BASIC"),
("Business", "BUSINESS"),
],
default="",
max_length=50,
),
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 4.2.8 on 2023-12-19 12:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0030_alter_zulipsponsorshiprequest_requested_plan"),
]
operations = [
migrations.AddField(
model_name="customer",
name="flat_discount",
field=models.IntegerField(default=2000),
),
migrations.AddField(
model_name="customer",
name="flat_discounted_months",
field=models.IntegerField(default=0),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.2.8 on 2023-12-14 13:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0031_customer_flat_discount_and_more"),
]
operations = [
migrations.AddField(
model_name="customer",
name="minimum_licenses",
field=models.PositiveIntegerField(null=True),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.2.8 on 2024-01-10 07:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0032_customer_minimum_licenses"),
]
operations = [
migrations.AddField(
model_name="customerplan",
name="invoice_overdue_email_sent",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.2.8 on 2024-01-09 14:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0033_customerplan_invoice_overdue_email_sent"),
]
operations = [
migrations.AddField(
model_name="customer",
name="required_plan_tier",
field=models.SmallIntegerField(null=True),
),
]

View File

@@ -0,0 +1,28 @@
# Generated by Django 4.2.8 on 2024-01-25 05:49
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
from django.db.models import F
def update_legacy_plan_next_invoice_date(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
CustomerPlan = apps.get_model("corporate", "CustomerPlan")
CustomerPlan.TIER_SELF_HOSTED_LEGACY = 101
# For legacy plans, set next_invoice_date = end_date.
CustomerPlan.objects.filter(tier=CustomerPlan.TIER_SELF_HOSTED_LEGACY).update(
next_invoice_date=F("end_date")
)
class Migration(migrations.Migration):
dependencies = [
("corporate", "0034_customer_discount_required_tier"),
]
operations = [
migrations.RunPython(update_legacy_plan_next_invoice_date, elidable=True),
]

View File

@@ -0,0 +1,40 @@
# Generated by Django 4.2.8 on 2024-01-24 08:08
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def fix_customer_plans_scheduled_after_legacy_plan(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
CustomerPlan = apps.get_model("corporate", "CustomerPlan")
CustomerPlan.TIER_SELF_HOSTED_LEGACY = 101
CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END = 8
CustomerPlan.NEVER_STARTED = 12
CustomerPlan.INVOICING_STATUS_INITIAL_INVOICE_TO_BE_SENT = 3
# Legacy plans scheduled to switch to a new plan.
legacy_plans = CustomerPlan.objects.filter(
tier=CustomerPlan.TIER_SELF_HOSTED_LEGACY, status=CustomerPlan.SWITCH_PLAN_TIER_AT_PLAN_END
)
for legacy_plan in legacy_plans:
CustomerPlan.objects.filter(
customer=legacy_plan.customer,
billing_cycle_anchor=legacy_plan.end_date,
status=CustomerPlan.NEVER_STARTED,
).update(
next_invoice_date=legacy_plan.end_date,
invoicing_status=CustomerPlan.INVOICING_STATUS_INITIAL_INVOICE_TO_BE_SENT,
)
class Migration(migrations.Migration):
dependencies = [
("corporate", "0035_update_legacy_plan_next_invoice_date"),
]
operations = [
migrations.RunPython(fix_customer_plans_scheduled_after_legacy_plan, elidable=True),
]

View File

@@ -0,0 +1,36 @@
# Generated by Django 4.2.8 on 2024-01-27 09:03
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0036_fix_customer_plans_scheduled_after_legacy_plan"),
]
operations = [
migrations.CreateModel(
name="CustomerPlanOffer",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("fixed_price", models.IntegerField(null=True)),
("tier", models.SmallIntegerField()),
("status", models.SmallIntegerField()),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
],
options={
"abstract": False,
},
),
]

View File

@@ -0,0 +1,37 @@
# Generated by Django 4.2.9 on 2024-02-02 10:15
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0037_customerplanoffer"),
]
operations = [
migrations.AddField(
model_name="customerplanoffer",
name="sent_invoice_id",
field=models.CharField(max_length=255, null=True),
),
migrations.CreateModel(
name="Invoice",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("stripe_invoice_id", models.CharField(max_length=255, unique=True)),
("status", models.SmallIntegerField()),
(
"customer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="corporate.customer"
),
),
],
),
]

View File

@@ -0,0 +1,63 @@
# Generated by Django 4.2.9 on 2024-02-21 11:53
from datetime import datetime
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def add_months(dt: datetime, months: int) -> datetime:
assert months >= 0
# It's fine that the max day in Feb is 28 for leap years.
MAX_DAY_FOR_MONTH = {
1: 31,
2: 28,
3: 31,
4: 30,
5: 31,
6: 30,
7: 31,
8: 31,
9: 30,
10: 31,
11: 30,
12: 31,
}
year = dt.year
month = dt.month + months
while month > 12:
year += 1
month -= 12
day = min(dt.day, MAX_DAY_FOR_MONTH[month])
# datetimes don't support leap seconds, so don't need to worry about those
return dt.replace(year=year, month=month, day=day)
def backfill_end_date_for_fixed_price_plans(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
CustomerPlan = apps.get_model("corporate", "CustomerPlan")
CustomerPlan.ACTIVE = 1
fixed_price_plans = CustomerPlan.objects.filter(
status=CustomerPlan.ACTIVE, fixed_price__isnull=False
)
for plan in fixed_price_plans:
assert plan.end_date is None
assert plan.billing_cycle_anchor is not None
plan.end_date = add_months(plan.billing_cycle_anchor, 12)
plan.save(update_fields=["end_date"])
class Migration(migrations.Migration):
dependencies = [
("corporate", "0038_customerplanoffer_sent_invoice_id_invoice"),
]
operations = [
migrations.RunPython(
backfill_end_date_for_fixed_price_plans,
elidable=True,
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 4.2.9 on 2024-02-15 06:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0039_backfill_end_date_for_fixed_price_plans"),
]
operations = [
migrations.AddField(
model_name="customerplan",
name="reminder_to_review_plan_email_sent",
field=models.BooleanField(default=False),
),
]

View File

@@ -0,0 +1,51 @@
# Generated by Django 4.2.10 on 2024-03-01 14:05
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def fix_plans_on_free_trial_with_changes_in_schedule(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
CustomerPlan = apps.get_model("corporate", "CustomerPlan")
LicenseLedger = apps.get_model("corporate", "LicenseLedger")
CustomerPlan.FREE_TRIAL = 3
CustomerPlan.ENDED = 11
CustomerPlan.INVOICING_STATUS_DONE = 1
plans_on_free_trial_with_changed_schedule = CustomerPlan.objects.filter(
status=CustomerPlan.FREE_TRIAL, invoiced_through=None
)
for plan in plans_on_free_trial_with_changed_schedule:
assert plan.customer is not None
assert plan.billing_cycle_anchor is not None
ledger_entries = LicenseLedger.objects.filter(
plan=plan,
is_renewal=True,
event_time=plan.billing_cycle_anchor,
)
assert ledger_entries.count() == 1
plan.invoiced_through = ledger_entries.first()
plan.invoicing_status = CustomerPlan.INVOICING_STATUS_DONE
plan.save(update_fields=["invoiced_through", "invoicing_status"])
CustomerPlan.objects.filter(
customer=plan.customer,
status=CustomerPlan.ENDED,
billing_cycle_anchor=plan.billing_cycle_anchor,
).update(next_invoice_date=None)
class Migration(migrations.Migration):
dependencies = [
("corporate", "0040_customerplan_reminder_to_review_plan_email_sent"),
]
operations = [
migrations.RunPython(
fix_plans_on_free_trial_with_changes_in_schedule,
elidable=True,
),
]

View File

@@ -0,0 +1,28 @@
# Generated by Django 4.2.11 on 2024-04-10 03:17
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0041_fix_plans_on_free_trial_with_changes_in_schedule"),
]
operations = [
migrations.AddField(
model_name="invoice",
name="is_created_for_free_trial_upgrade",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="invoice",
name="plan",
field=models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="corporate.customerplan",
),
),
]

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().iterator():
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, elidable=True),
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),
),
]

View File

@@ -0,0 +1,75 @@
from django.db import migrations, models
class Migration(migrations.Migration):
atomic = False
dependencies = [
("corporate", "0043_remove_customer_default_discount_and_more"),
]
operations = [
migrations.AlterField(
model_name="customer",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="customerplan",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="customerplanoffer",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="event",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="invoice",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="licenseledger",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="paymentintent",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="session",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="zulipsponsorshiprequest",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.0.10 on 2025-01-14 17:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0001_squashed_0044_convert_ids_to_bigints"),
]
operations = [
migrations.AddField(
model_name="zulipsponsorshiprequest",
name="plan_to_use_zulip",
field=models.TextField(default=""),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.1.8 on 2025-05-27 14:26
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("corporate", "0045_zulipsponsorshiprequest_plan_to_use_zulip"),
]
operations = [
migrations.RenameField(
model_name="customerplan",
old_name="invoice_overdue_email_sent",
new_name="stale_audit_log_data_email_sent",
),
]

View File

@@ -0,0 +1,33 @@
# Generated by Django 5.2.14 on 2026-05-19 13:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("corporate", "0046_rename_customerplan_invoice_overdue_email_sent"),
]
# CustomerPlanOffer and CustomerPlan status field values
# that we are setting to be unique for each Customer.
CONFIGURED = 1
NEVER_STARTED = 12
operations = [
migrations.AddConstraint(
model_name="customerplan",
constraint=models.UniqueConstraint(
condition=models.Q(("status", NEVER_STARTED)),
fields=("customer",),
name="unique_never_started_plan_customer",
),
),
migrations.AddConstraint(
model_name="customerplanoffer",
constraint=models.UniqueConstraint(
condition=models.Q(("status", CONFIGURED)),
fields=("customer",),
name="unique_configured_plan_offer_customer",
),
),
]

View File