From 9fdf66ed744192a2d25164bdfec45719423b0420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Tue, 3 Mar 2020 10:51:16 +0100 Subject: [PATCH] Fix MatrixService ordering --- uncloud/uncloud_pay/models.py | 4 +++ uncloud/uncloud_pay/views.py | 1 - uncloud/uncloud_vm/models.py | 6 ++++ uncloud/uncloud_vm/serializers.py | 16 +++++---- uncloud/ungleich_service/models.py | 12 +++++-- uncloud/ungleich_service/serializers.py | 17 +++++---- uncloud/ungleich_service/views.py | 48 +++++++++++++++++++++++-- 7 files changed, 83 insertions(+), 21 deletions(-) diff --git a/uncloud/uncloud_pay/models.py b/uncloud/uncloud_pay/models.py index f4bd4f0..8964cb3 100644 --- a/uncloud/uncloud_pay/models.py +++ b/uncloud/uncloud_pay/models.py @@ -303,5 +303,9 @@ class Product(models.Model): def recurring_period(self): return self.order.recurring_period + @staticmethod + def allowed_recurring_periods(): + return RecurringPeriod.choices + class Meta: abstract = True diff --git a/uncloud/uncloud_pay/views.py b/uncloud/uncloud_pay/views.py index aaee9de..936d4c7 100644 --- a/uncloud/uncloud_pay/views.py +++ b/uncloud/uncloud_pay/views.py @@ -90,7 +90,6 @@ class PaymentMethodViewSet(viewsets.ModelViewSet): else: return Response(status=status.HTTP_500_INTERNAL_ERROR) - ### # Admin views. diff --git a/uncloud/uncloud_vm/models.py b/uncloud/uncloud_vm/models.py index 7732964..2f048ec 100644 --- a/uncloud/uncloud_vm/models.py +++ b/uncloud/uncloud_vm/models.py @@ -60,6 +60,12 @@ class VMProduct(Product): return "Virtual machine '{}': {} core(s), {}GB memory".format( self.name, self.cores, self.ram_in_gb) + @staticmethod + def allowed_recurring_periods(): + return list(filter( + lambda pair: pair[0] in [RecurringPeriod.PER_MONTH, RecurringPeriod.PER_HOUR], + RecurringPeriod.choices)) + class VMWithOSProduct(VMProduct): pass diff --git a/uncloud/uncloud_vm/serializers.py b/uncloud/uncloud_vm/serializers.py index daf36ab..490a8d2 100644 --- a/uncloud/uncloud_vm/serializers.py +++ b/uncloud/uncloud_vm/serializers.py @@ -11,14 +11,9 @@ class VMHostSerializer(serializers.HyperlinkedModelSerializer): class VMProductSerializer(serializers.HyperlinkedModelSerializer): - # TODO: move this to VMProduct. - allowed_recurring_periods=list(filter( - lambda pair: pair[0] in [RecurringPeriod.PER_MONTH, RecurringPeriod.PER_HOUR], - RecurringPeriod.choices)) - # Custom field used at creation (= ordering) only. recurring_period = serializers.ChoiceField( - choices=allowed_recurring_periods) + choices=VMProduct.allowed_recurring_periods()) class Meta: model = VMProduct @@ -26,6 +21,15 @@ class VMProductSerializer(serializers.HyperlinkedModelSerializer): 'cores', 'ram_in_gb', 'recurring_period'] read_only_fields = ['uuid', 'order', 'owner', 'status'] +class ManagedVMProductSerializer(serializers.ModelSerializer): + """ + Managed VM serializer used in ungleich_service app. + """ + class Meta: + model = VMProduct + fields = [ 'cores', 'ram_in_gb'] + + class VMSnapshotProductSerializer(serializers.ModelSerializer): class Meta: model = VMSnapshotProduct diff --git a/uncloud/ungleich_service/models.py b/uncloud/ungleich_service/models.py index 0e84f62..8f95973 100644 --- a/uncloud/ungleich_service/models.py +++ b/uncloud/ungleich_service/models.py @@ -6,7 +6,6 @@ from uncloud_vm.models import VMProduct class MatrixServiceProduct(Product): monthly_managment_fee = 20 - setup_fee = 30 description = "Managed Matrix HomeServer" @@ -18,9 +17,16 @@ class MatrixServiceProduct(Product): def recurring_price(self, recurring_period=RecurringPeriod.PER_MONTH): if recurring_period == RecurringPeriod.PER_MONTH: - return monthly_managment_fee + vm.recurring_price(RecurringPeriod.PER_MONTH) + return self.monthly_managment_fee else: raise Exception('Invalid recurring period for VM Product pricing.') + @staticmethod + def allowed_recurring_periods(): + return list(filter( + lambda pair: pair[0] in [RecurringPeriod.PER_MONTH], + RecurringPeriod.choices)) + + @property def setup_fee(self): - return setup_fee + return 30 diff --git a/uncloud/ungleich_service/serializers.py b/uncloud/ungleich_service/serializers.py index 0c34dcf..b4038b7 100644 --- a/uncloud/ungleich_service/serializers.py +++ b/uncloud/ungleich_service/serializers.py @@ -1,18 +1,17 @@ from rest_framework import serializers from .models import MatrixServiceProduct -from uncloud_vm.serializers import VMProductSerializer +from uncloud_vm.serializers import ManagedVMProductSerializer from uncloud_vm.models import VMProduct +from uncloud_pay.models import RecurringPeriod class MatrixServiceProductSerializer(serializers.ModelSerializer): - vm = VMProductSerializer() + vm = ManagedVMProductSerializer() + + # Custom field used at creation (= ordering) only. + recurring_period = serializers.ChoiceField( + choices=MatrixServiceProduct.allowed_recurring_periods()) class Meta: model = MatrixServiceProduct - fields = ['uuid', 'order', 'owner', 'status', 'vm', 'domain'] + fields = ['uuid', 'order', 'owner', 'status', 'vm', 'domain', 'recurring_period'] read_only_fields = ['uuid', 'order', 'owner', 'status'] - - def create(self, validated_data): - # Create VM - vm_data = validated_data.pop('vm') - vm = VMProduct.objects.create(**vm_data) - return MatrixServiceProduct.create(vm=vm, **validated_data) diff --git a/uncloud/ungleich_service/views.py b/uncloud/ungleich_service/views.py index a8de2e0..d5191a2 100644 --- a/uncloud/ungleich_service/views.py +++ b/uncloud/ungleich_service/views.py @@ -1,9 +1,13 @@ from rest_framework import viewsets, permissions +from rest_framework.response import Response +from django.db import transaction from .models import MatrixServiceProduct from .serializers import MatrixServiceProductSerializer from uncloud_pay.helpers import ProductViewSet +from uncloud_pay.models import Order +from uncloud_vm.models import VMProduct class MatrixServiceProductViewSet(ProductViewSet): permission_classes = [permissions.IsAuthenticated] @@ -12,6 +16,46 @@ class MatrixServiceProductViewSet(ProductViewSet): def get_queryset(self): return MatrixServiceProduct.objects.filter(owner=self.request.user) + @transaction.atomic def create(self, request): - # TODO: create order, register service - return Response('{"HIT!"}') + # Extract serializer data. + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + order_recurring_period = serializer.validated_data.pop("recurring_period") + + # Create base order. + order = Order.objects.create( + recurring_period=order_recurring_period, + owner=request.user + ) + order.save() + + # Create unerderlying VM. + # TODO: move this logic to a method for use with other + # products. + vm_data = serializer.validated_data.pop('vm') + vm_data['owner'] = request.user + vm_data['order'] = order + vm = VMProduct.objects.create(**vm_data) + + # XXX: Move this to some kind of on_create hook in parent + # Product class? + order.add_record( + vm.setup_fee, + vm.recurring_price(order.recurring_period), + vm.description) + + # Create service. + service = serializer.save( + order=order, + owner=self.request.user, + vm=vm) + + # XXX: Move this to some kind of on_create hook in parent + # Product class? + order.add_record( + service.setup_fee, + service.recurring_price(order.recurring_period), + service.description) + + return Response(serializer.data)