Add initial generate-bills and charge-negative-balance uncloud-pay

commands
This commit is contained in:
fnux 2020-02-28 08:59:32 +01:00
commit 059791e2f2
10 changed files with 275 additions and 12 deletions

View file

@ -0,0 +1,12 @@
from functools import reduce
from .models import Bill, Payment
def sum_amounts(entries):
return reduce(lambda acc, entry: acc + entry.amount, entries, 0)
def get_balance_for(user):
bills = sum_amounts(Bill.objects.filter(owner=user))
payments = sum_amounts(Payment.objects.filter(owner=user))
return payments - bills

View file

@ -0,0 +1,23 @@
from django.core.management.base import BaseCommand
from uncloud_auth.models import User
from uncloud_pay.models import Order, Bill
from uncloud_pay.helpers import get_balance_for
from datetime import timedelta
from django.utils import timezone
class Command(BaseCommand):
help = 'Generate bills and charge customers if necessary.'
def add_arguments(self, parser):
pass
def handle(self, *args, **options):
users = User.objects.all()
print("Processing {} users.".format(users.count()))
for user in users:
balance = get_balance_for(user)
if balance < 0:
print("User {} has negative balance ({}), charging.".format(user.username, balance))
# TODO: charge
print("=> Done.")

View file

@ -0,0 +1,48 @@
from django.core.management.base import BaseCommand
from uncloud_auth.models import User
from uncloud_pay.models import Order, Bill
from datetime import timedelta
from django.utils import timezone
class Command(BaseCommand):
help = 'Generate bills and charge customers if necessary.'
def add_arguments(self, parser):
pass
# TODO: check for existing bills
def handle(self, *args, **options):
customers = User.objects.all()
print("Processing {} users.".format(customers.count()))
for customer in customers:
orders = Order.objects.filter(owner=customer)
# Pay all non-billed usage untill now.
bill_starting_date = timezone.now()
bill_ending_date = timezone.now()
billed_orders = []
for order in orders:
print(order)
if True: # FIXME
billed_orders.append(order)
# Update starting date if need be.
if order.starting_date < bill_starting_date:
bill_starting_date = order.starting_date
if len(billed_orders) > 0:
bill = Bill(owner=customer,
starting_date=bill_starting_date,
ending_date=bill_starting_date,
due_date=timezone.now() + timedelta(days=10))
bill.save()
for order in billed_orders:
print(order)
order.bill.add(bill)
print("Created bill {} for user {}".format(bill.uuid, customer.username))
print("=> Done.")

View file

@ -0,0 +1,42 @@
# Generated by Django 3.0.3 on 2020-02-28 07:37
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0004_auto_20200227_1532'),
]
operations = [
migrations.RemoveField(
model_name='bill',
name='id',
),
migrations.RemoveField(
model_name='bill',
name='paid',
),
migrations.AddField(
model_name='bill',
name='uuid',
field=models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False),
),
migrations.AlterField(
model_name='bill',
name='creation_date',
field=models.DateTimeField(auto_now_add=True),
),
migrations.AlterField(
model_name='order',
name='creation_date',
field=models.DateTimeField(auto_now_add=True),
),
migrations.AlterField(
model_name='order',
name='starting_date',
field=models.DateTimeField(auto_now_add=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-02-28 07:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0005_auto_20200228_0737'),
]
operations = [
migrations.AlterField(
model_name='order',
name='bill',
field=models.ManyToManyField(blank=True, editable=False, to='uncloud_pay.Bill'),
),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 3.0.3 on 2020-02-28 07:44
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0006_auto_20200228_0741'),
]
operations = [
migrations.RemoveField(
model_name='order',
name='bill',
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-02-28 07:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uncloud_pay', '0007_remove_order_bill'),
]
operations = [
migrations.AddField(
model_name='order',
name='bill',
field=models.ManyToManyField(blank=True, editable=False, to='uncloud_pay.Bill'),
),
]

View file

@ -19,21 +19,26 @@ class RecurringPeriod(models.TextChoices):
PER_SECOND = 'SECOND', _('Per Second')
class Bill(models.Model):
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()
creation_date = models.DateTimeField(auto_now_add=True)
starting_date = models.DateTimeField()
ending_date = models.DateTimeField()
due_date = models.DateField()
paid = models.BooleanField(default=False)
valid = models.BooleanField(default=True)
@property
def amount(self):
# iterate over all related orders
return 20
orders = Order.objects.filter(bill=self)
amount = 0
for order in orders:
amount += order.recurring_price
return amount
class Order(models.Model):
@ -49,8 +54,7 @@ class Order(models.Model):
bill = models.ManyToManyField(Bill,
editable=False,
blank=True,
null=True)
blank=True)
recurring_price = models.FloatField(editable=False)

View file

@ -1,6 +1,7 @@
from django.contrib.auth import get_user_model
from rest_framework import serializers
from .models import *
from .helpers import get_balance_for
from functools import reduce
from uncloud_vm.serializers import VMProductSerializer
@ -10,7 +11,7 @@ class BillSerializer(serializers.ModelSerializer):
class Meta:
model = Bill
fields = ['owner', 'amount', 'due_date', 'creation_date',
'starting_date', 'ending_date', 'paid']
'starting_date', 'ending_date']
class PaymentSerializer(serializers.ModelSerializer):
class Meta:
@ -41,8 +42,4 @@ class UserSerializer(serializers.ModelSerializer):
return reduce(lambda acc, entry: acc + entry.amount, entries, 0)
def get_balance(self, user):
bills = self.__sum_balance(Bill.objects.filter(owner=user))
payments = self.__sum_balance(Payment.objects.filter(owner=user))
balance = payments - bills
return balance
return get_balance_for(user)