Implement non-destructive order updates

This commit is contained in:
fnux 2020-05-08 10:07:44 +02:00
parent 89e853b490
commit d47c94ba84
3 changed files with 30 additions and 1 deletions

View file

@ -827,6 +827,7 @@ class Order(models.Model):
editable=False)
billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE)
description = models.TextField()
replaced_by = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
# TODO: enforce ending_date - starting_date to be larger than recurring_period.
creation_date = models.DateTimeField(auto_now_add=True)

View file

@ -71,7 +71,7 @@ class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = ['uuid', 'owner', 'description', 'creation_date', 'starting_date', 'ending_date',
'bill', 'recurring_period', 'recurring_price', 'one_time_price']
'bill', 'recurring_period', 'recurring_price', 'one_time_price', 'replaced_by']
###

View file

@ -13,6 +13,7 @@ from hardcopy import bytestring_to_pdf
from django.core.files.temp import NamedTemporaryFile
from django.http import FileResponse
from django.template.loader import render_to_string
from copy import deepcopy
import json
import logging
@ -304,6 +305,7 @@ class AdminBillViewSet(BillViewSet):
class AdminOrderViewSet(mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.CreateModelMixin,
mixins.UpdateModelMixin,
viewsets.GenericViewSet):
serializer_class = OrderSerializer
permission_classes = [permissions.IsAdminUser]
@ -314,6 +316,32 @@ class AdminOrderViewSet(mixins.ListModelMixin,
def get_queryset(self):
return Order.objects.all()
# Updates create a new order and terminate the 'old' one.
@transaction.atomic
def update(self, request, *args, **kwargs):
order = self.get_object()
partial = kwargs.pop('partial', False)
serializer = self.get_serializer(order, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
# Clone existing order for replacement.
replacing_order = deepcopy(order)
# Yes, that's how you make a new entry in DB:
# https://docs.djangoproject.com/en/3.0/topics/db/queries/#copying-model-instances
replacing_order.pk = None
for attr, value in serializer.validated_data.items():
setattr(replacing_order, attr, value)
# Save replacing order and terminate 'previous' one.
replacing_order.save()
order.replaced_by = replacing_order
order.save()
order.terminate()
return Response(replacing_order)
@action(detail=True, methods=['post'])
def terminate(self, request, pk):
order = self.get_object()