Cleanup code so that *most* test work again

Still need to solve the downgrade test
This commit is contained in:
Nico Schottelius 2020-11-15 15:43:11 +01:00
parent ecc9e6f734
commit 0b1c2cc168
8 changed files with 40 additions and 2254 deletions

View file

@ -236,16 +236,16 @@ VPNNetworks can be managed by all authenticated users.
** Milestones :uncloud: ** Milestones :uncloud:
*** 1.1 (cleanup 1) *** 1.1 (cleanup 1)
**** TODO Unify ValidationError, FieldError - define proper Exception **** TODO [#C] Unify ValidationError, FieldError - define proper Exception
- What do we use for model errors - What do we use for model errors
*** 1.0 (initial release) *** 1.0 (initial release)
**** TODO Initial Generic product support **** TODO [#C] Initial Generic product support
- Product - Product
***** TODO Recurring product support ***** TODO [#C] Recurring product support
****** TODO Support replacing orders for updates ****** TODO [#C] Support replacing orders for updates
****** DONE [#A] Finish split of bill creation ****** DONE [#A] Finish split of bill creation
CLOSED: [2020-09-11 Fri 23:19] CLOSED: [2020-09-11 Fri 23:19]
****** TODO Test the new functions in the Order class ****** TODO [#C] Test the new functions in the Order class
****** Define the correct order replacement logic ****** Define the correct order replacement logic
Assumption: Assumption:
- recurringperiods are 30days - recurringperiods are 30days
@ -302,13 +302,14 @@ VPNNetworks can be managed by all authenticated users.
- Total on bill: 30 CHF - Total on bill: 30 CHF
****** TODO Note: ending date not set if replaced by default (implicit!) ****** TODO [#C] Note: ending date not set if replaced by default (implicit!)
- Should the new order modify the old order on save()? - Should the new order modify the old order on save()?
****** DONE Fix totally wrong bill dates in our test case ****** DONE Fix totally wrong bill dates in our test case
CLOSED: [2020-09-09 Wed 01:00] CLOSED: [2020-09-09 Wed 01:00]
- 2020 used instead of 2019 - 2020 used instead of 2019
- Was due to existing test data ... - Was due to existing test data ...
***** TODO Bill logic is still wrong ***** DONE Bill logic is still wrong
CLOSED: [2020-11-05 Thu 18:58]
- Bill starting_date is the date of the first order - Bill starting_date is the date of the first order
- However first encountered order does not have to be the - However first encountered order does not have to be the
earliest in the bill! earliest in the bill!

View file

@ -3,6 +3,7 @@ from django.db.models import JSONField, Q
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.exceptions import FieldError
from uncloud import COUNTRIES from uncloud import COUNTRIES

View file

@ -196,11 +196,27 @@ class ReverseDNSEntry(models.Model):
name = models.CharField(max_length=253, null=False) name = models.CharField(max_length=253, null=False)
@property
def reverse_pointer(self):
return ipaddress.ip_address(self.ip_address).reverse_pointer
def implement(self):
"""
The implement function implements the change
"""
# Get all DNS entries (?) / update this DNS entry
# convert to DNS name
#
pass
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# Product.objects.filter(config__parameters__contains='reverse_dns_network') # Product.objects.filter(config__parameters__contains='reverse_dns_network')
# FIXME: check if order is still active / not replaced # FIXME: check if order is still active / not replaced
allowed = False allowed = False
product = None
for order in Order.objects.filter(config__parameters__reverse_dns_network__isnull=False, for order in Order.objects.filter(config__parameters__reverse_dns_network__isnull=False,
owner=self.owner): owner=self.owner):
@ -211,6 +227,7 @@ class ReverseDNSEntry(models.Model):
if addr in net: if addr in net:
allowed = True allowed = True
product = order.product
break break

View file

@ -9,7 +9,7 @@ from .views import *
from .models import * from .models import *
from uncloud_pay.models import BillingAddress, Order from uncloud_pay.models import BillingAddress, Order
from uncloud.models import UncloudNetwork
class UncloudNetworkTests(TestCase): class UncloudNetworkTests(TestCase):
def test_invalid_IPv4_network(self): def test_invalid_IPv4_network(self):

View file

@ -209,7 +209,7 @@ class PaymentMethod(models.Model):
pass pass
# See https://docs.djangoproject.com/en/dev/ref/models/fields/#field-choices-enum-types # See https://docs.djangoproject.com/en/dev/ref/models/fields/#field-choices-enum-types
class RecurringPeriodChoices(models.IntegerChoices): class RecurringPeriodDefaultChoices(models.IntegerChoices):
""" """
This is an old class and being superseeded by the database model below This is an old class and being superseeded by the database model below
""" """
@ -234,7 +234,7 @@ class RecurringPeriod(models.Model):
@classmethod @classmethod
def populate_db_defaults(cls): def populate_db_defaults(cls):
for (seconds, name) in RecurringPeriodChoices.choices: for (seconds, name) in RecurringPeriodDefaultChoices.choices:
obj, created = cls.objects.get_or_create(name=name, obj, created = cls.objects.get_or_create(name=name,
defaults={ 'duration_seconds': seconds }) defaults={ 'duration_seconds': seconds })
@ -470,7 +470,7 @@ class Product(models.Model):
@property @property
def recurring_orders(self): def recurring_orders(self):
return self.orders.order_by('id').exclude(recurring_period=RecurringPeriod.ONE_TIME) return self.orders.order_by('id').exclude(recurring_period=RecurringPeriod.objects.get(name="ONE_TIME"))
@property @property
def last_recurring_order(self): def last_recurring_order(self):
@ -478,7 +478,7 @@ class Product(models.Model):
@property @property
def one_time_orders(self): def one_time_orders(self):
return self.orders.order_by('id').filter(recurring_period=RecurringPeriod.ONE_TIME) return self.orders.order_by('id').filter(recurring_period=RecurringPeriod.objects.get(name="ONE_TIME"))
@property @property
def last_one_time_order(self): def last_one_time_order(self):
@ -503,13 +503,13 @@ class Product(models.Model):
billing_address=billing_address, billing_address=billing_address,
starting_date=when_to_start, starting_date=when_to_start,
price=self.one_time_price, price=self.one_time_price,
recurring_period=RecurringPeriod.ONE_TIME, recurring_period=RecurringPeriod.objects.get(name="ONE_TIME"),
description=str(self)) description=str(self))
self.orders.add(one_time_order) self.orders.add(one_time_order)
else: else:
one_time_order = None one_time_order = None
if recurring_period != RecurringPeriod.ONE_TIME: if recurring_period != RecurringPeriod.objects.get(name="ONE_TIME"):
if one_time_order: if one_time_order:
recurring_order = Order.objects.create(owner=self.owner, recurring_order = Order.objects.create(owner=self.owner,
billing_address=billing_address, billing_address=billing_address,
@ -827,7 +827,7 @@ class Order(models.Model):
@property @property
def is_recurring(self): def is_recurring(self):
return not self.recurring_period == RecurringPeriod.ONE_TIME return not self.recurring_period == RecurringPeriod.objects.get(name="ONE_TIME")
@property @property
def is_one_time(self): def is_one_time(self):
@ -857,6 +857,8 @@ class Order(models.Model):
(new_order.one_time_price, new_order.recurring_price, new_order.config) = new_order.calculate_prices_and_config() (new_order.one_time_price, new_order.recurring_price, new_order.config) = new_order.calculate_prices_and_config()
new_order.replaces = self new_order.replaces = self
new_order.save() new_order.save()

File diff suppressed because it is too large Load diff

View file

@ -1,721 +0,0 @@
from django.test import TestCase
from django.contrib.auth import get_user_model
from datetime import datetime, date, timedelta
from django.utils import timezone
from .models import *
from uncloud_service.models import GenericServiceProduct
class OrderTestCase(TestCase):
"""
The heart of ordering products
"""
def setUp(self):
self.user = get_user_model().objects.create(
username='random_user',
email='jane.random@domain.tld')
self.ba = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="somewhere else",
active=True)
def test_create_one_time_product(self):
"""
One time payment products cannot be updated - can they?
"""
p = SampleOneTimeProduct.objects.create(owner=self.user)
self.assertEqual(p.one_time_price, 5)
self.assertEqual(p.recurring_price, 0)
# class ProductTestCase(TestCase):
# """
# Test products and products <-> order interaction
# """
# def setUp(self):
# self.user = get_user_model().objects.create(
# username='random_user',
# email='jane.random@domain.tld')
# self.ba = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="somewhere else",
# active=True)
# def test_create_one_time_product(self):
# """
# One time payment products cannot be updated - can they?
# """
# p = SampleOneTimeProduct.objects.create(owner=self.user)
# self.assertEqual(p.one_time_price, 5)
# self.assertEqual(p.recurring_price, 0)
# def test_create_product_without_active_billing_address(self):
# """
# Fail to create a product without an active billing address
# """
# self.ba.active = False
# self.ba.save()
# with self.assertRaises(ValidationError):
# p = SampleOneTimeProduct.objects.create(owner=self.user)
# def test_create_product_without_billing_address(self):
# """
# Fail to create a product without a billing address
# """
# user2 = get_user_model().objects.create(
# username='random_user2',
# email='jane.randomly@domain.tld')
# with self.assertRaises(ValidationError):
# p = SampleOneTimeProduct.objects.create(owner=user2)
# def test_create_order_creates_correct_order_count(self):
# """
# Ensure creating orders from product only creates 1 order
# """
# # One order
# p = SampleOneTimeProduct.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# order_count = Order.objects.filter(owner=self.user).count()
# self.assertEqual(order_count, 1)
# # One more order
# p = SampleRecurringProduct.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# order_count = Order.objects.filter(owner=self.user).count()
# self.assertEqual(order_count, 2)
# # Should create 2 orders
# p = SampleRecurringProductOneTimeFee.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# order_count = Order.objects.filter(owner=self.user).count()
# self.assertEqual(order_count, 4)
# def test_update_recurring_order(self):
# """
# Ensure creating orders from product only creates 1 order
# """
# p = SampleRecurringProduct.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# p.create_or_update_recurring_order(timezone.make_aware(datetime.datetime(2020,3,4)))
# # FIXME: where is the assert?
class BillingAddressTestCase(TestCase):
def setUp(self):
self.user = get_user_model().objects.create(
username='random_user',
email='jane.random@domain.tld')
def test_user_no_address(self):
"""
Raise an error, when there is no address
"""
self.assertRaises(uncloud_pay.models.BillingAddress.DoesNotExist,
BillingAddress.get_address_for,
self.user)
def test_user_only_inactive_address(self):
"""
Raise an error, when there is no active address
"""
ba = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="somewhere else",
active=False)
self.assertRaises(uncloud_pay.models.BillingAddress.DoesNotExist,
BillingAddress.get_address_for,
self.user)
def test_find_active_address(self):
"""
Find the active address
"""
ba = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="unknown",
active=True)
self.assertEqual(BillingAddress.get_address_for(self.user), ba)
def test_find_right_address_with_multiple_addresses(self):
"""
Find the active address only, skip inactive
"""
ba = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="unknown",
active=True)
ba2 = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="somewhere else",
active=False)
self.assertEqual(BillingAddress.get_address_for(self.user), ba)
def test_change_addresses(self):
"""
Switch the active address
"""
ba = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="unknown",
active=True)
self.assertEqual(BillingAddress.get_address_for(self.user), ba)
ba.active=False
ba.save()
ba2 = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="somewhere else",
active=True)
self.assertEqual(BillingAddress.get_address_for(self.user), ba2)
class BillTestCase(TestCase):
def setUp(self):
self.user_without_address = get_user_model().objects.create(
username='no_home_person',
email='far.away@domain.tld')
self.user = get_user_model().objects.create(
username='jdoe',
email='john.doe@domain.tld')
self.recurring_user = get_user_model().objects.create(
username='recurrent_product_user',
email='jane.doe@domain.tld')
self.user_addr = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="unknown",
active=True)
self.recurring_user_addr = BillingAddress.objects.create(
owner=self.recurring_user,
organization = 'Test org',
street="Somewhere",
city="Else",
postal_code="unknown",
active=True)
self.order_meta = {}
self.order_meta[1] = {
'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'
}
self.one_time_order = Order.objects.create(
owner=self.user,
starting_date=self.order_meta[1]['starting_date'],
ending_date=self.order_meta[1]['ending_date'],
recurring_period=RecurringPeriod.ONE_TIME,
price=self.order_meta[1]['price'],
description=self.order_meta[1]['description'],
billing_address=BillingAddress.get_address_for(self.user))
self.recurring_order = Order.objects.create(
owner=self.recurring_user,
starting_date=timezone.make_aware(datetime.datetime(2020,3,3)),
recurring_period=RecurringPeriod.PER_30D,
price=15,
description="A pretty VM",
billing_address=BillingAddress.get_address_for(self.recurring_user)
)
# used for generating multiple bills
self.bill_dates = [
timezone.make_aware(datetime.datetime(2020,3,31)),
timezone.make_aware(datetime.datetime(2020,4,30)),
timezone.make_aware(datetime.datetime(2020,5,31)),
]
def test_bill_one_time_one_bill_record(self):
"""
Ensure there is only 1 bill record per order
"""
bill = Bill.create_next_bill_for_user_address(self.user_addr)
self.assertEqual(self.one_time_order.billrecord_set.count(), 1)
def test_bill_sum_onetime(self):
"""
Check the bill sum for a single one time order
"""
bill = Bill.create_next_bill_for_user_address(self.user_addr)
self.assertEqual(bill.sum, self.order_meta[1]['price'])
def test_bill_creates_record_for_recurring_order(self):
"""
Ensure there is only 1 bill record per order
"""
bill = Bill.create_next_bill_for_user_address(self.recurring_user_addr)
self.assertEqual(self.recurring_order.billrecord_set.count(), 1)
self.assertEqual(bill.billrecord_set.count(), 1)
def test_new_bill_after_closing(self):
"""
After closing a bill and the user has a recurring product,
the next bill run should create e new bill
"""
for ending_date in self.bill_dates:
b = Bill.create_next_bill_for_user_address(self.recurring_user_addr, ending_date)
b.close()
bill_count = Bill.objects.filter(owner=self.recurring_user).count()
self.assertEqual(len(self.bill_dates), bill_count)
def test_multi_addr_multi_bill(self):
"""
Ensure multiple bills are created if orders exist with different billing addresses
"""
username="lotsofplaces"
multi_addr_user = get_user_model().objects.create(
username=username,
email=f"{username}@example.org")
user_addr1 = BillingAddress.objects.create(
owner=multi_addr_user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="unknown",
active=True)
order1 = Order.objects.create(
owner=multi_addr_user,
starting_date=self.order_meta[1]['starting_date'],
ending_date=self.order_meta[1]['ending_date'],
recurring_period=RecurringPeriod.ONE_TIME,
price=self.order_meta[1]['price'],
description=self.order_meta[1]['description'],
billing_address=BillingAddress.get_address_for(self.user))
# Make this address inactive
user_addr1.active = False
user_addr1.save()
user_addr2 = BillingAddress.objects.create(
owner=multi_addr_user,
organization = 'Test2 org',
street="unknown2",
city="unknown2",
postal_code="unknown2",
active=True)
order2 = Order.objects.create(
owner=multi_addr_user,
starting_date=self.order_meta[1]['starting_date'],
ending_date=self.order_meta[1]['ending_date'],
recurring_period=RecurringPeriod.ONE_TIME,
price=self.order_meta[1]['price'],
description=self.order_meta[1]['description'],
billing_address=BillingAddress.get_address_for(self.user))
bills = Bill.create_next_bills_for_user(multi_addr_user)
self.assertEqual(len(bills), 2)
# TO BE IMPLEMENTED -- once orders can be marked as "done" / "inactive" / "not for billing"
# def test_skip_disabled_orders(self):
# """
# Ensure that a bill only considers "active" orders
# """
# self.assertEqual(1, 2)
class ModifyProductTestCase(TestCase):
def setUp(self):
self.user = get_user_model().objects.create(
username='random_user',
email='jane.random@domain.tld')
self.ba = BillingAddress.objects.create(
owner=self.user,
organization = 'Test org',
street="unknown",
city="unknown",
postal_code="somewhere else",
active=True)
def test_no_pro_rata_first_bill(self):
"""
The bill should NOT contain a partial amount -- this is a BILL TEST :-)
"""
price = 5
# Standard 30d recurring product
product = SampleRecurringProduct.objects.create(owner=self.user,
rc_price=price)
starting_date = timezone.make_aware(datetime.datetime(2020,3,3))
ending_date = timezone.make_aware(datetime.datetime(2020,3,31))
time_diff = (ending_date - starting_date).total_seconds()
product.create_order(starting_date)
bills = Bill.create_next_bills_for_user(self.user,
ending_date=ending_date)
# We expect 1 bill for 1 billing address and 1 time frame
self.assertEqual(len(bills), 1)
pro_rata_amount = time_diff / product.default_recurring_period.value
self.assertNotEqual(bills[0].sum, pro_rata_amount * price)
self.assertEqual(bills[0].sum, price)
def test_downgrade_product(self):
"""
Test downgrading behaviour:
We create a recurring product (recurring time: 30 days) and downgrade after 15 days.
We create the bill right AFTER the end of the first order.
Expected result:
- First bill record for 30 days
- Second bill record starting after 30 days
- Bill contains two bill records
"""
user = self.user
starting_price = 10
downgrade_price = 5
starting_date = timezone.make_aware(datetime.datetime(2019,3,3))
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)
product = SampleRecurringProduct.objects.create(owner=user, rc_price=starting_price)
product.create_order(starting_date)
product.rc_price = downgrade_price
product.save()
product.create_or_update_recurring_order(when_to_start=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(bill_records[0].starting_date, starting_date)
self.assertEqual(bill_records[0].order.ending_date, first_order_should_end_at)
# self.assertEqual(bill_records[0].ending_date, first_order_should_end_at)
# self.assertEqual(bill_records[0].quantity, 1)
# self.assertEqual(bill_records[1].quantity, 1)
# self.assertEqual(int(bill.sum), 15)
def test_upgrade_product(self):
"""
Test upgrading behaviour
"""
user = self.user
# Create product
starting_date = timezone.make_aware(datetime.datetime(2019,3,3))
starting_price = 10
product = SampleRecurringProduct.objects.create(owner=user, rc_price=starting_price)
product.create_order(starting_date)
change1_date = start_after(starting_date + datetime.timedelta(days=15))
product.rc_price = 20
product.save()
product.create_or_update_recurring_order(when_to_start=change1_date)
bill_ending_date = change1_date + datetime.timedelta(days=1)
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(bill_records[0].quantity, .5)
self.assertEqual(bill_records[0].ending_date, end_before(change1_date))
self.assertEqual(bill_records[1].quantity, 1)
self.assertEqual(bill_records[1].starting_date, change1_date)
self.assertEqual(int(bill.sum), 25)
# def test_bill_for_increasing_product(self):
# """
# Modify a product, see one pro rata entry
# """
# # Create product
# starting_date = timezone.make_aware(datetime.datetime(2019,3,3))
# starting_price = 30.5
# product = SampleRecurringProduct.objects.create(owner=self.user,
# rc_price=starting_price)
# product.create_order(starting_date)
# recurring_period = product.default_recurring_period.value
# # First change
# change1_date = timezone.make_aware(datetime.datetime(2019,4,17))
# product.rc_price = 49.5
# product.save()
# product.create_or_update_recurring_order(when_to_start=change1_date)
# # Second change
# change2_date = timezone.make_aware(datetime.datetime(2019,5,8))
# product.rc_price = 56.5
# product.save()
# product.create_or_update_recurring_order(when_to_start=change2_date)
# # Create bill one month after 2nd change
# bill_ending_date = timezone.make_aware(datetime.datetime(2019,6,30))
# bills = Bill.create_next_bills_for_user(self.user,
# ending_date=bill_ending_date)
# # only one bill in this test case
# bill = bills[0]
# expected_amount = starting_price
# d2 = starting_date + recurring_period
# duration2 = change1_date - d2
# expected_amount = 0
# # Expected bill sum & records:
# # 2019-03-03 - 2019-04-02 +30d: 30.5
# # 2019-04-02 - 2019-04-17: +15d: 15.25
# # 2019-04-17 - 2019-05-08: +21d: (21/30) * 49.5
# # 2019-05-08 - 2019-06-07: +30d: 56.5
# # 2019-06-07 - 2019-07-07: +30d: 56.5
# self.assertEqual(bills[0].sum, price)
# # expeted result:
# # 1x 5 chf bill record
# # 1x 5 chf bill record
# # 1x 10 partial bill record
# class NotABillingTC(TestCase):
# #class BillingTestCase(TestCase):
# def setUp(self):
# self.user = get_user_model().objects.create(
# username='jdoe',
# email='john.doe@domain.tld')
# self.billing_address = BillingAddress.objects.create(
# owner=self.user,
# street="unknown",
# city="unknown",
# postal_code="unknown")
# def test_basic_monthly_billing(self):
# one_time_price = 10
# recurring_price = 20
# description = "Test Product 1"
# # Three months: full, full, partial.
# # starting_date = datetime.fromisoformat('2020-03-01')
# starting_date = datetime(2020,3,1)
# ending_date = datetime(2020,5,8)
# # Create order to be billed.
# order = Order.objects.create(
# owner=self.user,
# starting_date=starting_date,
# ending_date=ending_date,
# recurring_period=RecurringPeriod.PER_30D,
# recurring_price=recurring_price,
# one_time_price=one_time_price,
# description=description,
# billing_address=self.billing_address)
# # Generate & check bill for first month: full recurring_price + setup.
# first_month_bills = order.generate_initial_bill()
# self.assertEqual(len(first_month_bills), 1)
# self.assertEqual(first_month_bills[0].amount, one_time_price + recurring_price)
# # Generate & check bill for second month: full recurring_price.
# second_month_bills = Bill.generate_for(2020, 4, self.user)
# self.assertEqual(len(second_month_bills), 1)
# self.assertEqual(second_month_bills[0].amount, recurring_price)
# # Generate & check bill for third and last month: partial recurring_price.
# third_month_bills = Bill.generate_for(2020, 5, self.user)
# self.assertEqual(len(third_month_bills), 1)
# # 31 days in May.
# self.assertEqual(float(third_month_bills[0].amount),
# round(round((7/31), AMOUNT_DECIMALS) * recurring_price, AMOUNT_DECIMALS))
# # Check that running Bill.generate_for() twice does not create duplicates.
# self.assertEqual(len(Bill.generate_for(2020, 3, self.user)), 0)
# def test_basic_yearly_billing(self):
# one_time_price = 10
# recurring_price = 150
# description = "Test Product 1"
# starting_date = datetime.fromisoformat('2020-03-31T08:05:23')
# # Create order to be billed.
# order = Order.objects.create(
# owner=self.user,
# starting_date=starting_date,
# recurring_period=RecurringPeriod.PER_365D,
# recurring_price=recurring_price,
# one_time_price=one_time_price,
# description=description,
# billing_address=self.billing_address)
# # Generate & check bill for first year: recurring_price + setup.
# first_year_bills = order.generate_initial_bill()
# self.assertEqual(len(first_year_bills), 1)
# self.assertEqual(first_year_bills[0].starting_date.date(),
# date.fromisoformat('2020-03-31'))
# self.assertEqual(first_year_bills[0].ending_date.date(),
# date.fromisoformat('2021-03-30'))
# self.assertEqual(first_year_bills[0].amount,
# recurring_price + one_time_price)
# # Generate & check bill for second year: recurring_price.
# second_year_bills = Bill.generate_for(2021, 3, self.user)
# self.assertEqual(len(second_year_bills), 1)
# self.assertEqual(second_year_bills[0].starting_date.date(),
# date.fromisoformat('2021-03-31'))
# self.assertEqual(second_year_bills[0].ending_date.date(),
# date.fromisoformat('2022-03-30'))
# self.assertEqual(second_year_bills[0].amount, recurring_price)
# # Check that running Bill.generate_for() twice does not create duplicates.
# self.assertEqual(len(Bill.generate_for(2020, 3, self.user)), 0)
# self.assertEqual(len(Bill.generate_for(2020, 4, self.user)), 0)
# self.assertEqual(len(Bill.generate_for(2020, 2, self.user)), 0)
# self.assertEqual(len(Bill.generate_for(2021, 3, self.user)), 0)
# def test_basic_hourly_billing(self):
# one_time_price = 10
# recurring_price = 1.4
# description = "Test Product 1"
# starting_date = datetime.fromisoformat('2020-03-31T08:05:23')
# ending_date = datetime.fromisoformat('2020-04-01T11:13:32')
# # Create order to be billed.
# order = Order.objects.create(
# owner=self.user,
# starting_date=starting_date,
# ending_date=ending_date,
# recurring_period=RecurringPeriod.PER_HOUR,
# recurring_price=recurring_price,
# one_time_price=one_time_price,
# description=description,
# billing_address=self.billing_address)
# # Generate & check bill for first month: recurring_price + setup.
# first_month_bills = order.generate_initial_bill()
# self.assertEqual(len(first_month_bills), 1)
# self.assertEqual(float(first_month_bills[0].amount),
# round(16 * recurring_price, AMOUNT_DECIMALS) + one_time_price)
# # Generate & check bill for first month: recurring_price.
# second_month_bills = Bill.generate_for(2020, 4, self.user)
# self.assertEqual(len(second_month_bills), 1)
# self.assertEqual(float(second_month_bills[0].amount),
# round(12 * recurring_price, AMOUNT_DECIMALS))

View file

@ -244,36 +244,6 @@ class ModifyOrderTestCase(TestCase):
# def test_no_pro_rata_first_bill(self):
# """
# The bill should NOT contain a partial amount -- this is a BILL TEST :-)
# """
# price = 5
# # Standard 30d recurring product
# product = SampleRecurringProduct.objects.create(owner=self.user,
# rc_price=price)
# starting_date = timezone.make_aware(datetime.datetime(2020,3,3))
# ending_date = timezone.make_aware(datetime.datetime(2020,3,31))
# time_diff = (ending_date - starting_date).total_seconds()
# product.create_order(starting_date)
# bills = Bill.create_next_bills_for_user(self.user,
# ending_date=ending_date)
# # We expect 1 bill for 1 billing address and 1 time frame
# self.assertEqual(len(bills), 1)
# pro_rata_amount = time_diff / product.default_recurring_period.value
# self.assertNotEqual(bills[0].sum, pro_rata_amount * price)
# self.assertEqual(bills[0].sum, price)
def test_downgrade_product(self): def test_downgrade_product(self):
""" """
Test downgrading behaviour: Test downgrading behaviour:
@ -300,7 +270,6 @@ class ModifyOrderTestCase(TestCase):
change1_date = start_after(starting_date + datetime.timedelta(days=15)) change1_date = start_after(starting_date + datetime.timedelta(days=15))
bill_ending_date = change1_date + datetime.timedelta(days=1) bill_ending_date = change1_date + datetime.timedelta(days=1)
order1 = Order.objects.create(owner=self.user, order1 = Order.objects.create(owner=self.user,
billing_address=BillingAddress.get_address_for(self.user), billing_address=BillingAddress.get_address_for(self.user),
product=self.product, product=self.product,
@ -309,12 +278,6 @@ class ModifyOrderTestCase(TestCase):
order1.update_order(vm_order_downgrade_config, starting_date=change1_date) order1.update_order(vm_order_downgrade_config, starting_date=change1_date)
# product = Product.objects.create(owner=user, rc_price=starting_price)
# product.create_order(starting_date)
# product.rc_price = downgrade_price
# product.save()
# product.create_or_update_recurring_order(when_to_start=change1_date)
bills = Bill.create_next_bills_for_user(user, ending_date=bill_ending_date) bills = Bill.create_next_bills_for_user(user, ending_date=bill_ending_date)
bill = bills[0] bill = bills[0]
@ -325,105 +288,6 @@ class ModifyOrderTestCase(TestCase):
self.assertEqual(bill_records[0].starting_date, starting_date) self.assertEqual(bill_records[0].starting_date, starting_date)
self.assertEqual(bill_records[0].order.ending_date, first_order_should_end_at) self.assertEqual(bill_records[0].order.ending_date, first_order_should_end_at)
# self.assertEqual(bill_records[0].ending_date, first_order_should_end_at)
# self.assertEqual(bill_records[0].quantity, 1)
# self.assertEqual(bill_records[1].quantity, 1)
# self.assertEqual(int(bill.sum), 15)
# def test_upgrade_product(self):
# """
# Test upgrading behaviour
# """
# user = self.user
# # Create product
# starting_date = timezone.make_aware(datetime.datetime(2019,3,3))
# starting_price = 10
# product = SampleRecurringProduct.objects.create(owner=user, rc_price=starting_price)
# product.create_order(starting_date)
# change1_date = start_after(starting_date + datetime.timedelta(days=15))
# product.rc_price = 20
# product.save()
# product.create_or_update_recurring_order(when_to_start=change1_date)
# bill_ending_date = change1_date + datetime.timedelta(days=1)
# 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(bill_records[0].quantity, .5)
# self.assertEqual(bill_records[0].ending_date, end_before(change1_date))
# self.assertEqual(bill_records[1].quantity, 1)
# self.assertEqual(bill_records[1].starting_date, change1_date)
# self.assertEqual(int(bill.sum), 25)
# def test_bill_for_increasing_product(self):
# """
# Modify a product, see one pro rata entry
# """
# # Create product
# starting_date = timezone.make_aware(datetime.datetime(2019,3,3))
# starting_price = 30.5
# product = SampleRecurringProduct.objects.create(owner=self.user,
# rc_price=starting_price)
# product.create_order(starting_date)
# recurring_period = product.default_recurring_period.value
# # First change
# change1_date = timezone.make_aware(datetime.datetime(2019,4,17))
# product.rc_price = 49.5
# product.save()
# product.create_or_update_recurring_order(when_to_start=change1_date)
# # Second change
# change2_date = timezone.make_aware(datetime.datetime(2019,5,8))
# product.rc_price = 56.5
# product.save()
# product.create_or_update_recurring_order(when_to_start=change2_date)
# # Create bill one month after 2nd change
# bill_ending_date = timezone.make_aware(datetime.datetime(2019,6,30))
# bills = Bill.create_next_bills_for_user(self.user,
# ending_date=bill_ending_date)
# # only one bill in this test case
# bill = bills[0]
# expected_amount = starting_price
# d2 = starting_date + recurring_period
# duration2 = change1_date - d2
# expected_amount = 0
# # Expected bill sum & records:
# # 2019-03-03 - 2019-04-02 +30d: 30.5
# # 2019-04-02 - 2019-04-17: +15d: 15.25
# # 2019-04-17 - 2019-05-08: +21d: (21/30) * 49.5
# # 2019-05-08 - 2019-06-07: +30d: 56.5
# # 2019-06-07 - 2019-07-07: +30d: 56.5
# self.assertEqual(bills[0].sum, price)
# # expeted result:
# # 1x 5 chf bill record
# # 1x 5 chf bill record
# # 1x 10 partial bill record
class BillTestCase(TestCase): class BillTestCase(TestCase):
""" """
@ -431,6 +295,8 @@ class BillTestCase(TestCase):
""" """
def setUp(self): def setUp(self):
RecurringPeriod.populate_db_defaults()
self.user_without_address = get_user_model().objects.create( self.user_without_address = get_user_model().objects.create(
username='no_home_person', username='no_home_person',
email='far.away@domain.tld') email='far.away@domain.tld')
@ -500,7 +366,7 @@ class BillTestCase(TestCase):
def order_chocolate(self): def order_chocolate(self):
return Order.objects.create( return Order.objects.create(
owner=self.user, owner=self.user,
recurring_period=RecurringPeriod.ONE_TIME, recurring_period=RecurringPeriod.objects.get(name="Onetime"),
product=self.chocolate, product=self.chocolate,
billing_address=BillingAddress.get_address_for(self.user), billing_address=BillingAddress.get_address_for(self.user),
starting_date=self.order_meta[1]['starting_date'], starting_date=self.order_meta[1]['starting_date'],
@ -522,7 +388,7 @@ class BillTestCase(TestCase):
return Order.objects.create( return Order.objects.create(
owner=self.user, owner=self.user,
recurring_period=RecurringPeriod.ONE_TIME, recurring_period=RecurringPeriod.objects.get(name="Onetime"),
product=self.chocolate, product=self.chocolate,
billing_address=BillingAddress.get_address_for(self.user), billing_address=BillingAddress.get_address_for(self.user),
starting_date=self.order_meta[1]['starting_date'], starting_date=self.order_meta[1]['starting_date'],
@ -580,167 +446,6 @@ class BillTestCase(TestCase):
self.assertEqual(len(self.bill_dates), bill_count) self.assertEqual(len(self.bill_dates), bill_count)
# def test_multi_addr_multi_bill(self):
# """
# Ensure multiple bills are created if orders exist with different billing addresses
# """
# username="lotsofplaces"
# multi_addr_user = get_user_model().objects.create(
# username=username,
# email=f"{username}@example.org")
# user_addr1 = BillingAddress.objects.create(
# owner=multi_addr_user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="unknown",
# active=True)
# order1 = Order.objects.create(
# owner=multi_addr_user,
# recurring_period=RecurringPeriod.ONE_TIME,
# product=self.chocolate,
# 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)
# order1 = Order.objects.create(
# owner=multi_addr_user,
# starting_date=self.order_meta[1]['starting_date'],
# ending_date=self.order_meta[1]['ending_date'],
# recurring_period=RecurringPeriod.ONE_TIME,
# price=self.order_meta[1]['price'],
# description=self.order_meta[1]['description'],
# billing_address=BillingAddress.get_address_for(self.user))
# # Make this address inactive
# user_addr1.active = False
# user_addr1.save()
# user_addr2 = BillingAddress.objects.create(
# owner=multi_addr_user,
# organization = 'Test2 org',
# street="unknown2",
# city="unknown2",
# postal_code="unknown2",
# active=True)
# order2 = Order.objects.create(
# owner=multi_addr_user,
# starting_date=self.order_meta[1]['starting_date'],
# ending_date=self.order_meta[1]['ending_date'],
# recurring_period=RecurringPeriod.ONE_TIME,
# price=self.order_meta[1]['price'],
# description=self.order_meta[1]['description'],
# billing_address=BillingAddress.get_address_for(self.user))
# bills = Bill.create_next_bills_for_user(multi_addr_user)
# self.assertEqual(len(bills), 2)
# # TO BE IMPLEMENTED -- once orders can be marked as "done" / "inactive" / "not for billing"
# # def test_skip_disabled_orders(self):
# # """
# # Ensure that a bill only considers "active" orders
# # """
# # self.assertEqual(1, 2)
# class ProductTestCase(TestCase):
# """
# Test products and products <-> order interaction
# """
# def setUp(self):
# self.user = get_user_model().objects.create(
# username='random_user',
# email='jane.random@domain.tld')
# self.ba = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="somewhere else",
# active=True)
# def test_create_one_time_product(self):
# """
# One time payment products cannot be updated - can they?
# """
# p = SampleOneTimeProduct.objects.create(owner=self.user)
# self.assertEqual(p.one_time_price, 5)
# self.assertEqual(p.recurring_price, 0)
# def test_create_product_without_active_billing_address(self):
# """
# Fail to create a product without an active billing address
# """
# self.ba.active = False
# self.ba.save()
# with self.assertRaises(ValidationError):
# p = SampleOneTimeProduct.objects.create(owner=self.user)
# def test_create_product_without_billing_address(self):
# """
# Fail to create a product without a billing address
# """
# user2 = get_user_model().objects.create(
# username='random_user2',
# email='jane.randomly@domain.tld')
# with self.assertRaises(ValidationError):
# p = SampleOneTimeProduct.objects.create(owner=user2)
# def test_create_order_creates_correct_order_count(self):
# """
# Ensure creating orders from product only creates 1 order
# """
# # One order
# p = SampleOneTimeProduct.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# order_count = Order.objects.filter(owner=self.user).count()
# self.assertEqual(order_count, 1)
# # One more order
# p = SampleRecurringProduct.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# order_count = Order.objects.filter(owner=self.user).count()
# self.assertEqual(order_count, 2)
# # Should create 2 orders
# p = SampleRecurringProductOneTimeFee.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# order_count = Order.objects.filter(owner=self.user).count()
# self.assertEqual(order_count, 4)
# def test_update_recurring_order(self):
# """
# Ensure creating orders from product only creates 1 order
# """
# p = SampleRecurringProduct.objects.create(owner=self.user)
# p.create_order(timezone.make_aware(datetime.datetime(2020,3,3)))
# p.create_or_update_recurring_order(timezone.make_aware(datetime.datetime(2020,3,4)))
# # FIXME: where is the assert?
class BillingAddressTestCase(TestCase): class BillingAddressTestCase(TestCase):
@ -758,219 +463,3 @@ class BillingAddressTestCase(TestCase):
self.assertRaises(uncloud_pay.models.BillingAddress.DoesNotExist, self.assertRaises(uncloud_pay.models.BillingAddress.DoesNotExist,
BillingAddress.get_address_for, BillingAddress.get_address_for,
self.user) self.user)
# def test_user_only_inactive_address(self):
# """
# Raise an error, when there is no active address
# """
# ba = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="somewhere else",
# active=False)
# self.assertRaises(uncloud_pay.models.BillingAddress.DoesNotExist,
# BillingAddress.get_address_for,
# self.user)
# def test_find_active_address(self):
# """
# Find the active address
# """
# ba = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="unknown",
# active=True)
# self.assertEqual(BillingAddress.get_address_for(self.user), ba)
# def test_find_right_address_with_multiple_addresses(self):
# """
# Find the active address only, skip inactive
# """
# ba = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="unknown",
# active=True)
# ba2 = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="somewhere else",
# active=False)
# self.assertEqual(BillingAddress.get_address_for(self.user), ba)
# def test_change_addresses(self):
# """
# Switch the active address
# """
# ba = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="unknown",
# active=True)
# self.assertEqual(BillingAddress.get_address_for(self.user), ba)
# ba.active=False
# ba.save()
# ba2 = BillingAddress.objects.create(
# owner=self.user,
# organization = 'Test org',
# street="unknown",
# city="unknown",
# postal_code="somewhere else",
# active=True)
# self.assertEqual(BillingAddress.get_address_for(self.user), ba2)
# class NotABillingTC(TestCase):
# #class BillingTestCase(TestCase):
# def setUp(self):
# self.user = get_user_model().objects.create(
# username='jdoe',
# email='john.doe@domain.tld')
# self.billing_address = BillingAddress.objects.create(
# owner=self.user,
# street="unknown",
# city="unknown",
# postal_code="unknown")
# def test_basic_monthly_billing(self):
# one_time_price = 10
# recurring_price = 20
# description = "Test Product 1"
# # Three months: full, full, partial.
# # starting_date = datetime.fromisoformat('2020-03-01')
# starting_date = datetime(2020,3,1)
# ending_date = datetime(2020,5,8)
# # Create order to be billed.
# order = Order.objects.create(
# owner=self.user,
# starting_date=starting_date,
# ending_date=ending_date,
# recurring_period=RecurringPeriod.PER_30D,
# recurring_price=recurring_price,
# one_time_price=one_time_price,
# description=description,
# billing_address=self.billing_address)
# # Generate & check bill for first month: full recurring_price + setup.
# first_month_bills = order.generate_initial_bill()
# self.assertEqual(len(first_month_bills), 1)
# self.assertEqual(first_month_bills[0].amount, one_time_price + recurring_price)
# # Generate & check bill for second month: full recurring_price.
# second_month_bills = Bill.generate_for(2020, 4, self.user)
# self.assertEqual(len(second_month_bills), 1)
# self.assertEqual(second_month_bills[0].amount, recurring_price)
# # Generate & check bill for third and last month: partial recurring_price.
# third_month_bills = Bill.generate_for(2020, 5, self.user)
# self.assertEqual(len(third_month_bills), 1)
# # 31 days in May.
# self.assertEqual(float(third_month_bills[0].amount),
# round(round((7/31), AMOUNT_DECIMALS) * recurring_price, AMOUNT_DECIMALS))
# # Check that running Bill.generate_for() twice does not create duplicates.
# self.assertEqual(len(Bill.generate_for(2020, 3, self.user)), 0)
# def test_basic_yearly_billing(self):
# one_time_price = 10
# recurring_price = 150
# description = "Test Product 1"
# starting_date = datetime.fromisoformat('2020-03-31T08:05:23')
# # Create order to be billed.
# order = Order.objects.create(
# owner=self.user,
# starting_date=starting_date,
# recurring_period=RecurringPeriod.PER_365D,
# recurring_price=recurring_price,
# one_time_price=one_time_price,
# description=description,
# billing_address=self.billing_address)
# # Generate & check bill for first year: recurring_price + setup.
# first_year_bills = order.generate_initial_bill()
# self.assertEqual(len(first_year_bills), 1)
# self.assertEqual(first_year_bills[0].starting_date.date(),
# date.fromisoformat('2020-03-31'))
# self.assertEqual(first_year_bills[0].ending_date.date(),
# date.fromisoformat('2021-03-30'))
# self.assertEqual(first_year_bills[0].amount,
# recurring_price + one_time_price)
# # Generate & check bill for second year: recurring_price.
# second_year_bills = Bill.generate_for(2021, 3, self.user)
# self.assertEqual(len(second_year_bills), 1)
# self.assertEqual(second_year_bills[0].starting_date.date(),
# date.fromisoformat('2021-03-31'))
# self.assertEqual(second_year_bills[0].ending_date.date(),
# date.fromisoformat('2022-03-30'))
# self.assertEqual(second_year_bills[0].amount, recurring_price)
# # Check that running Bill.generate_for() twice does not create duplicates.
# self.assertEqual(len(Bill.generate_for(2020, 3, self.user)), 0)
# self.assertEqual(len(Bill.generate_for(2020, 4, self.user)), 0)
# self.assertEqual(len(Bill.generate_for(2020, 2, self.user)), 0)
# self.assertEqual(len(Bill.generate_for(2021, 3, self.user)), 0)
# def test_basic_hourly_billing(self):
# one_time_price = 10
# recurring_price = 1.4
# description = "Test Product 1"
# starting_date = datetime.fromisoformat('2020-03-31T08:05:23')
# ending_date = datetime.fromisoformat('2020-04-01T11:13:32')
# # Create order to be billed.
# order = Order.objects.create(
# owner=self.user,
# starting_date=starting_date,
# ending_date=ending_date,
# recurring_period=RecurringPeriod.PER_HOUR,
# recurring_price=recurring_price,
# one_time_price=one_time_price,
# description=description,
# billing_address=self.billing_address)
# # Generate & check bill for first month: recurring_price + setup.
# first_month_bills = order.generate_initial_bill()
# self.assertEqual(len(first_month_bills), 1)
# self.assertEqual(float(first_month_bills[0].amount),
# round(16 * recurring_price, AMOUNT_DECIMALS) + one_time_price)
# # Generate & check bill for first month: recurring_price.
# second_month_bills = Bill.generate_for(2020, 4, self.user)
# self.assertEqual(len(second_month_bills), 1)
# self.assertEqual(float(second_month_bills[0].amount),
# round(12 * recurring_price, AMOUNT_DECIMALS))