commit
						31d057c750
					
				
					 4 changed files with 78 additions and 0 deletions
				
			
		|  | @ -1,3 +1,5 @@ | ||||||
|  | import datetime | ||||||
|  | 
 | ||||||
| from django.db import transaction | from django.db import transaction | ||||||
| 
 | 
 | ||||||
| from registrasion.models import commerce | from registrasion.models import commerce | ||||||
|  | @ -53,3 +55,27 @@ class CreditNoteController(ForId, object): | ||||||
|         inv.update_status() |         inv.update_status() | ||||||
| 
 | 
 | ||||||
|     # TODO: Add administration fee generator. |     # TODO: Add administration fee generator. | ||||||
|  |     @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. | ||||||
|  |         ''' | ||||||
|  | 
 | ||||||
|  |         from invoice import InvoiceController  # Circular imports bleh. | ||||||
|  | 
 | ||||||
|  |         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) | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ from registrasion.models import commerce | ||||||
| from registrasion.models import inventory | from registrasion.models import inventory | ||||||
| 
 | 
 | ||||||
| from django import forms | from django import forms | ||||||
|  | from django.core.exceptions import ValidationError | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class ApplyCreditNoteForm(forms.Form): | class ApplyCreditNoteForm(forms.Form): | ||||||
|  | @ -31,6 +32,14 @@ class ApplyCreditNoteForm(forms.Form): | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class CancellationFeeForm(forms.Form): | ||||||
|  | 
 | ||||||
|  |     percentage = forms.DecimalField( | ||||||
|  |         required=True, | ||||||
|  |         min_value=0, | ||||||
|  |         max_value=100, | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
| class ManualCreditNoteRefundForm(forms.ModelForm): | class ManualCreditNoteRefundForm(forms.ModelForm): | ||||||
| 
 | 
 | ||||||
|     class Meta: |     class Meta: | ||||||
|  |  | ||||||
|  | @ -440,3 +440,28 @@ class CreditNoteTestCase(TestHelperMixin, RegistrationCartTestCase): | ||||||
|             # Generate invoice that should be automatically paid |             # Generate invoice that should be automatically paid | ||||||
|             invoice2 = self._manual_invoice(1) |             invoice2 = self._manual_invoice(1) | ||||||
|             self.assertTrue(invoice2.invoice.is_paid) |             self.assertTrue(invoice2.invoice.is_paid) | ||||||
|  | 
 | ||||||
|  |     def test_cancellation_fee_is_applied(self): | ||||||
|  | 
 | ||||||
|  |         invoice1 = self._manual_invoice(1) | ||||||
|  |         invoice1.pay("Pay", invoice1.invoice.value) | ||||||
|  |         invoice1.refund() | ||||||
|  | 
 | ||||||
|  |         percentage = 15 | ||||||
|  | 
 | ||||||
|  |         cn = self._credit_note_for_invoice(invoice1.invoice) | ||||||
|  |         canc = cn.cancellation_fee(15) | ||||||
|  | 
 | ||||||
|  |         # Cancellation fee exceeds the amount for the invoice. | ||||||
|  |         self.assertTrue(canc.invoice.is_paid) | ||||||
|  | 
 | ||||||
|  |         # Cancellation fee is equal to 15% of credit note's value | ||||||
|  |         self.assertEqual( | ||||||
|  |             canc.invoice.value, | ||||||
|  |             cn.credit_note.value * percentage / 100 | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     def test_cancellation_fee_is_applied_when_another_invoice_is_unpaid(self): | ||||||
|  | 
 | ||||||
|  |         extra_invoice = self._manual_invoice(23) | ||||||
|  |         self.test_cancellation_fee_is_applied() | ||||||
|  |  | ||||||
|  | @ -765,6 +765,9 @@ def credit_note(request, note_id, access_code=None): | ||||||
|                                          # to an invoice. |                                          # to an invoice. | ||||||
|                     "refund_form": form, # A form for applying a *manual* |                     "refund_form": form, # A form for applying a *manual* | ||||||
|                                          # refund of the credit note. |                                          # refund of the credit note. | ||||||
|  |                     "cancellation_fee_form" : form, # A form for generating an | ||||||
|  |                                                     # invoice with a | ||||||
|  |                                                     # cancellation fee | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|     ''' |     ''' | ||||||
|  | @ -783,6 +786,11 @@ def credit_note(request, note_id, access_code=None): | ||||||
|         prefix="refund_note" |         prefix="refund_note" | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  |     cancellation_fee_form = forms.CancellationFeeForm( | ||||||
|  |         request.POST or None, | ||||||
|  |         prefix="cancellation_fee" | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|     if request.POST and apply_form.is_valid(): |     if request.POST and apply_form.is_valid(): | ||||||
|         inv_id = apply_form.cleaned_data["invoice"] |         inv_id = apply_form.cleaned_data["invoice"] | ||||||
|         invoice = commerce.Invoice.objects.get(pk=inv_id) |         invoice = commerce.Invoice.objects.get(pk=inv_id) | ||||||
|  | @ -805,10 +813,20 @@ def credit_note(request, note_id, access_code=None): | ||||||
|             prefix="refund_note", |             prefix="refund_note", | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|  |     elif request.POST and cancellation_fee_form.is_valid(): | ||||||
|  |         percentage = cancellation_fee_form.cleaned_data["percentage"] | ||||||
|  |         invoice = current_note.cancellation_fee(percentage) | ||||||
|  |         messages.success( | ||||||
|  |             request, | ||||||
|  |             "Generated cancellation fee for credit note %d." % note_id, | ||||||
|  |         ) | ||||||
|  |         return redirect("invoice", invoice.invoice.id) | ||||||
|  | 
 | ||||||
|     data = { |     data = { | ||||||
|         "credit_note": current_note.credit_note, |         "credit_note": current_note.credit_note, | ||||||
|         "apply_form": apply_form, |         "apply_form": apply_form, | ||||||
|         "refund_form": refund_form, |         "refund_form": refund_form, | ||||||
|  |         "cancellation_fee_form": cancellation_fee_form, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return render(request, "registrasion/credit_note.html", data) |     return render(request, "registrasion/credit_note.html", data) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Christopher Neugebauer
						Christopher Neugebauer