forked from uncloud/uncloud
- Added PricingPlan Model
- Implement a complete cycle for buying a Matrix Chat Host - Refactor the Payement cycle and stripe related methods
This commit is contained in:
parent
e205d8d07c
commit
b7aa1c6971
81 changed files with 5079 additions and 810 deletions
|
|
@ -5,52 +5,28 @@ from django.utils import timezone
|
|||
|
||||
from .models import *
|
||||
from uncloud_service.models import GenericServiceProduct
|
||||
from uncloud.models import UncloudProvider
|
||||
from uncloud.models import UncloudProvider, UncloudNetwork
|
||||
|
||||
import json
|
||||
|
||||
chocolate_product_config = {
|
||||
'features': {
|
||||
'gramm':
|
||||
{ 'min': 100,
|
||||
'max': 5000,
|
||||
'one_time_price_per_unit': 0.2,
|
||||
'recurring_price_per_unit': 0
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
chocolate_order_config = {
|
||||
'features': {
|
||||
'gramm': 500,
|
||||
}
|
||||
}
|
||||
|
||||
chocolate_one_time_price = chocolate_order_config['features']['gramm'] * chocolate_product_config['features']['gramm']['one_time_price_per_unit']
|
||||
|
||||
vm_product_config = {
|
||||
'features': {
|
||||
'cores':
|
||||
{ 'min': 1,
|
||||
'max': 48,
|
||||
'one_time_price_per_unit': 0,
|
||||
'recurring_price_per_unit': 4
|
||||
'max': 48
|
||||
},
|
||||
'ram_gb':
|
||||
{ 'min': 1,
|
||||
'max': 256,
|
||||
'one_time_price_per_unit': 0,
|
||||
'recurring_price_per_unit': 4
|
||||
'max': 256
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
vm_order_config = {
|
||||
'features': {
|
||||
'cores': 2,
|
||||
'ram_gb': 2
|
||||
}
|
||||
}
|
||||
vm_order_config = json.dumps({
|
||||
'cores': 1,
|
||||
'memory': 2,
|
||||
'storage': 100
|
||||
})
|
||||
|
||||
vm_order_downgrade_config = {
|
||||
'features': {
|
||||
|
|
@ -87,12 +63,11 @@ class ProductTestCase(TestCase):
|
|||
|
||||
RecurringPeriod.populate_db_defaults()
|
||||
self.default_recurring_period = RecurringPeriod.objects.get(name="Per 30 days")
|
||||
|
||||
|
||||
def test_create_product(self):
|
||||
"""
|
||||
Create a sample product
|
||||
"""
|
||||
|
||||
p = Product.objects.create(name="Testproduct",
|
||||
description="Only for testing",
|
||||
config=vm_product_config)
|
||||
|
|
@ -107,6 +82,8 @@ class OrderTestCase(TestCase):
|
|||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
||||
ram_unit_price=4, storage_unit_price=0.02)
|
||||
self.user = get_user_model().objects.create(
|
||||
username='random_user',
|
||||
email='jane.random@domain.tld')
|
||||
|
|
@ -135,23 +112,35 @@ class OrderTestCase(TestCase):
|
|||
Order a products with a recurringperiod that is not added to the product
|
||||
"""
|
||||
|
||||
order_config = json.dumps({
|
||||
'cores': 1,
|
||||
'memory':2,
|
||||
'storage': 100
|
||||
})
|
||||
o = Order.objects.create(owner=self.user,
|
||||
billing_address=self.ba,
|
||||
pricing_plan = self.pricing_plan,
|
||||
product=self.product,
|
||||
config=vm_order_config)
|
||||
config=order_config)
|
||||
|
||||
|
||||
def test_order_product(self):
|
||||
"""
|
||||
Order a product, ensure the order has correct price setup
|
||||
"""
|
||||
|
||||
order_config = json.dumps({
|
||||
'cores': 1,
|
||||
'memory':2,
|
||||
'storage': 100
|
||||
})
|
||||
o = Order.objects.create(owner=self.user,
|
||||
billing_address=self.ba,
|
||||
product=self.product)
|
||||
pricing_plan = self.pricing_plan,
|
||||
product=self.product,
|
||||
config=order_config)
|
||||
|
||||
self.assertEqual(o.one_time_price, 0)
|
||||
self.assertEqual(o.recurring_price, 16)
|
||||
self.assertEqual(o.recurring_price, 13.0)
|
||||
|
||||
def test_change_order(self):
|
||||
"""
|
||||
|
|
@ -159,14 +148,19 @@ class OrderTestCase(TestCase):
|
|||
- a new order is created
|
||||
- the price is correct in the new order
|
||||
"""
|
||||
order_config = json.dumps({
|
||||
'cores': 2,
|
||||
'memory':4,
|
||||
'storage': 200
|
||||
})
|
||||
order1 = Order.objects.create(owner=self.user,
|
||||
billing_address=self.ba,
|
||||
pricing_plan = self.pricing_plan,
|
||||
product=self.product,
|
||||
config=vm_order_config)
|
||||
|
||||
config=order_config)
|
||||
|
||||
self.assertEqual(order1.one_time_price, 0)
|
||||
self.assertEqual(order1.recurring_price, 16)
|
||||
self.assertEqual(order1.recurring_price, 26.0)
|
||||
|
||||
|
||||
class ModifyOrderTestCase(TestCase):
|
||||
|
|
@ -181,7 +175,18 @@ class ModifyOrderTestCase(TestCase):
|
|||
self.user = get_user_model().objects.create(
|
||||
username='random_user',
|
||||
email='jane.random@domain.tld')
|
||||
|
||||
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
||||
ram_unit_price=4, storage_unit_price=0.02)
|
||||
self.order1_config = json.dumps({
|
||||
'cores': 2,
|
||||
'memory':4,
|
||||
'storage': 200
|
||||
})
|
||||
self.order2_config = json.dumps({
|
||||
'cores': 1,
|
||||
'memory':2,
|
||||
'storage': 100
|
||||
})
|
||||
self.ba = BillingAddress.objects.create(
|
||||
owner=self.user,
|
||||
organization = 'Test org',
|
||||
|
|
@ -226,10 +231,11 @@ class ModifyOrderTestCase(TestCase):
|
|||
order1 = Order.objects.create(owner=self.user,
|
||||
billing_address=BillingAddress.get_address_for(self.user),
|
||||
product=self.product,
|
||||
config=vm_order_config,
|
||||
config=self.order1_config,
|
||||
pricing_plan=self.pricing_plan,
|
||||
starting_date=starting_date)
|
||||
|
||||
order1.update_order(vm_order_downgrade_config, starting_date=change1_date)
|
||||
order1.update_order(self.order2_config, starting_date=change1_date)
|
||||
|
||||
bills = Bill.create_next_bills_for_user(user, ending_date=bill_ending_date)
|
||||
|
||||
|
|
@ -270,24 +276,26 @@ class ModifyOrderTestCase(TestCase):
|
|||
first_order_should_end_at = starting_date + datetime.timedelta(days=30)
|
||||
change1_date = start_after(starting_date + datetime.timedelta(days=15))
|
||||
bill_ending_date = change1_date + datetime.timedelta(days=1)
|
||||
|
||||
order1 = Order.objects.create(owner=self.user,
|
||||
billing_address=BillingAddress.get_address_for(self.user),
|
||||
product=self.product,
|
||||
config=vm_order_config,
|
||||
pricing_plan=self.pricing_plan,
|
||||
config=self.order1_config,
|
||||
starting_date=starting_date)
|
||||
|
||||
order1.update_order(vm_order_downgrade_config, starting_date=change1_date)
|
||||
|
||||
bills = Bill.create_next_bills_for_user(user, ending_date=bill_ending_date)
|
||||
|
||||
bill = bills[0]
|
||||
bill_records = BillRecord.objects.filter(bill=bill)
|
||||
|
||||
self.assertEqual(len(bill_records), 2)
|
||||
|
||||
self.assertEqual(len(bill_records), 1)
|
||||
self.assertEqual(bill_records[0].starting_date, starting_date)
|
||||
self.assertEqual(bill_records[0].order.ending_date, first_order_should_end_at)
|
||||
|
||||
order1.update_order(self.order2_config, starting_date=change1_date)
|
||||
bills = Bill.create_next_bills_for_user(user, ending_date=bill_ending_date)
|
||||
bill_records = BillRecord.objects.filter(bill=bill)
|
||||
self.assertEqual(len(bill_records), 2)
|
||||
self.assertEqual(bill_records[0].order.ending_date.date(), change1_date.date())
|
||||
|
||||
|
||||
class BillTestCase(TestCase):
|
||||
|
|
@ -298,6 +306,9 @@ class BillTestCase(TestCase):
|
|||
def setUp(self):
|
||||
RecurringPeriod.populate_db_defaults()
|
||||
|
||||
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
||||
ram_unit_price=4, storage_unit_price=0.02)
|
||||
|
||||
self.user_without_address = get_user_model().objects.create(
|
||||
username='no_home_person',
|
||||
email='far.away@domain.tld')
|
||||
|
|
@ -331,12 +342,12 @@ class BillTestCase(TestCase):
|
|||
'starting_date': timezone.make_aware(datetime.datetime(2020,3,3)),
|
||||
'ending_date': timezone.make_aware(datetime.datetime(2020,4,17)),
|
||||
'price': 15,
|
||||
'description': 'One chocolate bar'
|
||||
'description': ''
|
||||
}
|
||||
|
||||
self.chocolate = Product.objects.create(name="Swiss Chocolate",
|
||||
self.product = Product.objects.create(name="Product Sample",
|
||||
description="Not only for testing, but for joy",
|
||||
config=chocolate_product_config)
|
||||
config=vm_product_config)
|
||||
|
||||
|
||||
self.vm = Product.objects.create(name="Super Fast VM",
|
||||
|
|
@ -349,7 +360,7 @@ class BillTestCase(TestCase):
|
|||
|
||||
self.onetime_recurring_period = RecurringPeriod.objects.get(name="Onetime")
|
||||
|
||||
self.chocolate.recurring_periods.add(self.onetime_recurring_period,
|
||||
self.product.recurring_periods.add(self.onetime_recurring_period,
|
||||
through_defaults= { 'is_default': True })
|
||||
|
||||
self.vm.recurring_periods.add(self.default_recurring_period,
|
||||
|
|
@ -364,15 +375,16 @@ class BillTestCase(TestCase):
|
|||
]
|
||||
|
||||
|
||||
def order_chocolate(self):
|
||||
def order_product(self):
|
||||
return Order.objects.create(
|
||||
owner=self.user,
|
||||
recurring_period=RecurringPeriod.objects.get(name="Onetime"),
|
||||
product=self.chocolate,
|
||||
product=self.product,
|
||||
billing_address=BillingAddress.get_address_for(self.user),
|
||||
starting_date=self.order_meta[1]['starting_date'],
|
||||
ending_date=self.order_meta[1]['ending_date'],
|
||||
config=chocolate_order_config)
|
||||
pricing_plan=self.pricing_plan,
|
||||
config=vm_order_config)
|
||||
|
||||
def order_vm(self, owner=None):
|
||||
|
||||
|
|
@ -383,27 +395,52 @@ class BillTestCase(TestCase):
|
|||
owner=owner,
|
||||
product=self.vm,
|
||||
config=vm_order_config,
|
||||
pricing_plan=self.pricing_plan,
|
||||
billing_address=BillingAddress.get_address_for(self.recurring_user),
|
||||
starting_date=timezone.make_aware(datetime.datetime(2020,3,3)),
|
||||
)
|
||||
|
||||
return Order.objects.create(
|
||||
def test_bill_one_time_with_recurring(self):
|
||||
"""
|
||||
Validate that if the order contains one_time_price and recurring_pricing
|
||||
One Bill records should be created
|
||||
"""
|
||||
|
||||
order = Order.objects.create(
|
||||
owner=self.user,
|
||||
recurring_period=RecurringPeriod.objects.get(name="Onetime"),
|
||||
product=self.chocolate,
|
||||
product=self.vm,
|
||||
config=vm_order_config,
|
||||
pricing_plan=self.pricing_plan,
|
||||
one_time_price = 35,
|
||||
billing_address=BillingAddress.get_address_for(self.user),
|
||||
starting_date=self.order_meta[1]['starting_date'],
|
||||
ending_date=self.order_meta[1]['ending_date'],
|
||||
config=chocolate_order_config)
|
||||
|
||||
starting_date=timezone.make_aware(datetime.datetime(2020,3,3)),
|
||||
)
|
||||
|
||||
bill = Bill.create_next_bill_for_user_address(self.user_addr)
|
||||
|
||||
self.assertEqual(order.billrecord_set.count(), 1)
|
||||
record = order.billrecord_set.first()
|
||||
self.assertEqual(record.is_recurring_record, False)
|
||||
self.assertEqual(record.price, 35)
|
||||
self.assertEqual(record.quantity, 1)
|
||||
self.assertEqual(record.sum, 35)
|
||||
#close the bill as it has been paid
|
||||
bill.close()
|
||||
bill2 = Bill.create_next_bill_for_user_address(self.user_addr)
|
||||
self.assertNotEqual(bill.id, bill2.id)
|
||||
self.assertEqual(order.billrecord_set.count(), 2)
|
||||
record = BillRecord.objects.filter(bill=bill2, order=order).first()
|
||||
self.assertEqual(record.is_recurring_record, True)
|
||||
self.assertEqual(record.price, 13)
|
||||
self.assertEqual(record.quantity, 1)
|
||||
self.assertEqual(record.sum, 13)
|
||||
|
||||
def test_bill_one_time_one_bill_record(self):
|
||||
"""
|
||||
Ensure there is only 1 bill record per order
|
||||
"""
|
||||
|
||||
order = self.order_chocolate()
|
||||
order = self.order_product()
|
||||
|
||||
bill = Bill.create_next_bill_for_user_address(self.user_addr)
|
||||
|
||||
|
|
@ -414,9 +451,14 @@ class BillTestCase(TestCase):
|
|||
Check the bill sum for a single one time order
|
||||
"""
|
||||
|
||||
order = self.order_chocolate()
|
||||
order = self.order_product()
|
||||
self.assertEqual(order.recurring_price, 13.0)
|
||||
bill = Bill.create_next_bill_for_user_address(self.user_addr)
|
||||
self.assertEqual(bill.sum, chocolate_one_time_price)
|
||||
self.assertEqual(order.billrecord_set.count(), 1)
|
||||
record = order.billrecord_set.first()
|
||||
self.assertEqual(record.price, 13)
|
||||
self.assertEqual(record.quantity, 1)
|
||||
self.assertEqual(bill.sum, 13)
|
||||
|
||||
|
||||
def test_bill_creates_record_for_recurring_order(self):
|
||||
|
|
@ -461,7 +503,7 @@ class BillingAddressTestCase(TestCase):
|
|||
Raise an error, when there is no address
|
||||
"""
|
||||
|
||||
self.assertRaises(uncloud_pay.models.BillingAddress.DoesNotExist,
|
||||
self.assertRaises(BillingAddress.DoesNotExist,
|
||||
BillingAddress.get_address_for,
|
||||
self.user)
|
||||
|
||||
|
|
@ -478,7 +520,8 @@ class VATRatesTestCase(TestCase):
|
|||
city="unknown",
|
||||
postal_code="unknown",
|
||||
active=True)
|
||||
|
||||
|
||||
UncloudNetwork.populate_db_defaults()
|
||||
UncloudProvider.populate_db_defaults()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue