Don't flag vouchers/discounts as used until multireg completed
authorMagnus Hagander <magnus@hagander.net>
Wed, 7 Mar 2018 18:35:45 +0000 (13:35 -0500)
committerMagnus Hagander <magnus@hagander.net>
Wed, 7 Mar 2018 18:35:45 +0000 (13:35 -0500)
If the invoice details are not filled in, we generate an error in the
form. But at the time we had already flagged the voucher/code as used,
and thus the next create would now fail saying the code has already been
used.

Fix this by setting a savepoint at the beginning and roll back to it in
the failure case.

postgresqleu/confreg/views.py

index f57b2bb7db3da6893c09ccbb9bf54ef6366352a6..40b283db861e02eb44de71493e75664e54c2013b 100644 (file)
@@ -479,6 +479,8 @@ def multireg_newinvoice(request, confname):
                return HttpResponseRedirect('../')
 
        finalize = (request.method == 'POST' and request.POST['submit'] == 'Create')
+       if finalize:
+               savepoint = transaction.savepoint()
 
        # Almost like a bulk invoice, but we know the registrations were
     # created so they exist.
@@ -510,6 +512,7 @@ def multireg_newinvoice(request, confname):
                form = MultiRegInvoiceForm(data=request.POST)
                if totalwithvat != Decimal(request.POST['totalwithvat']):
                        errors.append('Total amount has changed, likely due to a registration being concurrently changed. Please try again.')
+                       # Error set, so will fall through into the path that rolls back
 
                if form.is_valid() and not errors:
                        if totalwithvat == 0:
@@ -527,6 +530,10 @@ def multireg_newinvoice(request, confname):
 
                                return HttpResponseRedirect("../b{0}/".format(bp.id))
 
+               # If we flagged discount codes etc as used, but came down her in the error path,
+           # make sure we roll back the change.
+               transaction.savepoint_rollback(savepoint)
+
                # Add the errors to the form, so they're actually visible.
                for e in errors:
                        form.add_error(None, e)