Start wiring BillingAddresses to bills & orders
This commit is contained in:
parent
3fa1d5753e
commit
0522927c50
3 changed files with 66 additions and 19 deletions
|
@ -440,6 +440,36 @@ class PaymentMethod(models.Model):
|
||||||
###
|
###
|
||||||
# Bills.
|
# 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):
|
class Bill(models.Model):
|
||||||
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||||
owner = models.ForeignKey(get_user_model(),
|
owner = models.ForeignKey(get_user_model(),
|
||||||
|
@ -484,6 +514,7 @@ class Bill(models.Model):
|
||||||
# A bill is final when its ending date is passed.
|
# A bill is final when its ending date is passed.
|
||||||
return self.ending_date < timezone.now()
|
return self.ending_date < timezone.now()
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
def activate_products(self):
|
def activate_products(self):
|
||||||
for order in self.order_set.all():
|
for order in self.order_set.all():
|
||||||
# FIXME: using __something might not be a good idea.
|
# FIXME: using __something might not be a good idea.
|
||||||
|
@ -492,8 +523,12 @@ class Bill(models.Model):
|
||||||
if product.status == UncloudStatus.AWAITING_PAYMENT:
|
if product.status == UncloudStatus.AWAITING_PAYMENT:
|
||||||
product.status = UncloudStatus.PENDING
|
product.status = UncloudStatus.PENDING
|
||||||
product.save()
|
product.save()
|
||||||
|
@property
|
||||||
|
def billing_address(self):
|
||||||
|
return self.order.billing_address
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
||||||
def generate_for(year, month, user):
|
def generate_for(year, month, user):
|
||||||
# /!\ We exclusively work on the specified year and month.
|
# /!\ We exclusively work on the specified year and month.
|
||||||
generated_bills = []
|
generated_bills = []
|
||||||
|
@ -704,17 +739,6 @@ class BillRecord():
|
||||||
def amount(self):
|
def amount(self):
|
||||||
return Decimal(float(self.recurring_price) * self.recurring_count) + self.one_time_price
|
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.
|
# Populated with the import-vat-numbers django command.
|
||||||
class VATRate(models.Model):
|
class VATRate(models.Model):
|
||||||
start_date = models.DateField(blank=True, null=True)
|
start_date = models.DateField(blank=True, null=True)
|
||||||
|
@ -725,6 +749,21 @@ class VATRate(models.Model):
|
||||||
rate_type = models.TextField(blank=True, default='')
|
rate_type = models.TextField(blank=True, default='')
|
||||||
description = 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.
|
# Orders.
|
||||||
|
|
||||||
|
@ -735,6 +774,7 @@ class Order(models.Model):
|
||||||
owner = models.ForeignKey(get_user_model(),
|
owner = models.ForeignKey(get_user_model(),
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
editable=False)
|
editable=False)
|
||||||
|
billing_address = models.ForeignKey(BillingAddress, on_delete=models.CASCADE)
|
||||||
|
|
||||||
# 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)
|
||||||
|
|
|
@ -57,18 +57,19 @@ class BillRecordSerializer(serializers.Serializer):
|
||||||
view_name='order-detail',
|
view_name='order-detail',
|
||||||
read_only=True)
|
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):
|
class BillSerializer(serializers.ModelSerializer):
|
||||||
|
billing_address = BillingAddressSerializer(read_only=True)
|
||||||
records = BillRecordSerializer(many=True, read_only=True)
|
records = BillRecordSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Bill
|
model = Bill
|
||||||
fields = ['reference', 'owner', 'total', 'due_date', 'creation_date',
|
fields = ['reference', 'owner', 'total', 'due_date', 'creation_date',
|
||||||
'starting_date', 'ending_date', 'records', 'final']
|
'starting_date', 'ending_date', 'records', 'final', 'billing_address']
|
||||||
|
|
||||||
class BillingAddressSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = BillingAddress
|
|
||||||
fields = ['uuid', 'street', 'city', 'postal_code', 'country', 'vat_number']
|
|
||||||
|
|
||||||
# We do not want users to mutate the country / VAT number of an address, as it
|
# We do not want users to mutate the country / VAT number of an address, as it
|
||||||
# will change VAT on existing bills.
|
# will change VAT on existing bills.
|
||||||
|
|
|
@ -2,7 +2,7 @@ from rest_framework import serializers
|
||||||
from .models import *
|
from .models import *
|
||||||
from uncloud_vm.serializers import ManagedVMProductSerializer
|
from uncloud_vm.serializers import ManagedVMProductSerializer
|
||||||
from uncloud_vm.models import VMProduct
|
from uncloud_vm.models import VMProduct
|
||||||
from uncloud_pay.models import RecurringPeriod
|
from uncloud_pay.models import RecurringPeriod, BillingAddress
|
||||||
|
|
||||||
class MatrixServiceProductSerializer(serializers.ModelSerializer):
|
class MatrixServiceProductSerializer(serializers.ModelSerializer):
|
||||||
vm = ManagedVMProductSerializer()
|
vm = ManagedVMProductSerializer()
|
||||||
|
@ -11,9 +11,15 @@ class MatrixServiceProductSerializer(serializers.ModelSerializer):
|
||||||
recurring_period = serializers.ChoiceField(
|
recurring_period = serializers.ChoiceField(
|
||||||
choices=MatrixServiceProduct.allowed_recurring_periods())
|
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:
|
class Meta:
|
||||||
model = MatrixServiceProduct
|
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']
|
read_only_fields = ['uuid', 'order', 'owner', 'status']
|
||||||
|
|
||||||
class GenericServiceProductSerializer(serializers.ModelSerializer):
|
class GenericServiceProductSerializer(serializers.ModelSerializer):
|
||||||
|
|
Loading…
Reference in a new issue