Phase in admin, remove uuid from bills

This commit is contained in:
Nico Schottelius 2020-06-21 13:46:54 +02:00
parent 662845128f
commit 8decfe1b16
6 changed files with 246 additions and 117 deletions

View file

@ -86,4 +86,5 @@ urlpatterns = [
description="uncloud API",
version="1.0.0"
), name='openapi-schema'),
path('admin/', admin.site.urls),
]

View file

@ -1,3 +1,12 @@
from django.contrib import admin
# Register your models here.
from uncloud_pay.models import Bill, Order, BillRecord, BillingAddress
class BillAdmin(admin.ModelAdmin):
pass
admin.site.register(Bill, BillAdmin)
admin.site.register(Order)
admin.site.register(BillRecord)
admin.site.register(BillingAddress)

View file

@ -0,0 +1,55 @@
# Generated by Django 3.0.6 on 2020-06-21 11:10
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0016_auto_20200523_2138'),
]
operations = [
migrations.CreateModel(
name='BillRecord',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('usage_count', models.IntegerField(default=1)),
('creation_date', models.DateTimeField(auto_now_add=True)),
('starting_date', models.DateTimeField()),
('ending_date', models.DateTimeField()),
('bill', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='uncloud_pay.Bill')),
],
),
migrations.RemoveField(
model_name='ordertimothee',
name='bill',
),
migrations.RemoveField(
model_name='ordertimothee',
name='billing_address',
),
migrations.RemoveField(
model_name='ordertimothee',
name='owner',
),
migrations.RemoveField(
model_name='order',
name='bill',
),
migrations.RemoveField(
model_name='order',
name='one_time_price',
),
migrations.RemoveField(
model_name='order',
name='recurring_price',
),
migrations.DeleteModel(
name='BillNico',
),
migrations.DeleteModel(
name='OrderTimothee',
),
]

View file

@ -0,0 +1,25 @@
# Generated by Django 3.0.6 on 2020-06-21 11:40
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0017_auto_20200621_1110'),
]
operations = [
migrations.AddField(
model_name='bill',
name='bill_records',
field=models.ManyToManyField(through='uncloud_pay.BillRecord', to='uncloud_pay.Order'),
),
migrations.AddField(
model_name='billrecord',
name='order',
field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, to='uncloud_pay.Order'),
preserve_default=False,
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 3.0.6 on 2020-06-21 11:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0018_auto_20200621_1140'),
]
operations = [
migrations.RemoveField(
model_name='bill',
name='uuid',
),
migrations.AddField(
model_name='bill',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
preserve_default=False,
),
]

View file

@ -223,11 +223,14 @@ class BillingAddress(models.Model):
return addresses[0]
def __str__(self):
return "{}, {}, {} {}, {}".format(
return "{} - {}, {}, {} {}, {}".format(
self.owner,
self.name, self.street, self.postal_code, self.city,
self.country)
# Populated with the import-vat-numbers django command.
###
# VAT
class VATRate(models.Model):
start_date = models.DateField(blank=True, null=True)
stop_date = models.DateField(blank=True, null=True)
@ -250,115 +253,6 @@ class VATRate(models.Model):
logger.debug("Did not find VAT rate for %s, returning 0" % country_code)
return 0
class BillRecord(models.Model):
"""
Entry of a bill, dynamically generated from an order.
"""
bill = models.ForeignKey(Bill, on_delete=models.CASCADE)
# How many times the order has been used in this record
usage_count = models.IntegerField(default=1)
# The timeframe the bill record is for can (and probably often will) differ
# from the bill time
creation_date = models.DateTimeField(auto_now_add=True)
starting_date = models.DateTimeField()
ending_date = models.DateTimeField()
class Bill(models.Model):
""" FIXME:
Bill needs to be unique in the triple (owner, year, month)
"""
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
owner = models.ForeignKey(get_user_model(),
on_delete=models.CASCADE)
creation_date = models.DateTimeField(auto_now_add=True)
starting_date = models.DateTimeField()
ending_date = models.DateTimeField()
due_date = models.DateField()
valid = models.BooleanField(default=True)
# billing address and vat rate is the same for the whole bill
# @property
# def vat_rate(self):
# return Decimal(VATRate.get_for_country(self.bill.billing_address.country))
@classmethod
def create_all_bills(cls):
for owner in get_user_model().objects.all():
# mintime = time of first order
# maxtime = time of last order
# iterate month based through it
cls.assign_orders_to_bill(owner, year, month)
pass
def assign_orders_to_bill(self, owner, year, month):
"""
Generate a bill for the specific month of a user.
First handle all one time orders
FIXME:
- limit this to active users in the future! (2020-05-23)
"""
"""
Find all one time orders that have a starting date that falls into this month
recurring_period=RecurringPeriod.ONE_TIME,
Can we do this even for recurring / all of them
"""
# FIXME: add something to check whether the order should be billed at all - i.e. a marker that
# disables searching -> optimization for later
# Create the initial bill record
# FIXME: maybe limit not even to starting/ending date, but to empty_bill record -- to be fixed in the future
# for order in Order.objects.filter(Q(starting_date__gte=self.starting_date),
# Q(starting_date__lte=self.ending_date),
# FIXME below: only check for active orders
# Ensure all orders of that owner have at least one bill record
for order in Order.objects.filter(owner=owner,
bill_records=None):
bill_record = BillRecord.objects.create(bill=self,
usage_count=1,
starting_date=order.starting_date,
ending_date=order.starting_date + timedelta(seconds=order.recurring_period))
# For each recurring order get the usage and bill it
for order in Order.objects.filter(~Q(recurring_period=RecurringPeriod.ONE_TIME),
Q(starting_date__lt=self.starting_date),
owner=owner):
if order.recurring_period > 0: # avoid div/0 - these are one time payments
# How much time will have passed by the end of the billing cycle
td = self.ending_date - order.starting_date
# How MANY times it will have been used by then
used_times = ceil(td / timedelta(seconds=order.recurring_period))
billed_times = len(order.bills)
# How many times it WAS billed -- can also be inferred from the bills that link to it!
if used_times > billed_times:
billing_times = used_times - billed_times
# ALSO REGISTER THE TIME PERIOD!
pass
###
# Orders.
@ -382,9 +276,9 @@ class Order(models.Model):
ending_date = models.DateTimeField(blank=True,
null=True)
bill_records = models.ManyToManyField(BillRecord,
editable=False,
blank=True)
# bill_records = models.ManyToManyField(BillRecord,
# editable=False,
# blank=True)
@property
def count_billed(self):
@ -512,6 +406,127 @@ class Order(models.Model):
self.recurring_price)
class Bill(models.Model):
""" FIXME:
Bill needs to be unique in the triple (owner, year, month)
"""
# uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
owner = models.ForeignKey(get_user_model(),
on_delete=models.CASCADE)
creation_date = models.DateTimeField(auto_now_add=True)
starting_date = models.DateTimeField()
ending_date = models.DateTimeField()
due_date = models.DateField()
valid = models.BooleanField(default=True)
# Mapping to BillRecords
# https://stackoverflow.com/questions/4443190/djangos-manytomany-relationship-with-additional-fields
bill_records = models.ManyToManyField(Order, through="BillRecord")
# billing address and vat rate is the same for the whole bill
# @property
# def vat_rate(self):
# return Decimal(VATRate.get_for_country(self.bill.billing_address.country))
def __str__(self):
return f"uc-{self.id}"
@classmethod
def create_all_bills(cls):
for owner in get_user_model().objects.all():
# mintime = time of first order
# maxtime = time of last order
# iterate month based through it
cls.assign_orders_to_bill(owner, year, month)
pass
def assign_orders_to_bill(self, owner, year, month):
"""
Generate a bill for the specific month of a user.
First handle all one time orders
FIXME:
- limit this to active users in the future! (2020-05-23)
"""
"""
Find all one time orders that have a starting date that falls into this month
recurring_period=RecurringPeriod.ONE_TIME,
Can we do this even for recurring / all of them
"""
# FIXME: add something to check whether the order should be billed at all - i.e. a marker that
# disables searching -> optimization for later
# Create the initial bill record
# FIXME: maybe limit not even to starting/ending date, but to empty_bill record -- to be fixed in the future
# for order in Order.objects.filter(Q(starting_date__gte=self.starting_date),
# Q(starting_date__lte=self.ending_date),
# FIXME below: only check for active orders
# Ensure all orders of that owner have at least one bill record
for order in Order.objects.filter(owner=owner,
bill_records=None):
bill_record = BillRecord.objects.create(bill=self,
usage_count=1,
starting_date=order.starting_date,
ending_date=order.starting_date + timedelta(seconds=order.recurring_period))
# For each recurring order get the usage and bill it
for order in Order.objects.filter(~Q(recurring_period=RecurringPeriod.ONE_TIME),
Q(starting_date__lt=self.starting_date),
owner=owner):
if order.recurring_period > 0: # avoid div/0 - these are one time payments
# How much time will have passed by the end of the billing cycle
td = self.ending_date - order.starting_date
# How MANY times it will have been used by then
used_times = ceil(td / timedelta(seconds=order.recurring_period))
billed_times = len(order.bills)
# How many times it WAS billed -- can also be inferred from the bills that link to it!
if used_times > billed_times:
billing_times = used_times - billed_times
# ALSO REGISTER THE TIME PERIOD!
pass
class BillRecord(models.Model):
"""
Entry of a bill, dynamically generated from an order.
"""
bill = models.ForeignKey(Bill, on_delete=models.CASCADE)
order = models.ForeignKey(Order, on_delete=models.CASCADE)
# How many times the order has been used in this record
usage_count = models.IntegerField(default=1)
# The timeframe the bill record is for can (and probably often will) differ
# from the bill time
creation_date = models.DateTimeField(auto_now_add=True)
starting_date = models.DateTimeField()
ending_date = models.DateTimeField()
def __str__(self):
return f"{order.owner}"
class OrderRecord(models.Model):
"""
@ -523,6 +538,7 @@ class OrderRecord(models.Model):
"""
order = models.ForeignKey(Order, on_delete=models.CASCADE)
one_time_price = models.DecimalField(default=0.0,
max_digits=AMOUNT_MAX_DIGITS,
decimal_places=AMOUNT_DECIMALS,