diff --git a/doc/uncloud-manual-2020-08-01.org b/doc/uncloud-manual-2020-08-01.org index 6abeb7a..6e8e4be 100644 --- a/doc/uncloud-manual-2020-08-01.org +++ b/doc/uncloud-manual-2020-08-01.org @@ -2,9 +2,9 @@ ** Pre-requisites by operating system *** Alpine #+BEGIN_SRC sh -apk add openldap-dev postgresql-dev +apk add openldap-dev postgresql-dev libxml2-dev libxslt-dev #+END_SRC -*** Debian/Devuan: +*** Debian/Devuan: #+BEGIN_SRC sh apt install postgresql-server-dev-all #+END_SRC diff --git a/uncloud_pay/management/commands/add-opennebula-vm-orders.py b/uncloud_pay/management/commands/add-opennebula-vm-orders.py index e07d3f5..d90c0ad 100644 --- a/uncloud_pay/management/commands/add-opennebula-vm-orders.py +++ b/uncloud_pay/management/commands/add-opennebula-vm-orders.py @@ -58,31 +58,74 @@ class Command(BaseCommand): owner=user, size_in_gb=30) - order_vm_25206 = Order.objects.create(owner=user, - billing_address=addr, - starting_date=timezone.make_aware(datetime.datetime(2020,3,3)), - recurring_period=RecurringPeriod.PER_30D, - recurring_price = vm_price_2020(cpu=1, ram=4) / 2, - description = "VM %s" % vm25206 - ) - - order_vm_25206_ssd = Order.objects.create(owner=user, - billing_address=addr, - starting_date=timezone.make_aware(datetime.datetime(2020,3,3)), - recurring_period=RecurringPeriod.PER_30D, - recurring_price = disk_price_2020(30, VMDiskType.CEPH_SSD) / 2, - description = vm25206_ssd - ) - vm25206.cores = 2 vm25206.ram_in_gb = 8 vm25206.save() + vm25206.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,4,17))) - order_vm_25206_growing = Order.objects.create(owner=user, - billing_address=addr, - starting_date=timezone.make_aware(datetime.datetime(2020,4,17)), - recurring_period=RecurringPeriod.PER_30D, - recurring_price = vm_price_2020(cpu=2, ram=8) / 2, - replaces=order_vm_25206, - description = "VM %s" % vm25206 - ) + vm25206_ssd.size_in_gb = 50 + vm25206_ssd.save() + vm25206_ssd.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,8,5))) + + vm25615 = VMProduct.objects.create(name="OpenNebula 25615", + cores=1, + ram_in_gb=4, + owner=user) + + vm25615_ssd = VMDiskProduct.objects.create(vm=vm25615, + owner=user, + size_in_gb=30) + + + vm25615.cores = 2 + vm25615.ram_in_gb = 8 + vm25615.save() + vm25615.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,4,17))) + + vm25615_ssd.size_in_gb = 50 + vm25615_ssd.save() + vm25615_ssd.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,8,5))) + + + vm25208 = VMProduct.objects.create(name="OpenNebula 25208", + cores=1, + ram_in_gb=4, + owner=user) + + vm25208_ssd = VMDiskProduct.objects.create(vm=vm25208, + owner=user, + size_in_gb=30) + + + vm25208.cores = 2 + vm25208.ram_in_gb = 8 + vm25208.save() + vm25208.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,4,17))) + + vm25208_ssd.size_in_gb = 50 + vm25208_ssd.save() + vm25208_ssd.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,8,5))) + + + vm25207 = VMProduct.objects.create(name="OpenNebula 25207", + cores=1, + ram_in_gb=4, + owner=user) + + vm25207_ssd = VMDiskProduct.objects.create(vm=vm25207, + owner=user, + size_in_gb=30) + + vm25207_ssd.size_in_gb = 50 + vm25207_ssd.save() + vm25207_ssd.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,8,5))) + + + vm25207.cores = 2 + vm25207.ram_in_gb = 8 + vm25207.save() + vm25207.create_or_update_order(when_to_start=timezone.make_aware(datetime.datetime(2020,6,19))) + + + # FIXES: check starting times (they are slightly different) + # add vm 25236 diff --git a/uncloud_pay/migrations/0002_auto_20200801_2208.py b/uncloud_pay/migrations/0002_auto_20200801_2208.py new file mode 100644 index 0000000..9bc76f1 --- /dev/null +++ b/uncloud_pay/migrations/0002_auto_20200801_2208.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.8 on 2020-08-01 22:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('uncloud_pay', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='billingaddress', + name='organization', + field=models.CharField(blank=True, max_length=100, null=True), + ), + ] diff --git a/uncloud_pay/models.py b/uncloud_pay/models.py index 662e51c..ebc1c09 100644 --- a/uncloud_pay/models.py +++ b/uncloud_pay/models.py @@ -224,7 +224,7 @@ class PaymentMethod(models.Model): class BillingAddress(models.Model): owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE) - organization = models.CharField(max_length=100) + organization = models.CharField(max_length=100, blank=True, null=True) name = models.CharField(max_length=100) street = models.CharField(max_length=100) city = models.CharField(max_length=50) @@ -241,17 +241,8 @@ class BillingAddress(models.Model): ] @staticmethod - def get_addresses_for(user): - return BillingAddress.objects.filter(owner=user) - - @classmethod - def get_preferred_address_for(cls, user): - addresses = cls.get_addresses_for(user) - if len(addresses) == 0: - return None - else: - # TODO: allow user to set primary/preferred address - return addresses[0] + def get_address_for(user): + return BillingAddress.objects.get(owner=user, active=True) def __str__(self): return "{} - {}, {}, {} {}, {}".format( @@ -608,8 +599,9 @@ class Product(UncloudModel): order = models.ForeignKey(Order, on_delete=models.CASCADE, - editable=False, + editable=True, null=True) + # FIXME: editable=True -> is in the admin, but also editable in DRF status = models.CharField(max_length=32, choices=UncloudStatus.choices, @@ -618,25 +610,48 @@ class Product(UncloudModel): # Default period for all products default_recurring_period = RecurringPeriod.PER_30D - # Used to save records. - def save(self, *args, **kwargs): - # _state.adding is switched to false after super(...) call. - being_created = self._state.adding - # First time saving - create an order + def create_or_update_order(self, when_to_start=None): + if not when_to_start: + when_to_start = timezone.now() + if not self.order: - billing_address = BillingAddress.get_preferred_address_for(self.owner) - print(billing_address) + billing_address = BillingAddress.get_address_for(self.owner) if not billing_address: raise ValidationError("Cannot order without a billing address") - # FIXME: allow user to choose recurring_period self.order = Order.objects.create(owner=self.owner, billing_address=billing_address, + starting_date=when_to_start, one_time_price=self.one_time_price, recurring_period=self.default_recurring_period, - recurring_price=self.recurring_price) + recurring_price=self.recurring_price, + description=str(self)) + + else: + previous_order = self.order + when_to_end = when_to_start - datetime.timedelta(seconds=1) + + new_order = Order.objects.create(owner=self.owner, + billing_address=self.order.billing_address, + starting_date=when_to_start, + one_time_price=self.one_time_price, + recurring_period=self.default_recurring_period, + recurring_price=self.recurring_price, + description=str(self), + replaces=self.order) + + self.order.end_date = when_to_end + self.order.save() + + self.order = new_order + + + def save(self, *args, **kwargs): + # Create order the first time a product is created + if self._state.adding: + self.create_or_update_order() super().save(*args, **kwargs) diff --git a/uncloud_vm/admin.py b/uncloud_vm/admin.py index 9f30b04..6f3bc50 100644 --- a/uncloud_vm/admin.py +++ b/uncloud_vm/admin.py @@ -2,13 +2,17 @@ from django.contrib import admin # Register your models here. from uncloud_vm.models import * +from uncloud_pay.models import Order class VMDiskInline(admin.TabularInline): model = VMDiskProduct +class OrderInline(admin.TabularInline): + model = Order + class VMProductAdmin(admin.ModelAdmin): inlines = [ - VMDiskInline, + VMDiskInline ] admin.site.register(VMProduct, VMProductAdmin)