From f7274fe967f7d1976b7bec3fc2adb2af8efd9edb Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Thu, 3 Sep 2020 16:38:51 +0200 Subject: [PATCH] Adding logic to order to find out whether its closed --- uncloud_pay/models.py | 73 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/uncloud_pay/models.py b/uncloud_pay/models.py index e8e7ac2..d1cf6a3 100644 --- a/uncloud_pay/models.py +++ b/uncloud_pay/models.py @@ -290,6 +290,22 @@ class Order(models.Model): """ Order are assumed IMMUTABLE and used as SOURCE OF TRUST for generating 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(), @@ -365,6 +381,34 @@ class Order(models.Model): 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 def is_recurring(self): return not self.recurring_period == RecurringPeriod.ONE_TIME @@ -375,10 +419,9 @@ class Order(models.Model): def replace_with(self, new_order): 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() - def save(self, *args, **kwargs): if self.ending_date and self.ending_date < self.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(): 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 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): """ Determine the ending date of the billing record - - """ # If the order is quit, charge the final amount (?) @@ -550,7 +613,7 @@ class Bill(models.Model): return this_ending_date @classmethod - def create_next_bill_for_user_address(cls, + def create_next_bill_for_user_address_old(cls, owner, billing_address, ending_date=None):