diff --git a/uncloud_django_based/uncloud/uncloud/urls.py b/uncloud_django_based/uncloud/uncloud/urls.py index 00eaf16..343e06b 100644 --- a/uncloud_django_based/uncloud/uncloud/urls.py +++ b/uncloud_django_based/uncloud/uncloud/urls.py @@ -44,6 +44,8 @@ router.register(r'vm/vm', vmviews.VMProductViewSet, basename='vmproduct') # Services router.register(r'service/matrix', serviceviews.MatrixServiceProductViewSet, basename='matrixserviceproduct') +router.register(r'service/generic', serviceviews.GenericServiceProductViewSet, basename='genericserviceproduct') + # Net router.register(r'net/vpn', netviews.VPNNetworkViewSet, basename='vpnnet') diff --git a/uncloud_django_based/uncloud/uncloud_service/models.py b/uncloud_django_based/uncloud/uncloud_service/models.py index fb1af50..fc92157 100644 --- a/uncloud_django_based/uncloud/uncloud_service/models.py +++ b/uncloud_django_based/uncloud/uncloud_service/models.py @@ -1,8 +1,9 @@ import uuid from django.db import models -from uncloud_pay.models import Product, RecurringPeriod +from uncloud_pay.models import Product, RecurringPeriod, AMOUNT_MAX_DIGITS, AMOUNT_DECIMALS from uncloud_vm.models import VMProduct, VMDiskImageProduct +from django.core.validators import MinValueValidator class MatrixServiceProduct(Product): monthly_managment_fee = 20 @@ -33,3 +34,30 @@ class MatrixServiceProduct(Product): @property def one_time_price(self): return 30 + +class GenericServiceProduct(Product): + custom_description = models.TextField() + custom_recurring_price = models.DecimalField(default=0.0, + max_digits=AMOUNT_MAX_DIGITS, + decimal_places=AMOUNT_DECIMALS, + validators=[MinValueValidator(0)]) + custom_one_time_price = models.DecimalField(default=0.0, + max_digits=AMOUNT_MAX_DIGITS, + decimal_places=AMOUNT_DECIMALS, + validators=[MinValueValidator(0)]) + + @property + def recurring_price(self): + return self.custom_recurring_price + + @property + def description(self): + return self.custom_description + + @property + def one_time_price(self): + return self.custom_one_time_price + + @staticmethod + def allowed_recurring_periods(): + return RecurringPeriod.choices diff --git a/uncloud_django_based/uncloud/uncloud_service/serializers.py b/uncloud_django_based/uncloud/uncloud_service/serializers.py index b4038b7..1d50bbf 100644 --- a/uncloud_django_based/uncloud/uncloud_service/serializers.py +++ b/uncloud_django_based/uncloud/uncloud_service/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from .models import MatrixServiceProduct +from .models import * from uncloud_vm.serializers import ManagedVMProductSerializer from uncloud_vm.models import VMProduct from uncloud_pay.models import RecurringPeriod @@ -15,3 +15,14 @@ class MatrixServiceProductSerializer(serializers.ModelSerializer): model = MatrixServiceProduct fields = ['uuid', 'order', 'owner', 'status', 'vm', 'domain', 'recurring_period'] read_only_fields = ['uuid', 'order', 'owner', 'status'] + +class GenericServiceProductSerializer(serializers.ModelSerializer): + # Custom field used at creation (= ordering) only. + recurring_period = serializers.ChoiceField( + choices=GenericServiceProduct.allowed_recurring_periods()) + + class Meta: + model = GenericServiceProduct + fields = ['uuid', 'order', 'owner', 'status', 'custom_recurring_price', + 'custom_description', 'custom_one_time_price', 'recurring_period'] + read_only_fields = ['uuid', 'order', 'owner', 'status'] diff --git a/uncloud_django_based/uncloud/uncloud_service/views.py b/uncloud_django_based/uncloud/uncloud_service/views.py index e25f3a5..d4be3a6 100644 --- a/uncloud_django_based/uncloud/uncloud_service/views.py +++ b/uncloud_django_based/uncloud/uncloud_service/views.py @@ -1,9 +1,10 @@ from rest_framework import viewsets, permissions from rest_framework.response import Response from django.db import transaction +from django.utils import timezone -from .models import MatrixServiceProduct -from .serializers import MatrixServiceProductSerializer +from .models import * +from .serializers import * from uncloud_pay.helpers import ProductViewSet from uncloud_pay.models import Order @@ -47,7 +48,10 @@ class MatrixServiceProductViewSet(ProductViewSet): # Create base order.) order = Order.objects.create( recurring_period=order_recurring_period, - owner=request.user) + owner=request.user, + starting_date=timezone.now() + ) + order.save() # Create unerderlying VM. data = serializer.validated_data.pop('vm') @@ -65,3 +69,45 @@ class MatrixServiceProductViewSet(ProductViewSet): vm=vm) return Response(serializer.data) + +class GenericServiceProductViewSet(ProductViewSet): + permission_classes = [permissions.IsAuthenticated] + serializer_class = GenericServiceProductSerializer + + def get_queryset(self): + return GenericServiceProduct.objects.filter(owner=self.request.user) + + @transaction.atomic + def create(self, request): + # 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, + starting_date=timezone.now() + ) + order.save() + + # Create service. + print(serializer.validated_data) + service = serializer.save(order=order, owner=request.user) + + # XXX: Move this to some kind of on_create hook in parent + # Product class? + order.add_record( + service.one_time_price, + service.recurring_price, + service.description) + + # XXX: Move this to some kind of on_create hook in parent + # Product class? + order.add_record( + service.one_time_price, + service.recurring_price, + service.description) + + return Response(serializer.data) diff --git a/uncloud_django_based/uncloud/ungleich_service/migrations/0005_auto_20200417_0551.py b/uncloud_django_based/uncloud/ungleich_service/migrations/0005_auto_20200417_0551.py new file mode 100644 index 0000000..aed07b6 --- /dev/null +++ b/uncloud_django_based/uncloud/ungleich_service/migrations/0005_auto_20200417_0551.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.5 on 2020-04-17 05:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ungleich_service', '0004_auto_20200403_1727'), + ] + + operations = [ + migrations.AlterField( + model_name='matrixserviceproduct', + name='status', + field=models.CharField(choices=[('PENDING', 'Pending'), ('AWAITING_PAYMENT', 'Awaiting payment'), ('BEING_CREATED', 'Being created'), ('SCHEDULED', 'Scheduled'), ('ACTIVE', 'Active'), ('MODIFYING', 'Modifying'), ('DELETED', 'Deleted'), ('DISABLED', 'Disabled'), ('UNUSABLE', 'Unusable')], default='AWAITING_PAYMENT', max_length=32), + ), + ] diff --git a/uncloud_django_based/uncloud/ungleich_service/migrations/0006_genericserviceproduct.py b/uncloud_django_based/uncloud/ungleich_service/migrations/0006_genericserviceproduct.py new file mode 100644 index 0000000..f4bda32 --- /dev/null +++ b/uncloud_django_based/uncloud/ungleich_service/migrations/0006_genericserviceproduct.py @@ -0,0 +1,36 @@ +# Generated by Django 3.0.5 on 2020-04-17 08:02 + +from django.conf import settings +import django.contrib.postgres.fields.jsonb +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('uncloud_pay', '0005_auto_20200417_0551'), + ('ungleich_service', '0005_auto_20200417_0551'), + ] + + operations = [ + migrations.CreateModel( + name='GenericServiceProduct', + fields=[ + ('extra_data', django.contrib.postgres.fields.jsonb.JSONField(blank=True, editable=False, null=True)), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('status', models.CharField(choices=[('PENDING', 'Pending'), ('AWAITING_PAYMENT', 'Awaiting payment'), ('BEING_CREATED', 'Being created'), ('SCHEDULED', 'Scheduled'), ('ACTIVE', 'Active'), ('MODIFYING', 'Modifying'), ('DELETED', 'Deleted'), ('DISABLED', 'Disabled'), ('UNUSABLE', 'Unusable')], default='AWAITING_PAYMENT', max_length=32)), + ('custom_description', models.TextField()), + ('custom_recurring_price', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])), + ('custom_one_time_price', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, validators=[django.core.validators.MinValueValidator(0)])), + ('order', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='uncloud_pay.Order')), + ('owner', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ]