forked from CGM_Public/pretix_original
Fix #1255 -- Approvals of free orders after last date of payments
This commit is contained in:
@@ -606,7 +606,7 @@ class Order(LockModel, LoggedModel):
|
|||||||
), tz)
|
), tz)
|
||||||
return term_last
|
return term_last
|
||||||
|
|
||||||
def _can_be_paid(self, count_waitinglist=True) -> Union[bool, str]:
|
def _can_be_paid(self, count_waitinglist=True, ignore_date=False) -> Union[bool, str]:
|
||||||
error_messages = {
|
error_messages = {
|
||||||
'late_lastdate': _("The payment can not be accepted as the last date of payments configured in the "
|
'late_lastdate': _("The payment can not be accepted as the last date of payments configured in the "
|
||||||
"payment settings is over."),
|
"payment settings is over."),
|
||||||
@@ -617,13 +617,13 @@ class Order(LockModel, LoggedModel):
|
|||||||
if self.require_approval:
|
if self.require_approval:
|
||||||
return error_messages['require_approval']
|
return error_messages['require_approval']
|
||||||
term_last = self.payment_term_last
|
term_last = self.payment_term_last
|
||||||
if term_last:
|
if term_last and not ignore_date:
|
||||||
if now() > term_last:
|
if now() > term_last:
|
||||||
return error_messages['late_lastdate']
|
return error_messages['late_lastdate']
|
||||||
|
|
||||||
if self.status == self.STATUS_PENDING:
|
if self.status == self.STATUS_PENDING:
|
||||||
return True
|
return True
|
||||||
if not self.event.settings.get('payment_term_accept_late'):
|
if not self.event.settings.get('payment_term_accept_late') and not ignore_date:
|
||||||
return error_messages['late']
|
return error_messages['late']
|
||||||
|
|
||||||
return self._is_still_available(count_waitinglist=count_waitinglist)
|
return self._is_still_available(count_waitinglist=count_waitinglist)
|
||||||
@@ -1137,9 +1137,9 @@ class OrderPayment(models.Model):
|
|||||||
"""
|
"""
|
||||||
return self.order.event.get_payment_providers().get(self.provider)
|
return self.order.event.get_payment_providers().get(self.provider)
|
||||||
|
|
||||||
def _mark_paid(self, force, count_waitinglist, user, auth, overpaid=False):
|
def _mark_paid(self, force, count_waitinglist, user, auth, ignore_date=False, overpaid=False):
|
||||||
from pretix.base.signals import order_paid
|
from pretix.base.signals import order_paid
|
||||||
can_be_paid = self.order._can_be_paid(count_waitinglist=count_waitinglist)
|
can_be_paid = self.order._can_be_paid(count_waitinglist=count_waitinglist, ignore_date=ignore_date)
|
||||||
if not force and can_be_paid is not True:
|
if not force and can_be_paid is not True:
|
||||||
self.order.log_action('pretix.event.order.quotaexceeded', {
|
self.order.log_action('pretix.event.order.quotaexceeded', {
|
||||||
'message': can_be_paid
|
'message': can_be_paid
|
||||||
@@ -1159,7 +1159,7 @@ class OrderPayment(models.Model):
|
|||||||
self.order.log_action('pretix.event.order.overpaid', {}, user=user, auth=auth)
|
self.order.log_action('pretix.event.order.overpaid', {}, user=user, auth=auth)
|
||||||
order_paid.send(self.order.event, order=self.order)
|
order_paid.send(self.order.event, order=self.order)
|
||||||
|
|
||||||
def confirm(self, count_waitinglist=True, send_mail=True, force=False, user=None, auth=None, mail_text='', lock=True):
|
def confirm(self, count_waitinglist=True, send_mail=True, force=False, user=None, auth=None, mail_text='', ignore_date=False, lock=True):
|
||||||
"""
|
"""
|
||||||
Marks the payment as complete. If possible, this also marks the order as paid if no further
|
Marks the payment as complete. If possible, this also marks the order as paid if no further
|
||||||
payment is required
|
payment is required
|
||||||
@@ -1169,6 +1169,7 @@ class OrderPayment(models.Model):
|
|||||||
:type count_waitinglist: boolean
|
:type count_waitinglist: boolean
|
||||||
:param force: Whether this payment should be marked as paid even if no remaining
|
:param force: Whether this payment should be marked as paid even if no remaining
|
||||||
quota is available (default: ``False``).
|
quota is available (default: ``False``).
|
||||||
|
:param ignore_date: Whether this order should be marked as paid even when the last date of payments is over.
|
||||||
:type force: boolean
|
:type force: boolean
|
||||||
:param send_mail: Whether an email should be sent to the user about this event (default: ``True``).
|
:param send_mail: Whether an email should be sent to the user about this event (default: ``True``).
|
||||||
:type send_mail: boolean
|
:type send_mail: boolean
|
||||||
@@ -1222,10 +1223,12 @@ class OrderPayment(models.Model):
|
|||||||
# Performance optimization. In this case, there's really no reason to lock everything and an atomic
|
# Performance optimization. In this case, there's really no reason to lock everything and an atomic
|
||||||
# database transaction is more than enough.
|
# database transaction is more than enough.
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
self._mark_paid(force, count_waitinglist, user, auth, overpaid=payment_sum - refund_sum > self.order.total)
|
self._mark_paid(force, count_waitinglist, user, auth, overpaid=payment_sum - refund_sum > self.order.total,
|
||||||
|
ignore_date=ignore_date)
|
||||||
else:
|
else:
|
||||||
with self.order.event.lock():
|
with self.order.event.lock():
|
||||||
self._mark_paid(force, count_waitinglist, user, auth, overpaid=payment_sum - refund_sum > self.order.total)
|
self._mark_paid(force, count_waitinglist, user, auth, overpaid=payment_sum - refund_sum > self.order.total,
|
||||||
|
ignore_date=ignore_date)
|
||||||
|
|
||||||
invoice = None
|
invoice = None
|
||||||
if invoice_qualified(self.order):
|
if invoice_qualified(self.order):
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ def mark_order_expired(order, user=None, auth=None):
|
|||||||
return order
|
return order
|
||||||
|
|
||||||
|
|
||||||
def approve_order(order, user=None, send_mail: bool=True, auth=None):
|
def approve_order(order, user=None, send_mail: bool=True, auth=None, force=False):
|
||||||
"""
|
"""
|
||||||
Mark this order as approved
|
Mark this order as approved
|
||||||
:param order: The order to change
|
:param order: The order to change
|
||||||
@@ -185,7 +185,7 @@ def approve_order(order, user=None, send_mail: bool=True, auth=None):
|
|||||||
fee=None
|
fee=None
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
p.confirm(send_mail=False, count_waitinglist=False, user=user, auth=auth)
|
p.confirm(send_mail=False, count_waitinglist=False, user=user, auth=auth, ignore_date=True, force=force)
|
||||||
except Quota.QuotaExceededException:
|
except Quota.QuotaExceededException:
|
||||||
raise OrderError(error_messages['unavailable'])
|
raise OrderError(error_messages['unavailable'])
|
||||||
|
|
||||||
|
|||||||
@@ -268,6 +268,26 @@ def test_approve_free(event):
|
|||||||
assert 'confirmed' in djmail.outbox[0].subject
|
assert 'confirmed' in djmail.outbox[0].subject
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_approve_free_after_last_payment_date(event):
|
||||||
|
event.settings.payment_term_last = (now() - timedelta(days=1)).date().isoformat()
|
||||||
|
djmail.outbox = []
|
||||||
|
event.settings.invoice_generate = 'True'
|
||||||
|
o1 = Order.objects.create(
|
||||||
|
code='FOO', event=event, email='dummy@dummy.test',
|
||||||
|
status=Order.STATUS_PENDING,
|
||||||
|
datetime=now(), expires=now() - timedelta(days=10),
|
||||||
|
total=0, require_approval=True
|
||||||
|
)
|
||||||
|
approve_order(o1)
|
||||||
|
o1.refresh_from_db()
|
||||||
|
assert o1.status == Order.STATUS_PAID
|
||||||
|
assert not o1.require_approval
|
||||||
|
assert o1.invoices.count() == 0
|
||||||
|
assert len(djmail.outbox) == 1
|
||||||
|
assert 'confirmed' in djmail.outbox[0].subject
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_deny(event):
|
def test_deny(event):
|
||||||
djmail.outbox = []
|
djmail.outbox = []
|
||||||
|
|||||||
Reference in New Issue
Block a user