Adding logic to order to find out whether its closed

This commit is contained in:
Nico Schottelius 2020-09-03 16:38:51 +02:00
parent 1c7d81762d
commit f7274fe967

View file

@ -290,6 +290,22 @@ class Order(models.Model):
""" """
Order are assumed IMMUTABLE and used as SOURCE OF TRUST for generating Order are assumed IMMUTABLE and used as SOURCE OF TRUST for generating
bills. Do **NOT** mutate then! bills. Do **NOT** mutate then!
An one time order is "closed" (does not need to be billed anymore)
if it has one bill record. Having more than one is a programming
error.
A recurring order is closed if it has been replaced
(replaces__isnull=False) AND the ending_date is set AND it was
billed the last time it needed to be billed (how to check the last
item?)
BOTH are closed, if they are ended/closed AND have been fully
charged.
Fully charged == fully billed: sum_of_order_usage == sum_of_bill_records
""" """
owner = models.ForeignKey(get_user_model(), owner = models.ForeignKey(get_user_model(),
@ -365,6 +381,34 @@ class Order(models.Model):
return sum([ br.quantity for br in self.bill_records.all() ]) return sum([ br.quantity for br in self.bill_records.all() ])
@property
def count_used(self, when=None):
"""
How many times this order was billed so far.
This logic is mainly thought to be for recurring bills, but also works for one time bills
"""
if self.is_one_time:
return 1
if not when:
when = timezone.now()
# Cannot be used after it ended
if self.ending_date and when > self.ending_date:
when = self.ending_date
return (when - self.starting_date) / self.default_recurring_period
@property
def fully_billed(self, when=None):
"""
Returns true if this order does not need any further billing
ever. In other words: is this order "closed"?
"""
if self.count_billed ==
@property @property
def is_recurring(self): def is_recurring(self):
return not self.recurring_period == RecurringPeriod.ONE_TIME return not self.recurring_period == RecurringPeriod.ONE_TIME
@ -375,10 +419,9 @@ class Order(models.Model):
def replace_with(self, new_order): def replace_with(self, new_order):
new_order.replaces = self new_order.replaces = self
self.ending_date = new_order.starting_date - datetime.timedelta(seconds=1) self.ending_date = end_before(new_order.starting_date)
self.save() self.save()
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.ending_date and self.ending_date < self.starting_date: if self.ending_date and self.ending_date < self.starting_date:
raise ValidationError("End date cannot be before starting date") raise ValidationError("End date cannot be before starting date")
@ -445,6 +488,28 @@ class Bill(models.Model):
for owner in get_user_model().objects.all(): for owner in get_user_model().objects.all():
cls.create_next_bills_for_user(owner) cls.create_next_bills_for_user(owner)
@classmethod
def create_next_bill_for_user_address(cls,
owner,
billing_address,
ending_date=None):
"""
Check the existing orders of the billing address
and generate a bill if there is at least one active order
"""
all_orders = Order.objects.filter(owner=owner,
billing_address=billing_address).order_by('id')
# a bill. If there
# for order in all_orders:
# if order.is_one_time:
# cls.create_one_time_record
# pass
@classmethod @classmethod
def create_next_bills_for_user(cls, owner, ending_date=None): def create_next_bills_for_user(cls, owner, ending_date=None):
""" """
@ -534,8 +599,6 @@ class Bill(models.Model):
def get_bill_record_ending_date(order, bill): def get_bill_record_ending_date(order, bill):
""" """
Determine the ending date of the billing record Determine the ending date of the billing record
""" """
# If the order is quit, charge the final amount (?) # If the order is quit, charge the final amount (?)
@ -550,7 +613,7 @@ class Bill(models.Model):
return this_ending_date return this_ending_date
@classmethod @classmethod
def create_next_bill_for_user_address(cls, def create_next_bill_for_user_address_old(cls,
owner, owner,
billing_address, billing_address,
ending_date=None): ending_date=None):