2016-09-15 02:15:40 +00:00
|
|
|
import datetime
|
|
|
|
|
2016-04-10 04:41:43 +00:00
|
|
|
from django.db import transaction
|
|
|
|
|
2016-04-22 05:06:24 +00:00
|
|
|
from registrasion.models import commerce
|
2016-04-10 04:41:43 +00:00
|
|
|
|
2017-04-17 12:55:48 +00:00
|
|
|
from registrasion.controllers.for_id import ForId
|
2016-04-10 04:41:43 +00:00
|
|
|
|
2016-04-24 21:13:37 +00:00
|
|
|
|
|
|
|
class CreditNoteController(ForId, object):
|
|
|
|
|
|
|
|
__MODEL__ = commerce.CreditNote
|
2016-04-10 04:41:43 +00:00
|
|
|
|
|
|
|
def __init__(self, credit_note):
|
|
|
|
self.credit_note = credit_note
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def generate_from_invoice(cls, invoice, value):
|
|
|
|
''' Generates a credit note of the specified value and pays it against
|
|
|
|
the given invoice. You need to call InvoiceController.update_status()
|
|
|
|
to set the status correctly, if appropriate. '''
|
|
|
|
|
2016-04-22 05:06:24 +00:00
|
|
|
credit_note = commerce.CreditNote.objects.create(
|
2016-04-10 04:41:43 +00:00
|
|
|
invoice=invoice,
|
|
|
|
amount=0-value, # Credit notes start off as a payment against inv.
|
|
|
|
reference="ONE MOMENT",
|
|
|
|
)
|
|
|
|
credit_note.reference = "Generated credit note %d" % credit_note.id
|
|
|
|
credit_note.save()
|
|
|
|
|
|
|
|
return cls(credit_note)
|
|
|
|
|
|
|
|
@transaction.atomic
|
|
|
|
def apply_to_invoice(self, invoice):
|
|
|
|
''' Applies the total value of this credit note to the specified
|
|
|
|
invoice. If this credit note overpays the invoice, a new credit note
|
|
|
|
containing the residual value will be created.
|
|
|
|
|
|
|
|
Raises ValidationError if the given invoice is not allowed to be
|
|
|
|
paid.
|
|
|
|
'''
|
|
|
|
|
2017-04-22 08:39:07 +00:00
|
|
|
# Circular Import
|
|
|
|
from registrasion.controllers.invoice import InvoiceController
|
2016-04-10 04:41:43 +00:00
|
|
|
inv = InvoiceController(invoice)
|
|
|
|
inv.validate_allowed_to_pay()
|
|
|
|
|
|
|
|
# Apply payment to invoice
|
2016-04-22 05:06:24 +00:00
|
|
|
commerce.CreditNoteApplication.objects.create(
|
2016-04-10 04:41:43 +00:00
|
|
|
parent=self.credit_note,
|
|
|
|
invoice=invoice,
|
|
|
|
amount=self.credit_note.value,
|
|
|
|
reference="Applied credit note #%d" % self.credit_note.id,
|
|
|
|
)
|
|
|
|
|
|
|
|
inv.update_status()
|
|
|
|
|
|
|
|
# TODO: Add administration fee generator.
|
2016-09-15 02:15:40 +00:00
|
|
|
@transaction.atomic
|
|
|
|
def cancellation_fee(self, percentage):
|
|
|
|
''' Generates an invoice with a cancellation fee, and applies
|
|
|
|
credit to the invoice.
|
|
|
|
|
|
|
|
percentage (Decimal): The percentage of the credit note to turn into
|
|
|
|
a cancellation fee. Must be 0 <= percentage <= 100.
|
|
|
|
'''
|
|
|
|
|
2017-04-22 08:39:07 +00:00
|
|
|
# Circular Import
|
|
|
|
from registrasion.controllers.invoice import InvoiceController
|
2016-09-15 02:15:40 +00:00
|
|
|
|
|
|
|
assert(percentage >= 0 and percentage <= 100)
|
|
|
|
|
|
|
|
cancellation_fee = self.credit_note.value * percentage / 100
|
|
|
|
due = datetime.timedelta(days=1)
|
|
|
|
item = [("Cancellation fee", cancellation_fee)]
|
|
|
|
invoice = InvoiceController.manual_invoice(
|
|
|
|
self.credit_note.invoice.user, due, item
|
|
|
|
)
|
|
|
|
|
|
|
|
if not invoice.is_paid:
|
|
|
|
self.apply_to_invoice(invoice)
|
|
|
|
|
|
|
|
return InvoiceController(invoice)
|