Skip to content

Commit

Permalink
switch invoice fields to fk (#280)
Browse files Browse the repository at this point in the history
  • Loading branch information
diego-escobedo authored Nov 10, 2022
1 parent 58e5bcd commit 4a94fce
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 155 deletions.
15 changes: 3 additions & 12 deletions backend/metering_billing/invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
now_utc,
)
from metering_billing.utils.enums import FLAT_FEE_BILLING_TYPE, INVOICE_STATUS
from rest_framework import serializers

from .webhooks import invoice_created_webhook

Expand All @@ -27,11 +26,6 @@ def generate_invoice(subscription, draft=False, charge_next_plan=False):
Generate an invoice for a subscription.
"""
from metering_billing.models import CustomerBalanceAdjustment, Invoice, PlanVersion
from metering_billing.serializers.internal_serializers import (
InvoiceCustomerSerializer,
InvoiceOrganizationSerializer,
InvoiceSubscriptionSerializer,
)
from metering_billing.serializers.model_serializers import InvoiceSerializer

issue_date = now_utc()
Expand Down Expand Up @@ -185,15 +179,12 @@ def generate_invoice(subscription, draft=False, charge_next_plan=False):
summary_dict = make_all_dates_times_strings(summary_dict)

# create kwargs for invoice
org_serializer = InvoiceOrganizationSerializer(organization)
customer_serializer = InvoiceCustomerSerializer(customer)
subscription_serializer = InvoiceSubscriptionSerializer(subscription)
invoice_kwargs = {
"cost_due": amount,
"issue_date": issue_date,
"organization": org_serializer.data,
"customer": customer_serializer.data,
"subscription": make_all_dates_times_strings(subscription_serializer.data),
"organization": organization,
"customer": customer,
"subscription": subscription,
"payment_status": INVOICE_STATUS.DRAFT if draft else INVOICE_STATUS.UNPAID,
"external_payment_obj_id": None,
"external_payment_obj_type": None,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Generated by Django 4.0.5 on 2022-11-10 21:00

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("metering_billing", "0066_change_unique_rate_to_count"),
]

operations = [
migrations.RenameField(
model_name="historicalinvoice",
old_name="customer",
new_name="old_customer",
),
migrations.RenameField(
model_name="historicalinvoice",
old_name="organization",
new_name="old_organization",
),
migrations.RenameField(
model_name="historicalinvoice",
old_name="subscription",
new_name="old_subscription",
),
migrations.RenameField(
model_name="invoice",
old_name="customer",
new_name="old_customer",
),
migrations.RenameField(
model_name="invoice",
old_name="organization",
new_name="old_organization",
),
migrations.RenameField(
model_name="invoice",
old_name="subscription",
new_name="old_subscription",
),
migrations.RemoveField(
model_name="historicalinvoice",
name="external_payment_obj",
),
migrations.RemoveField(
model_name="invoice",
name="external_payment_obj",
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Generated by Django 4.0.5 on 2022-11-10 21:01

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
(
"metering_billing",
"0067_rename_customer_historicalinvoice_old_customer_and_more",
),
]

operations = [
migrations.AddField(
model_name="historicalinvoice",
name="customer",
field=models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="metering_billing.customer",
),
),
migrations.AddField(
model_name="historicalinvoice",
name="organization",
field=models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="metering_billing.organization",
),
),
migrations.AddField(
model_name="historicalinvoice",
name="subscription",
field=models.ForeignKey(
blank=True,
db_constraint=False,
null=True,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name="+",
to="metering_billing.subscription",
),
),
migrations.AddField(
model_name="invoice",
name="customer",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="invoices",
to="metering_billing.customer",
),
),
migrations.AddField(
model_name="invoice",
name="organization",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="invoices",
to="metering_billing.organization",
),
),
migrations.AddField(
model_name="invoice",
name="subscription",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="invoices",
to="metering_billing.subscription",
),
),
]
72 changes: 72 additions & 0 deletions backend/metering_billing/migrations/0069_transfer_invoice_to_fk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Generated by Django 4.0.5 on 2022-11-10 21:02

from django.db import migrations


def migrate_jsonfields_to_fk(apps, schema_editor):
Invoice = apps.get_model("metering_billing", "Invoice")
Organization = apps.get_model("metering_billing", "Organization")
Subscription = apps.get_model("metering_billing", "Subscription")
Customer = apps.get_model("metering_billing", "Customer")

invoice_org_dict = {}
invoice_customer_dict = {}
invoice_sub_dict = {}
for invoice in Invoice.objects.all():
try:
invoice_org = invoice.old_organization["company_name"]
except:
print(invoice.__dict__)
raise
invoice_customer = invoice.old_customer["customer_id"]
invoice_sub = invoice.old_subscription["subscription_id"]

if invoice_org in invoice_org_dict:
invoice_org_object = invoice_org_dict[invoice_org]
else:
try:
invoice_org_object = Organization.objects.get(company_name=invoice_org)
except Organization.DoesNotExist:
invoice_org_object = None
print(f"Invoice {invoice.pk} has no organization")
invoice_org_dict[invoice_org] = invoice_org_object
invoice.organization = invoice_org_object

if invoice_customer in invoice_customer_dict:
invoice_customer_object = invoice_customer_dict[invoice_customer]
else:
try:
invoice_customer_object = Customer.objects.get(
organization=invoice_org_object, customer_id=invoice_customer
)
except:
invoice_customer_object = None
print(f"Invoice {invoice.pk} has no customer")
invoice_customer_dict[invoice_customer] = invoice_customer_object
invoice.customer = invoice_customer_object

if invoice_sub in invoice_sub_dict:
invoice_sub_object = invoice_sub_dict[invoice_sub]
else:
try:
invoice_sub_object = Subscription.objects.get(
organization=invoice_org_object, subscription_id=invoice_sub
)
except:
invoice_sub_object = None
print(f"Invoice {invoice.pk} has no subscription")
invoice_sub_dict[invoice_sub] = invoice_sub_object
invoice.subscription = invoice_sub_object

invoice.save()


class Migration(migrations.Migration):

dependencies = [
("metering_billing", "0068_historicalinvoice_customer_and_more"),
]

operations = [
migrations.RunPython(migrate_jsonfields_to_fk),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 4.0.5 on 2022-11-10 21:22

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("metering_billing", "0069_transfer_invoice_to_fk"),
]

operations = [
migrations.RemoveField(
model_name="historicalinvoice",
name="old_customer",
),
migrations.RemoveField(
model_name="historicalinvoice",
name="old_organization",
),
migrations.RemoveField(
model_name="historicalinvoice",
name="old_subscription",
),
migrations.RemoveField(
model_name="invoice",
name="old_customer",
),
migrations.RemoveField(
model_name="invoice",
name="old_organization",
),
migrations.RemoveField(
model_name="invoice",
name="old_subscription",
),
]
13 changes: 9 additions & 4 deletions backend/metering_billing/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,15 +537,20 @@ class Invoice(models.Model):
invoice_id = models.CharField(
max_length=100, null=False, blank=True, default=invoice_uuid, unique=True
)
external_payment_obj = models.JSONField(default=dict, blank=True, null=True)
external_payment_obj_id = models.CharField(max_length=200, blank=True, null=True)
external_payment_obj_type = models.CharField(
choices=PAYMENT_PROVIDERS.choices, max_length=40, null=True, blank=True
)
line_items = models.JSONField()
organization = models.JSONField()
customer = models.JSONField()
subscription = models.JSONField()
organization = models.ForeignKey(
Organization, on_delete=models.CASCADE, null=True, related_name="invoices"
)
customer = models.ForeignKey(
Customer, on_delete=models.CASCADE, null=True, related_name="invoices"
)
subscription = models.ForeignKey(
"Subscription", on_delete=models.CASCADE, null=True, related_name="invoices"
)
history = HistoricalRecords()

def __str__(self):
Expand Down
19 changes: 4 additions & 15 deletions backend/metering_billing/payment_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,6 @@ def import_payment_objects(self, organization):

def _import_payment_objects_for_customer(self, customer):
from metering_billing.models import Invoice
from metering_billing.serializers.internal_serializers import (
InvoiceCustomerSerializer,
InvoiceOrganizationSerializer,
)

stripe.api_key = self.secret_key
invoices = stripe.PaymentIntent.list(
Expand All @@ -244,7 +240,7 @@ def _import_payment_objects_for_customer(self, customer):
Decimal(stripe_invoice.amount) / 100, stripe_invoice.currency
)
invoice_kwargs = {
"customer": InvoiceCustomerSerializer(customer).data,
"customer": customer,
"cost_due": cost_due,
"issue_date": datetime.datetime.fromtimestamp(
stripe_invoice.created, pytz.utc
Expand All @@ -253,10 +249,8 @@ def _import_payment_objects_for_customer(self, customer):
"cust_connected_to_payment_provider": True,
"external_payment_obj_id": stripe_invoice.id,
"external_payment_obj_type": PAYMENT_PROVIDERS.STRIPE,
"organization": InvoiceOrganizationSerializer(
customer.organization
).data,
"subscription": {},
"organization": customer.organization,
"subscription": None,
"line_items": {},
}
lotus_invoice = Invoice.objects.create(**invoice_kwargs)
Expand Down Expand Up @@ -315,12 +309,7 @@ def create_payment_object(self, invoice) -> str:
stripe.api_key = self.secret_key
# check everything works as expected + build invoice item
assert invoice.external_payment_obj_id is None
organization = Organization.objects.get(
company_name=invoice.organization["company_name"]
)
customer = Customer.objects.get(
organization=organization, customer_id=invoice.customer["customer_id"]
)
customer = invoice.customer
stripe_customer_id = customer.integrations.get(
PAYMENT_PROVIDERS.STRIPE, {}
).get("id")
Expand Down
Loading

0 comments on commit 4a94fce

Please sign in to comment.