first bill generation works
Signed-off-by: Nico Schottelius <nico@nico-notebook.schottelius.org>
This commit is contained in:
parent
fd39526350
commit
d7c0c40926
6 changed files with 136 additions and 65 deletions
|
|
@ -382,9 +382,7 @@ class Bill(models.Model):
|
|||
starting_date = models.DateTimeField(default=start_of_this_month)
|
||||
ending_date = models.DateTimeField()
|
||||
due_date = models.DateField(default=default_payment_delay)
|
||||
|
||||
# what is valid for? should this be "final"?
|
||||
valid = models.BooleanField(default=True)
|
||||
is_final = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
|
|
@ -409,29 +407,36 @@ class Bill(models.Model):
|
|||
all_orders = Order.objects.filter(owner=owner).order_by('id')
|
||||
first_order = all_orders.first()
|
||||
|
||||
bill = None
|
||||
ending_date = None
|
||||
|
||||
# Calculate the start date
|
||||
# Get date & bill from previous bill
|
||||
if last_bill:
|
||||
# TODO: check that last bill is finished/closed, if not continue using it
|
||||
starting_date = last_bill.end_date + datetime.timedelta(seconds=1)
|
||||
if not last_bill.is_final:
|
||||
bill = last_bill
|
||||
starting_date = last_bill.starting_date
|
||||
ending_date = bill.ending_date
|
||||
else:
|
||||
starting_date = last_bill.end_date + datetime.timedelta(seconds=1)
|
||||
else:
|
||||
if first_order:
|
||||
starting_date = first_order.starting_date
|
||||
else:
|
||||
starting_date = timezone.now()
|
||||
|
||||
ending_date = end_of_month(starting_date)
|
||||
|
||||
# FIXME above: maybe even use different date / active / open bill
|
||||
bill, created = cls.objects.get_or_create(
|
||||
owner=owner,
|
||||
starting_date=starting_date,
|
||||
ending_date=ending_date)
|
||||
if not ending_date:
|
||||
ending_date = end_of_month(starting_date)
|
||||
|
||||
# create new bill, if previous is closed/does not exist
|
||||
if not bill:
|
||||
|
||||
bill = cls.objects.create(
|
||||
owner=owner,
|
||||
starting_date=starting_date,
|
||||
ending_date=ending_date)
|
||||
|
||||
for order in all_orders:
|
||||
# check if order needs to be billed
|
||||
# check if order has previous billing record
|
||||
|
||||
if order.is_one_time:
|
||||
if order.billrecord_set.count() == 0:
|
||||
br = BillRecord.objects.create(bill=bill,
|
||||
|
|
@ -447,6 +452,10 @@ class Bill(models.Model):
|
|||
starting_date=starting_date,
|
||||
ending_date=ending_date)
|
||||
|
||||
# Filtering ideas:
|
||||
# If order is replaced, it should not be added anymore if it has been billed "last time"
|
||||
# If order has ended and finally charged, do not charge anymore
|
||||
|
||||
return bill
|
||||
|
||||
@classmethod
|
||||
|
|
@ -546,7 +555,7 @@ class BillRecord(models.Model):
|
|||
|
||||
@property
|
||||
def sum(self):
|
||||
return self.order.price * self.quantity
|
||||
return self.order.price * Decimal(self.quantity)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.bill}: {self.quantity} x {self.order}"
|
||||
|
|
@ -575,34 +584,54 @@ class Product(UncloudModel):
|
|||
# Default period for all products
|
||||
default_recurring_period = RecurringPeriod.PER_30D
|
||||
|
||||
def create_order_at(self, when_to_start, *args, **kwargs):
|
||||
def create_order_at(self, when_to_start=None, recurring_period=None):
|
||||
billing_address = BillingAddress.get_address_for(self.owner)
|
||||
|
||||
order = Order.objects.create(owner=self.owner,
|
||||
billing_address=billing_address,
|
||||
starting_date=when_to_start,
|
||||
one_time_price=self.one_time_price,
|
||||
recurring_period=self.default_recurring_period,
|
||||
recurring_price=self.recurring_price,
|
||||
description=str(self))
|
||||
if not billing_address:
|
||||
raise ValidationError("Cannot order without a billing address")
|
||||
|
||||
def create_or_update_order(self, when_to_start=None):
|
||||
if not when_to_start:
|
||||
when_to_start = timezone.now()
|
||||
|
||||
if not recurring_period:
|
||||
recurring_period = self.default_recurring_period
|
||||
|
||||
one_time_order = None
|
||||
|
||||
if self.one_time_price > 0:
|
||||
|
||||
one_time_order = Order.objects.create(owner=self.owner,
|
||||
billing_address=billing_address,
|
||||
starting_date=when_to_start,
|
||||
price=self.one_time_price,
|
||||
recurring_period=RecurringPeriod.ONE_TIME,
|
||||
description=str(self))
|
||||
|
||||
|
||||
if recurring_period != RecurringPeriod.ONE_TIME:
|
||||
if one_time_order:
|
||||
recurring_order = Order.objects.create(owner=self.owner,
|
||||
billing_address=billing_address,
|
||||
starting_date=when_to_start,
|
||||
price=self.recurring_price,
|
||||
recurring_period=recurring_period,
|
||||
depends_on=one_time_order,
|
||||
description=str(self))
|
||||
else:
|
||||
recurring_order = Order.objects.create(owner=self.owner,
|
||||
billing_address=billing_address,
|
||||
starting_date=when_to_start,
|
||||
price=self.recurring_price,
|
||||
recurring_period=recurring_period,
|
||||
description=str(self))
|
||||
|
||||
|
||||
def create_or_update_order(self, when_to_start=None, recurring_period=None):
|
||||
if not when_to_start:
|
||||
when_to_start = timezone.now()
|
||||
|
||||
if not self.order:
|
||||
billing_address = BillingAddress.get_address_for(self.owner)
|
||||
|
||||
if not billing_address:
|
||||
raise ValidationError("Cannot order without a billing address")
|
||||
|
||||
self.order = Order.objects.create(owner=self.owner,
|
||||
billing_address=billing_address,
|
||||
starting_date=when_to_start,
|
||||
one_time_price=self.one_time_price,
|
||||
recurring_period=self.default_recurring_period,
|
||||
recurring_price=self.recurring_price,
|
||||
description=str(self))
|
||||
self.create_order_at(when_to_start, recurring_period)
|
||||
|
||||
else:
|
||||
previous_order = self.order
|
||||
|
|
@ -611,9 +640,8 @@ class Product(UncloudModel):
|
|||
new_order = Order.objects.create(owner=self.owner,
|
||||
billing_address=self.order.billing_address,
|
||||
starting_date=when_to_start,
|
||||
one_time_price=self.one_time_price,
|
||||
recurring_period=self.default_recurring_period,
|
||||
recurring_price=self.recurring_price,
|
||||
price=self.recurring_price,
|
||||
recurring_period=recurring_period,
|
||||
description=str(self),
|
||||
replaces=self.order)
|
||||
|
||||
|
|
@ -641,6 +669,14 @@ class Product(UncloudModel):
|
|||
"""
|
||||
return 0
|
||||
|
||||
|
||||
@property
|
||||
def is_recurring(self):
|
||||
return self.recurring_price > 0
|
||||
|
||||
# on is_one_time as this should be has_one_time which is the same as > 0 again...
|
||||
|
||||
|
||||
@property
|
||||
def billing_address(self):
|
||||
return self.order.billing_address
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue