Add button to update invoice

Allow the recipient on an invoice to be updated without creating a new invoice.
This allows fixing of mistakes easily, especially for when it is given to someone
else to pay and a new invoice would be confusing.
This commit is contained in:
Joel Addison 2019-10-30 09:16:55 +10:00
parent e529983759
commit f52477c9b4
4 changed files with 46 additions and 12 deletions

View file

@ -32,10 +32,15 @@
{% elif invoice.is_paid %}
{% if user.is_staff %}
<a class="btn btn-default" href="{% url "manual_payment" invoice.id %}">Apply manual payment/refund</a>
<a class="btn btn-default" href="{% url "refund" invoice.id %}">Refund by issuing credit note</a>
<a class="btn btn-primary" href="{% url "manual_payment" invoice.id %}">Apply manual payment/refund</a>
<a class="btn btn-secondary" href="{% url "refund" invoice.id %}">Refund by issuing credit note</a>
{% endif %}
{% endif %}
{% if user.is_staff %}
<a class="btn btn-info" href="{% url "attendee" invoice.user.id %}">View attendee</a>
<a class="btn btn-light" href="{% url "invoice_update" invoice.id %}">Refresh recipient</a>
{% endif %}
</div>
{% endblock %}

View file

@ -172,12 +172,7 @@ class InvoiceController(ForId, object):
issued = timezone.now()
due = max(issued, min_due_time)
# Get the invoice recipient
profile = people.AttendeeProfileBase.objects.get_subclass(
id=user.attendee.attendeeprofilebase.id,
)
recipient = profile.invoice_recipient()
recipient = cls._recipient(user)
invoice_value = sum(item.quantity * item.price for item in line_items)
invoice = commerce.Invoice.objects.create(
@ -228,6 +223,22 @@ class InvoiceController(ForId, object):
invoice.refresh_from_db()
@classmethod
def _recipient(cls, user):
''' Get the invoice recipient. '''
profile = people.AttendeeProfileBase.objects.get_subclass(
id=user.attendee.attendeeprofilebase.id,
)
recipient = profile.invoice_recipient()
return recipient
def update_recipient(self):
''' Update the recipient of the invoice based on the current
attendee data. '''
self.invoice.recipient = self._recipient(self.invoice.user)
self.invoice.save()
def can_view(self, user=None, access_code=None):
''' Returns true if the accessing user is allowed to view this invoice,
or if the given access code matches this invoice's user's access code.

View file

@ -17,6 +17,7 @@ from .views import (
invoice,
invoice_access,
invoice_mailout,
invoice_update,
manual_payment,
product_category,
refund,
@ -43,8 +44,8 @@ public = [
url(r"^invoice/([0-9]+)/([A-Z0-9]+)$", invoice, name="invoice"),
url(r"^invoice/([0-9]+)/manual_payment$",
manual_payment, name="manual_payment"),
url(r"^invoice/([0-9]+)/refund$",
refund, name="refund"),
url(r"^invoice/([0-9]+)/refund$", refund, name="refund"),
url(r"^invoice/([0-9]+)/update$", invoice_update, name="invoice_update"),
url(r"^invoice_access/([A-Z0-9]+)$", invoice_access,
name="invoice_access"),
url(r"^invoice_mailout$", invoice_mailout, name="invoice_mailout"),

View file

@ -711,7 +711,8 @@ def checkout(request, user_id=None):
current_cart = CartController.for_user(user)
if "fix_errors" in request.GET and request.GET["fix_errors"] == "true":
fix_errors = request.GET.get("fix_errors") == "true"
if fix_errors:
current_cart.fix_simple_errors()
try:
@ -719,6 +720,9 @@ def checkout(request, user_id=None):
except ValidationError as ve:
return _checkout_errors(request, ve)
if fix_errors:
current_invoice.update_recipient()
return redirect("invoice", current_invoice.invoice.id)
@ -825,6 +829,19 @@ def invoice(request, invoice_id, access_code=None):
return render(request, "registrasion/invoice.html", data)
def invoice_update(request, invoice_id):
''' Updates an invoice to have the latest recipient information. '''
current_invoice = InvoiceController.for_id_or_404(invoice_id)
if not current_invoice.can_view(user=request.user):
raise Http404()
current_invoice.update_recipient()
return redirect("invoice", current_invoice.invoice.id)
def _staff_only(user):
''' Returns true if the user is staff. '''
return user.is_staff