Skip to content

Commit

Permalink
Delete payments when Payment.NONE in pizzas
Browse files Browse the repository at this point in the history
  • Loading branch information
se-bastiaan committed Mar 21, 2020
1 parent 047e1df commit cf8f52a
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 77 deletions.
1 change: 0 additions & 1 deletion website/events/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from events import emails
from events.exceptions import RegistrationError
from events.models import Registration, RegistrationInformationField, Event
from payments.exceptions import PaymentError
from payments.models import Payment
from payments.services import create_payment, delete_payment
from utils.snippets import datetime_to_lectureyear
Expand Down
4 changes: 4 additions & 0 deletions website/payments/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ def create_payment(
raise PaymentError(_("This user does not have Thalia Pay enabled"))

if payable.payment is not None:
payable.payment.amount = payable.payment_amount
payable.payment.notes = payable.payment_notes
payable.payment.topic = payable.payment_topic
payable.payment.paid_by = payable.payment_payer
payable.payment.type = pay_type
payable.payment.save()
else:
Expand Down
4 changes: 2 additions & 2 deletions website/payments/tests/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ def test_create_payment(self):
self.assertEqual(p.paid_by, self.member)
self.assertEqual(p.processed_by, self.member)
self.assertEqual(p.type, Payment.CASH)
with self.subTest("Does not create new payment if one already exists"):
with self.subTest("Updates payment if one already exists"):
existing_payment = Payment(amount=2)
p = services.create_payment(
MockPayable(payer=self.member, payment=existing_payment),
self.member,
Payment.CASH,
)
self.assertEqual(p, existing_payment)
self.assertEqual(p.amount, 2)
self.assertEqual(p.amount, 5)
with self.subTest("Does not allow Thalia Pay when not enabled"):
with self.assertRaises(PaymentError):
services.create_payment(
Expand Down
21 changes: 3 additions & 18 deletions website/pizzas/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,9 @@ def validate(self, attrs):
return super().validate(attrs)

def create(self, validated_data: Any) -> Any:
if "payment" in validated_data:
payment_type = validated_data["payment"].get("type", Payment.NONE)
del validated_data["payment"]
else:
payment_type = Payment.NONE

instance = super().create(validated_data)
instance.payment.type = payment_type
instance.payment.save()
return instance
del validated_data["payment"]
return super().create(validated_data)

def update(self, instance: Model, validated_data: Any) -> Any:
if (
validated_data.get("payment", {}).get("type", instance.payment.type)
!= instance.payment.type
):
instance.payment.type = validated_data["payment"]["type"]
instance.payment.save()
if "payment" in validated_data:
del validated_data["payment"]
del validated_data["payment"]
return super().update(instance, validated_data)
29 changes: 21 additions & 8 deletions website/pizzas/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from payments.models import Payment
from pizzas.api import serializers
from pizzas.models import Product, PizzaEvent, Order
from pizzas.services import can_change_order
from pizzas.services import can_change_order, update_payment


class PizzaViewset(GenericViewSet, ListModelMixin):
Expand Down Expand Up @@ -53,7 +53,7 @@ def get_queryset(self):

return Order.objects.filter(
member=self.request.member,
payment__type=Payment.NONE,
payment=None,
pizza_event=event,
)
return Order.objects.filter(member=self.request.member, pizza_event=event)
Expand All @@ -80,13 +80,26 @@ def perform_create(self, serializer):
if serializer.validated_data.get("name"):
serializer.save(pizza_event=PizzaEvent.current())
else:
if self.action.endswith("update") and can_change_order(
self.request.member, PizzaEvent.current()
):
serializer.save(pizza_event=PizzaEvent.current())
if can_change_order(self.request.member, PizzaEvent.current()):
order = serializer.save(pizza_event=PizzaEvent.current())
if "payment" in serializer.validated_data:
payment_type = serializer.validated_data["payment"]["type"]
else:
payment_type = Payment.NONE

update_payment(order, payment_type, self.request.user)
else:
serializer.save(
member=self.request.member, pizza_event=PizzaEvent.current()
)
except IntegrityError:
raise ValidationError("Something went wrong when saving the order")
except IntegrityError as e:
raise ValidationError("Something went wrong when saving the order" + str(e))

def perform_update(self, serializer):
order = serializer.save()
if "payment" in serializer.validated_data and can_change_order(
self.request.member, PizzaEvent.current()
):
update_payment(
order, serializer.validated_data["payment"]["type"], self.request.user,
)
19 changes: 19 additions & 0 deletions website/pizzas/migrations/0012_auto_20191116_2329.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 2.2.6 on 2019-11-16 22:29

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('pizzas', '0011_auto_20191129_1634'),
]

operations = [
migrations.AlterField(
model_name='order',
name='payment',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pizzas_order', to='payments.Payment', verbose_name='payment'),
),
]
66 changes: 26 additions & 40 deletions website/pizzas/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from events.models import Event
import members
from members.models import Member
from payments.models import Payment
from payments.models import Payment, Payable
from pushnotifications.models import ScheduledMessage, Category
from utils.translation import ModelTranslateMeta, MultilingualField

Expand Down Expand Up @@ -170,7 +170,7 @@ class Meta:
permissions = (("order_restricted_products", _("Order restricted products")),)


class Order(models.Model):
class Order(models.Model, Payable):
"""Describes an order of an item during an event"""

member = models.ForeignKey(
Expand All @@ -190,6 +190,8 @@ class Order(models.Model):
to="payments.Payment",
related_name="pizzas_order",
on_delete=models.CASCADE,
blank=True,
null=True,
)

product = models.ForeignKey(
Expand All @@ -200,6 +202,26 @@ class Order(models.Model):
verbose_name=_("event"), to=PizzaEvent, on_delete=models.CASCADE
)

@property
def payment_amount(self):
return self.product.price

@property
def payment_topic(self):
start_date = date(self.pizza_event.start, "Y-m-d")
return f"Pizzas {self.pizza_event.event.title_en} [{start_date}]"

@property
def payment_notes(self):
return (
f"Pizza order by {self.member_name} "
f"for {self.pizza_event.event.title_en}"
)

@property
def payment_payer(self):
return self.member

def clean(self):
if (self.member is None and not self.name) or (self.member and self.name):
raise ValidationError(
Expand All @@ -209,38 +231,6 @@ def clean(self):
}
)

def save(self, *args, **kwargs):
if not self.id and self.pizza_event.end_reminder:
self.pizza_event.end_reminder.users.remove(self.member)

notes = (
f"Pizza order by {self.member_name} "
f"for {self.pizza_event.event.title_en}"
)
try:
self.payment.notes = notes
self.payment.paid_by = self.member
self.payment.amount = self.product.price
self.payment.save()
except ObjectDoesNotExist:
self.payment = Payment.objects.create(
amount=self.product.price,
notes=notes,
paid_by=self.member,
topic=f"Pizzas {self.pizza_event.event.title_en} "
f'[{date(self.pizza_event.start, "Y-m-d")}]',
)

super().save(*args, **kwargs)

def delete(self, using=None, keep_parents=False):
if not self.id and self.pizza_event.end_reminder:
self.pizza_event.end_reminder.users.add(self.member)

payment = self.payment
super().delete(using, keep_parents)
payment.delete()

@property
def member_name(self):
if self.member is not None:
Expand All @@ -263,12 +253,8 @@ def member_first_name(self):
def can_be_changed(self):
try:
return (
self.payment
and not (
self.payment.processed and not self.payment.type == Payment.TPAY
)
and not self.pizza_event.has_ended
)
not self.payment or self.payment.type == Payment.TPAY
) and not self.pizza_event.has_ended
except ObjectDoesNotExist:
return False

Expand Down
15 changes: 15 additions & 0 deletions website/pizzas/services.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
from events.services import is_organiser
from payments.models import Payment
from payments.services import create_payment, delete_payment
from .models import Product, Order, PizzaEvent


def update_payment(order, payment_type=None, processed_by=None):
if order.payment and payment_type == Payment.NONE:
delete_payment(order)
elif order.payment:
if payment_type is None:
payment_type = order.payment.type
order.payment = create_payment(order, processed_by, payment_type)
order.payment.save()
else:
order.payment = create_payment(order, processed_by, payment_type)
order.save()


def gen_stats_pizza_orders():
"""
Generate statistics about number of orders per product
Expand Down
22 changes: 21 additions & 1 deletion website/pizzas/signals.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""The signals checked by the pizzas package"""
from django.db.models.signals import post_save
from django.db.models.signals import post_save, post_delete, pre_delete, pre_save

from utils.models.signals import suspendingreceiver

Expand All @@ -19,3 +19,23 @@ def post_registration_save(sender, instance, **kwargs):
event.pizzaevent.end_reminder.users.remove(instance.member)
else:
event.pizzaevent.end_reminder.users.add(instance.member)


@suspendingreceiver(pre_save, sender="pizzas.Order", dispatch_uid="pizzas_order_save")
def pre_order_save(sender, instance, **kwargs):
"""Remove user from the order reminder when saved"""
if (
not instance.pk
and instance.pizza_event.end_reminder
and not instance.pizza_event.end_reminder.sent
):
instance.pizza_event.end_reminder.users.remove(instance.member)


@suspendingreceiver(
pre_delete, sender="pizzas.Order", dispatch_uid="pizzas_order_delete"
)
def pre_order_delete(sender, instance, **kwargs):
"""Re-add user to reminder to on order deletion"""
if instance.pizza_event.end_reminder and not instance.pizza_event.end_reminder.sent:
instance.pizza_event.end_reminder.users.add(instance.member)
6 changes: 3 additions & 3 deletions website/pizzas/templates/pizzas/admin/orders.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,16 @@
<td>
<select name="payment"
data-none="{{ payment.NONE }}"
{% if order.payment.type != payment.NONE %}class="paid"{% endif %}>
{% if order.payment is not None %}class="paid"{% endif %}>
<option value="{{ payment.NONE }}"
{% if order.payment.type == payment.NONE %}selected{% endif %}>{% trans 'None' %}</option>
{% if order.payment is None %}selected{% endif %}>{% trans 'None' %}</option>
<option value="{{ payment.CARD }}"
{% if order.payment.type == payment.CARD %}selected{% endif %}>{% trans 'Card' %}</option>
<option value="{{ payment.CASH }}"
{% if order.payment.type == payment.CASH %}selected{% endif %}>{% trans 'Cash' %}</option>
<option value="{{ payment.TPAY }}"
{% if order.payment.type == payment.TPAY %}selected{% endif %}
{% if not order.payment.paid_by.tpay_enabled %} disabled {% endif %}>{% trans 'Thalia Pay' %}</option>
{% if not order.member.tpay_enabled %} disabled {% endif %}>{% trans 'Thalia Pay' %}</option>
</select>
</td>
<td>
Expand Down
6 changes: 2 additions & 4 deletions website/pizzas/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from payments.models import Payment
from .models import Order, PizzaEvent, Product
from .services import update_payment


@login_required
Expand All @@ -34,8 +35,6 @@ def cancel_order(request):
if not order.can_be_changed:
messages.error(request, _("You can no longer cancel."))
elif order.member == request.member:
if order.payment.type == Payment.TPAY:
order.payment.type = Payment.NONE
order.delete()
messages.success(request, _("Your order has been cancelled."))
except Http404:
Expand All @@ -50,8 +49,7 @@ def pay_order(request):
try:
order = get_object_or_404(Order, pk=int(request.POST["order"]))
if order.member == request.member:
order.payment.type = Payment.TPAY
order.save()
update_payment(order, Payment.TPAY, order.member)
messages.success(
request, _("Your order has been paid with " "Thalia Pay.")
)
Expand Down

0 comments on commit cf8f52a

Please sign in to comment.