Skip to content

Commit

Permalink
Merge pull request #337 from compute-tooling/rm-unused-code
Browse files Browse the repository at this point in the history
Clean up unused code after PR #335
  • Loading branch information
hdoupe authored Sep 11, 2020
2 parents 2f485d3 + 09f918a commit 656c4f8
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 285 deletions.
6 changes: 2 additions & 4 deletions webapp/apps/billing/admin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
from django.contrib import admin

from .models import (Customer, Product, Plan, Subscription, SubscriptionItem,
UsageRecord, Event)
from .models import Customer, Product, Plan, Subscription, SubscriptionItem, Event

# Register your models here.
admin.site.register(Customer)
admin.site.register(Product)
admin.site.register(Plan)
admin.site.register(Subscription)
admin.site.register(SubscriptionItem)
admin.site.register(UsageRecord)
admin.site.register(Event)
admin.site.register(Event)
14 changes: 14 additions & 0 deletions webapp/apps/billing/migrations/0006_delete_usagerecord.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated by Django 3.0.10 on 2020-09-11 14:33

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("billing", "0005_auto_20200306_1600"),
]

operations = [
migrations.DeleteModel(name="UsageRecord",),
]
130 changes: 1 addition & 129 deletions webapp/apps/billing/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ class RequiredLocalInstances(Exception):


class CustomerManager(models.Manager):
def sync_subscriptions(self):
for customer in self.all():
print("user", customer.user.username)
customer.sync_subscriptions()
pass


class UpdateStatus(Enum):
Expand Down Expand Up @@ -82,44 +79,6 @@ def update_source(self, stripe_token):
self.default_source = stripe_token
self.save()

def sync_subscriptions(self, plans=None):
public_plans = Plan.get_public_plans(usage_type="metered")
if plans is None:
plans = public_plans
do_update = True
try:
sub = self.subscriptions.get(subscription_type="primary")
curr_plans = [plan.id for plan in sub.plans.all()]
not_subscribed = public_plans.filter(
~Q(id__in=curr_plans), usage_type="metered"
)
# Don't call stripe api with empty list of plans!
if not_subscribed:
print(
"adding plans: ",
self.user.username,
[ns.nickname for ns in not_subscribed],
)
stripe_sub = stripe.Subscription.modify(
sub.stripe_id,
items=[{"plan": plan.stripe_id} for plan in not_subscribed],
)
sub.plans.add(*not_subscribed)
sub.save()
else:
# no need to update.
do_update = False
except Subscription.DoesNotExist:
stripe_sub = Subscription.create_stripe_object(self, plans)
sub = Subscription.construct(
stripe_sub, self, plans, subscription_type="primary"
)
if do_update:
for raw_si in stripe_sub["items"]["data"]:
stripe_si = SubscriptionItem.get_stripe_object(raw_si["id"])
plan = public_plans.get(stripe_id=raw_si["plan"]["id"])
si, created = SubscriptionItem.get_or_construct(stripe_si.id, plan, sub)

def card_info(self):
"""Returns last 4 digits and brand of default source or None"""
stripe_obj = Customer.get_stripe_object(self.stripe_id)
Expand Down Expand Up @@ -414,10 +373,6 @@ def get_or_construct(stripe_id, product=None):
plan, created = Plan.objects.get(stripe_id), False
return (plan, created)

@staticmethod
def get_public_plans(**kwargs):
return Plan.objects.filter(product__project__is_public=True, **kwargs)


class Subscription(models.Model):
# raises error on deletion
Expand Down Expand Up @@ -564,63 +519,6 @@ def get_or_construct(stripe_id, plan=None, subscription=None):
return (si, created)


class UsageRecord(models.Model):
INC = "increment"
SET = "set"
ACTION_CHOICES = ((INC, "increment"), (SET, "set"))
stripe_id = models.CharField(max_length=255, unique=True)
livemode = models.BooleanField(default=False)
action = models.CharField(max_length=9, choices=ACTION_CHOICES, default=INC)
quantity = models.IntegerField(default=0)
subscription_item = models.ForeignKey(
SubscriptionItem, on_delete=models.CASCADE, related_name="usage_records"
)
timestamp = models.DateTimeField()

@staticmethod
def create_stripe_object(
quantity, timestamp, subscription_item, action="increment"
):
stripe_usage_record = stripe.UsageRecord.create(
quantity=quantity,
# None implies now
timestamp=timestamp or math.floor(datetime.now().timestamp()),
subscription_item=subscription_item.stripe_id,
action=action,
)
return stripe_usage_record

@staticmethod
def get_stripe_object(stripe_id):
"""
`stripe.UsageRecord` does not have a `get` method
"""
raise NotImplementedError()

@staticmethod
def construct(stripe_usage_record, subscription_item):
print("construct", stripe_usage_record)
usage_record = UsageRecord.objects.create(
stripe_id=stripe_usage_record.id,
livemode=stripe_usage_record.livemode,
quantity=stripe_usage_record.quantity,
subscription_item=subscription_item,
timestamp=timestamp_to_datetime(stripe_usage_record.timestamp),
)
return usage_record

@staticmethod
def get_or_construct(stripe_id, subscription_item=None):
try:
(usage_record, created) = (
UsageRecord.objects.get(stripe_id=stripe_id),
False,
)
except IntegrityError:
usage_record, created = UsageRecord.objects.get(stripe_id), False
return (usage_record, created)


class Event(models.Model):
stripe_id = models.CharField(max_length=255, unique=True)
created = models.DateTimeField()
Expand Down Expand Up @@ -648,32 +546,6 @@ def construct(stripe_event, customer=None, invoice=None):
return event


def create_billing_objects(project):
if USE_STRIPE and (not hasattr(project, "product") or project.product is None):
owner = project.owner.user.username
title = project.title
name = f"{owner}/{title}"
print("creating billing objects for ", name)
stripe_product = Product.create_stripe_object(name)
product = Product.construct(stripe_product, project)
stripe_plan_lic = Plan.create_stripe_object(
amount=0,
product=product,
usage_type="licensed",
interval="month",
currency="usd",
)
Plan.construct(stripe_plan_lic, product)
stripe_plan_met = Plan.create_stripe_object(
amount=1,
product=product,
usage_type="metered",
interval="month",
currency="usd",
)
Plan.construct(stripe_plan_met, product)


def create_pro_billing_objects():
if Product.objects.filter(name="Compute Studio Subscription").count() == 0:
stripe_obj = Product.create_stripe_object("Compute Studio Subscription")
Expand Down
4 changes: 4 additions & 0 deletions webapp/apps/billing/tests/test_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def ea_deployments(profile):
)


@pytest.mark.requires_stripe
class TestInvoice:
def test_owner_resources(
self,
Expand Down Expand Up @@ -191,6 +192,7 @@ def test_owner_resources(
"sponsor": {},
},
}

stripe_invoice = profile_invoices["invoice"]

assert profile_invoices["invoice"].amount_due == int(
Expand Down Expand Up @@ -250,6 +252,7 @@ def test_sponsor_resources(
},
},
}

stripe_invoice = profile_invoices["invoice"]

assert profile_invoices["invoice"].amount_due == int(100 * sponsored_sims_cost)
Expand Down Expand Up @@ -297,6 +300,7 @@ def test_other_profile_resources(
"sponsor": {},
},
}

stripe_invoice = profile_invoices["invoice"]

assert profile_invoices["invoice"].amount_due == int(
Expand Down
128 changes: 2 additions & 126 deletions webapp/apps/billing/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
Product,
Subscription,
SubscriptionItem,
UsageRecord,
create_pro_billing_objects,
UpdateStatus,
)
Expand Down Expand Up @@ -47,143 +46,20 @@ def test_construct_customer(self, stripe_customer, user):
assert not created
assert not customer.livemode

def test_construct(self):
product = Product.objects.get(name="modeler/Used-for-testing")
assert (
f"{product.project.owner.user.username}/{product.project.title}"
== product.name
)
assert (
Plan.objects.filter(product__name="modeler/Used-for-testing").count() == 2
)

def test_construct_subscription(self, basiccustomer, licensed_plan, metered_plan):
stripe_subscription = Subscription.create_stripe_object(
basiccustomer, [licensed_plan, metered_plan]
)
assert stripe_subscription

subscription, created = Subscription.get_or_construct(
stripe_subscription.id,
customer=basiccustomer,
plans=[licensed_plan, metered_plan],
)

for raw_si in stripe_subscription["items"]["data"]:
stripe_si = SubscriptionItem.get_stripe_object(raw_si["id"])
plan, created = Plan.get_or_construct(raw_si["plan"]["id"])
assert not created
si, created = SubscriptionItem.get_or_construct(
stripe_si.id, plan, subscription
)
assert created
assert si
assert si.stripe_id == raw_si["id"]
assert si.plan == plan
assert si.subscription == subscription

assert subscription
assert created
assert subscription.customer == basiccustomer
qs = Subscription.objects.filter(
plans__stripe_id=licensed_plan.stripe_id,
customer__stripe_id=basiccustomer.stripe_id,
)
assert qs.count() == 1
assert subscription.subscription_items.count() == 2

subscription, created = Subscription.get_or_construct(
stripe_subscription.stripe_id
)

assert subscription
assert not created
assert subscription.customer == basiccustomer
assert subscription.subscription_items.count() == 2

def test_metered_subscription_item(self, subscription):
assert subscription
si = subscription.subscription_items.get(plan__usage_type="metered")
assert si
assert si.plan.usage_type == "metered"
ts = math.floor(datetime.now().timestamp())
stripe_usage_record = UsageRecord.create_stripe_object(
quantity=10, timestamp=ts, subscription_item=si, action="increment"
)
assert stripe_usage_record
print("one", stripe_usage_record)
usage_record = UsageRecord.construct(stripe_usage_record, si)

assert usage_record
assert usage_record.stripe_id == stripe_usage_record.id
assert usage_record.livemode == False
assert usage_record.action == "increment"
assert usage_record.quantity == 10
assert usage_record.subscription_item == si

def test_update_customer(self, customer):
tok = "tok_bypassPending"
prev_source = customer.default_source
customer.update_source(tok)
assert customer.default_source != prev_source

def test_cancel_subscriptions(self, customer):
def test_cancel_subscriptions(self, pro_profile):
customer = pro_profile.user.customer
for sub in customer.subscriptions.all():
assert not sub.cancel_at_period_end
customer.cancel_subscriptions()
for sub in customer.subscriptions.all():
assert sub.cancel_at_period_end

def test_customer_sync_subscriptions(self, db, client):
u = User.objects.create_user(
username="synctest", email="[email protected]", password="syncer2222"
)
p = Profile.objects.create(user=u, is_active=True)
stripe_customer = stripe.Customer.create(
email=u.email, source="tok_bypassPending"
)
c, _ = Customer.get_or_construct(stripe_customer.id, u)
assert c.subscriptions.count() == 1
assert c.current_plan(as_dict=False).plan == Plan.objects.get(
nickname="Free Plan"
)

# test new customer gets all subscriptions.
c.sync_subscriptions()
primary_sub = c.subscriptions.get(subscription_type="primary")
curr_plans = [plan.id for plan in primary_sub.plans.all()]
assert set(curr_plans) == set(
pp.id for pp in Plan.get_public_plans(usage_type="metered")
)

# create new product and test that customer gets subscribed to it.
client.login(username=u.username, password="syncer2222")
post_data = {
"title": "New-Model",
"oneliner": "oneliner",
"description": "**Super** new!",
"repo_url": "https://github.com/compute-tooling/compute-studio",
"repo_tag": "dev",
"cpu": 3,
"memory": 9,
"listed": True,
}

with mock_sync_projects():
resp = client.post("/apps/api/v1/", post_data)
assert resp.status_code == 200
Project.objects.sync_products()
Customer.objects.sync_subscriptions()

c = Customer.objects.get(user__username="synctest")
primary_sub = c.subscriptions.get(subscription_type="primary")
curr_plans = [plan.id for plan in primary_sub.plans.all()]
assert set(curr_plans) == set(
pp.id for pp in Plan.get_public_plans(usage_type="metered")
)

Customer.objects.sync_subscriptions()

def test_create_pro_billing_objects(self, db):
# this function is called in conftest.py
# create_pro_billing_objects()
Expand Down
5 changes: 1 addition & 4 deletions webapp/apps/comp/asyncsubmit.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ def submit(self):
}
print("submit", data)
project = self.sim.project
if project.latest_tag is None:
tag = project.latest_tag_deprecated
else:
tag = str(project.latest_tag)
tag = str(project.latest_tag)
self.submitted_id = self.compute.submit_job(
project=inputs.project, task_name=actions.SIM, task_kwargs=data, tag=tag,
)
Expand Down
Loading

0 comments on commit 656c4f8

Please sign in to comment.