From 0522927c50accc6a5e51eb835e79a9eff197a7c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Sat, 18 Apr 2020 08:30:45 +0200 Subject: [PATCH] Start wiring BillingAddresses to bills & orders --- .../uncloud/uncloud_pay/models.py | 62 +++++++++++++++---- .../uncloud/uncloud_pay/serializers.py | 13 ++-- .../uncloud/uncloud_service/serializers.py | 10 ++- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/uncloud_django_based/uncloud/uncloud_pay/models.py b/uncloud_django_based/uncloud/uncloud_pay/models.py index e809f09..932a6d1 100644 --- a/uncloud_django_based/uncloud/uncloud_pay/models.py +++ b/uncloud_django_based/uncloud/uncloud_pay/models.py @@ -440,6 +440,36 @@ class PaymentMethod(models.Model): ### # Bills. +class BillingAddress(models.Model): + uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE) + + name = models.CharField(max_length=100) + street = models.CharField(max_length=100) + city = models.CharField(max_length=50) + postal_code = models.CharField(max_length=50) + country = CountryField(blank=True) + vat_number = models.CharField(max_length=100, default="", blank=True) + + @staticmethod + def get_addresses_for(user): + return BillingAddress.objects.filter(owner=user) + + @staticmethod + def get_preferred_address_for(user): + addresses = get_addresses_for(user) + if len(addresses) == 0: + return None + else: + # TODO: allow user to set primary/preferred address + return addresses[0] + + def __str__(self): + return "{}, {}, {} {}, {}".format( + self.name, self.street, self.postal_code, self.city, + self.country) + + class Bill(models.Model): uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) owner = models.ForeignKey(get_user_model(), @@ -484,6 +514,7 @@ class Bill(models.Model): # A bill is final when its ending date is passed. return self.ending_date < timezone.now() +<<<<<<< HEAD def activate_products(self): for order in self.order_set.all(): # FIXME: using __something might not be a good idea. @@ -492,8 +523,12 @@ class Bill(models.Model): if product.status == UncloudStatus.AWAITING_PAYMENT: product.status = UncloudStatus.PENDING product.save() + @property + def billing_address(self): + return self.order.billing_address @staticmethod + def generate_for(year, month, user): # /!\ We exclusively work on the specified year and month. generated_bills = [] @@ -704,17 +739,6 @@ class BillRecord(): def amount(self): return Decimal(float(self.recurring_price) * self.recurring_count) + self.one_time_price -class BillingAddress(models.Model): - uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - owner = models.ForeignKey(get_user_model(), - on_delete=models.CASCADE) - - street = models.CharField(max_length=100) - city = models.CharField(max_length=50) - postal_code = models.CharField(max_length=50) - country = CountryField(blank=True) - vat_number = models.CharField(max_length=100, default="", blank=True) - # Populated with the import-vat-numbers django command. class VATRate(models.Model): start_date = models.DateField(blank=True, null=True) @@ -725,6 +749,21 @@ class VATRate(models.Model): rate_type = models.TextField(blank=True, default='') description = models.TextField(blank=True, default='') + @staticmethod + def get_for_country(country_code): + vat_rate = None + try: + vat_rate = VATRates.objects.get( + territory_codes=country, start_date__isnull=False, stop_date=None + ) + logger.debug("VAT rate for %s is %s" % (country, vat_rate.rate)) + return vat_rate.rate + except VATRates.DoesNotExist as dne: + logger.debug(str(dne)) + logger.debug("Did not find VAT rate for %s, returning 0" % country) + return 0 + + ### # Orders. @@ -735,6 +774,7 @@ class Order(models.Model): owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, editable=False) + billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE) # TODO: enforce ending_date - starting_date to be larger than recurring_period. creation_date = models.DateTimeField(auto_now_add=True) diff --git a/uncloud_django_based/uncloud/uncloud_pay/serializers.py b/uncloud_django_based/uncloud/uncloud_pay/serializers.py index 5579b14..659092c 100644 --- a/uncloud_django_based/uncloud/uncloud_pay/serializers.py +++ b/uncloud_django_based/uncloud/uncloud_pay/serializers.py @@ -57,18 +57,19 @@ class BillRecordSerializer(serializers.Serializer): view_name='order-detail', read_only=True) +class BillingAddressSerializer(serializers.ModelSerializer): + class Meta: + model = BillingAddress + fields = ['uuid', 'name', 'street', 'city', 'postal_code', 'country', 'vat_number'] + class BillSerializer(serializers.ModelSerializer): + billing_address = BillingAddressSerializer(read_only=True) records = BillRecordSerializer(many=True, read_only=True) class Meta: model = Bill fields = ['reference', 'owner', 'total', 'due_date', 'creation_date', - 'starting_date', 'ending_date', 'records', 'final'] - -class BillingAddressSerializer(serializers.ModelSerializer): - class Meta: - model = BillingAddress - fields = ['uuid', 'street', 'city', 'postal_code', 'country', 'vat_number'] + 'starting_date', 'ending_date', 'records', 'final', 'billing_address'] # We do not want users to mutate the country / VAT number of an address, as it # will change VAT on existing bills. diff --git a/uncloud_django_based/uncloud/uncloud_service/serializers.py b/uncloud_django_based/uncloud/uncloud_service/serializers.py index 1d50bbf..2be2cee 100644 --- a/uncloud_django_based/uncloud/uncloud_service/serializers.py +++ b/uncloud_django_based/uncloud/uncloud_service/serializers.py @@ -2,7 +2,7 @@ from rest_framework import serializers from .models import * from uncloud_vm.serializers import ManagedVMProductSerializer from uncloud_vm.models import VMProduct -from uncloud_pay.models import RecurringPeriod +from uncloud_pay.models import RecurringPeriod, BillingAddress class MatrixServiceProductSerializer(serializers.ModelSerializer): vm = ManagedVMProductSerializer() @@ -11,9 +11,15 @@ class MatrixServiceProductSerializer(serializers.ModelSerializer): recurring_period = serializers.ChoiceField( choices=MatrixServiceProduct.allowed_recurring_periods()) + def __init__(self, *args, **kwargs): + super(MatrixServiceProductSerializer, self).__init__(*args, **kwargs) + self.fields['billing_address'] = serializers.ChoiceField( + choices=BillingAddress.get_addresses_for(self.context['request'].user)) + class Meta: model = MatrixServiceProduct - fields = ['uuid', 'order', 'owner', 'status', 'vm', 'domain', 'recurring_period'] + fields = ['uuid', 'order', 'owner', 'status', 'vm', 'domain', + 'recurring_period'] read_only_fields = ['uuid', 'order', 'owner', 'status'] class GenericServiceProductSerializer(serializers.ModelSerializer):