forked from uncloud/uncloud
Implement non-destructive order updates
This commit is contained in:
parent
89e853b490
commit
d47c94ba84
3 changed files with 30 additions and 1 deletions
|
@ -827,6 +827,7 @@ class Order(models.Model):
|
||||||
editable=False)
|
editable=False)
|
||||||
billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE)
|
billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE)
|
||||||
description = models.TextField()
|
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.
|
# TODO: enforce ending_date - starting_date to be larger than recurring_period.
|
||||||
creation_date = models.DateTimeField(auto_now_add=True)
|
creation_date = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
|
@ -71,7 +71,7 @@ class OrderSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Order
|
model = Order
|
||||||
fields = ['uuid', 'owner', 'description', 'creation_date', 'starting_date', 'ending_date',
|
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']
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
|
@ -13,6 +13,7 @@ from hardcopy import bytestring_to_pdf
|
||||||
from django.core.files.temp import NamedTemporaryFile
|
from django.core.files.temp import NamedTemporaryFile
|
||||||
from django.http import FileResponse
|
from django.http import FileResponse
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
@ -304,6 +305,7 @@ class AdminBillViewSet(BillViewSet):
|
||||||
class AdminOrderViewSet(mixins.ListModelMixin,
|
class AdminOrderViewSet(mixins.ListModelMixin,
|
||||||
mixins.RetrieveModelMixin,
|
mixins.RetrieveModelMixin,
|
||||||
mixins.CreateModelMixin,
|
mixins.CreateModelMixin,
|
||||||
|
mixins.UpdateModelMixin,
|
||||||
viewsets.GenericViewSet):
|
viewsets.GenericViewSet):
|
||||||
serializer_class = OrderSerializer
|
serializer_class = OrderSerializer
|
||||||
permission_classes = [permissions.IsAdminUser]
|
permission_classes = [permissions.IsAdminUser]
|
||||||
|
@ -314,6 +316,32 @@ class AdminOrderViewSet(mixins.ListModelMixin,
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Order.objects.all()
|
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'])
|
@action(detail=True, methods=['post'])
|
||||||
def terminate(self, request, pk):
|
def terminate(self, request, pk):
|
||||||
order = self.get_object()
|
order = self.get_object()
|
||||||
|
|
Loading…
Reference in a new issue