My site is going to have a credit system that basically works a lot like a credit card. Each user has an unlimited credit limit, but at the end of each week, they have to pay it off. For example, a user might make several purchases between March 1st and 7th, and then at the end of March 7th, they would be emailed an invoice that lists all their purchases during the week and a total that is due by the 14th. If they don't pay it off, their account is simply deactivated until they do. I'm just trying to wrap my head around how to implement this.
I have a list of all their purchases, that's not a problem, but I'm just trying to figure out what to do with it. On the end of the 7th day, I could set up a cronjob to generate an invoice, which would basically have an id, and due date, and then I would need another many-to-many table to link all the purchases to the invoice. Then when a user adds money to their account, I guess it's applied against their current outstanding invoice? And what if they don't pay off their invoice by the time a new invoice rolls around, so now they have 2 outstanding ones, how do I know which to apply it against? Or do I make the cronjob check for any previous outstanding invoices, cancel them, and add a new item to the new invoice as "balance forward (+interest)"? How would you apply the money against an invoice? Would each payment have to be linked to an invoice, or could I just deposit it to their account credit, and then somehow figure out whats been paid and what hasn't? What if they pay in advance, before their invoice has been generated? Do I deduct it from their credit from the invoice upon generation, or at the end of the week when its due? There are so many ways to do this...
Can anyone describe what approach they would take?
If anyone's interested, my Invoice model presently looks as follows (in Django). The InvoiceItems are linked to actual "products" by a reverse ID (the FK is on the product, not the invoice item to allow different item types (different tables)), but I think I'm going to switch that around.
class Invoice(models.Model):
user = models.ForeignKey(User, related_name='invoices')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
closed_date = models.DateTimeField(null=True, blank=True)
due_date = models.DateTimeField(default=_next_weekday())
payment_date = models.DateTimeField(null=True, blank=True) # date the invoice was fully paid
total_payments = CurrencyField(default=0)
interest_charges = CurrencyField(default=0)
@property
def days_overdue(self):
dt = self.due_date - datetime.date.today()
return dt.days if dt.days > 0 else 0
@property
def item_total(self):
return self.items.filter(amount__gt=0).aggregate(t=Sum('amount'))['t'] or Decimal('0.00')
@property
def daily_interest(self):
return _round((self.item_total - self.total_payments) * settings.INTEREST_RATE/Decimal('365.242199'))
@property
def subtotal(self):
return self.item_total + self.interest_charges
@property
def tax(self):
return _round(self.subtotal * settings.GST)
@property
def total(self):
return self.subtotal + self.tax
@property
def balance_owing(self):
return self.total - self.total_payments
@property
def is_paid(self):
return self.payment_date != None
@property
def is_open(self):
return self.closed_date == None
@property
def is_overdue(self):
return not self.is_paid and self.due_date < datetime.date.today()
class InvoiceItem(models.Model):
invoice = models.ForeignKey(Invoice, related_name='items')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
description = models.CharField(max_length=200)
trans_date = models.DateTimeField(verbose_name='transaction date')
amount = CurrencyField()
I have a crontab set up to run at midnight every night to add interest charges to all overdue items, and invoices are mailed out every Friday morning.