From 28de423a1475f1fc4f167311be292a4ab41d34eb Mon Sep 17 00:00:00 2001 From: PCoder Date: Fri, 6 Apr 2018 00:51:44 +0200 Subject: [PATCH 01/67] Add VMPricing model --- datacenterlight/models.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/datacenterlight/models.py b/datacenterlight/models.py index 6fcf24a9..01ddfdcf 100644 --- a/datacenterlight/models.py +++ b/datacenterlight/models.py @@ -12,6 +12,19 @@ class VMTemplate(models.Model): return vm_template +class VMPricing(models.Model): + name = models.CharField(max_length=255, unique=True) + vat_inclusive = models.BooleanField(default=True) + vat_percentage = models.DecimalField(decimal_places=2, blank=True) + cores_unit_price = models.DecimalField(decimal_places=2, default=0) + ram_unit_price = models.DecimalField(decimal_places=2, default= 0) + ssd_unit_price = models.DecimalField(decimal_places=2, default=0) + hdd_unit_price = models.DecimalField(decimal_places=2, default=0) + + def __str__(self): + return self.name + + class StripePlan(models.Model): """ A model to store Data Center Light's created Stripe plans From d07cc41d0a102dd65938185331e3662fc9059cc4 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 9 Apr 2018 21:17:48 +0200 Subject: [PATCH 02/67] Update VMPricing and add get_default_pricing class method --- datacenterlight/models.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/datacenterlight/models.py b/datacenterlight/models.py index 01ddfdcf..3a376747 100644 --- a/datacenterlight/models.py +++ b/datacenterlight/models.py @@ -15,14 +15,33 @@ class VMTemplate(models.Model): class VMPricing(models.Model): name = models.CharField(max_length=255, unique=True) vat_inclusive = models.BooleanField(default=True) - vat_percentage = models.DecimalField(decimal_places=2, blank=True) - cores_unit_price = models.DecimalField(decimal_places=2, default=0) - ram_unit_price = models.DecimalField(decimal_places=2, default= 0) - ssd_unit_price = models.DecimalField(decimal_places=2, default=0) - hdd_unit_price = models.DecimalField(decimal_places=2, default=0) + vat_percentage = models.DecimalField( + max_digits=7, decimal_places=2, blank=True, default=0 + ) + cores_unit_price = models.DecimalField( + max_digits=7, decimal_places=2, default=0 + ) + ram_unit_price = models.DecimalField( + max_digits=7, decimal_places=2, default=0 + ) + ssd_unit_price = models.DecimalField( + max_digits=7, decimal_places=2, default=0 + ) + hdd_unit_price = models.DecimalField( + max_digits=7, decimal_places=2, default=0 + ) def __str__(self): - return self.name + return self.name + '-' + 'VAT' if self.vat_inclusive else 'NO_VAT' + + @classmethod + def get_default_pricing(cls): + """ Returns the default pricing or None """ + try: + default_pricing = VMPricing.objects.get(name='default') + except: + default_pricing = None + return default_pricing class StripePlan(models.Model): From c7afbb32c0d8f5d237bd96e480be30a5e64077bd Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 9 Apr 2018 21:18:18 +0200 Subject: [PATCH 03/67] Add DCLCalculatorPluginModel --- datacenterlight/cms_models.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/datacenterlight/cms_models.py b/datacenterlight/cms_models.py index 9eb55e0c..583ac6a5 100644 --- a/datacenterlight/cms_models.py +++ b/datacenterlight/cms_models.py @@ -6,6 +6,8 @@ from django.utils.safestring import mark_safe from djangocms_text_ckeditor.fields import HTMLField from filer.fields.image import FilerImageField +from datacenterlight.models import VMPricing + class CMSIntegration(models.Model): name = models.CharField( @@ -275,3 +277,12 @@ class DCLSectionPromoPluginModel(CMSPlugin): if self.background_image: extra_classes += ' promo-with-bg' return extra_classes + + +class DCLCalculatorPluginModel(DCLSectionPluginModel): + pricing = models.ForeignKey( + VMPricing, + default=VMPricing.get_default_pricing(), + help_text='Choose a pricing that will be associated with this ' + 'Calculator' + ) From dd30542f9f14737cf59186f06a7ef3f2fbdac245 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 9 Apr 2018 21:18:50 +0200 Subject: [PATCH 04/67] Use DCLCalculatorPluginModel in DCLCalculatorPlugin --- datacenterlight/cms_plugins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datacenterlight/cms_plugins.py b/datacenterlight/cms_plugins.py index a1a3833d..26ee9162 100644 --- a/datacenterlight/cms_plugins.py +++ b/datacenterlight/cms_plugins.py @@ -6,7 +6,7 @@ from .cms_models import ( DCLFooterPluginModel, DCLLinkPluginModel, DCLNavbarDropdownPluginModel, DCLSectionIconPluginModel, DCLSectionImagePluginModel, DCLSectionPluginModel, DCLNavbarPluginModel, - DCLSectionPromoPluginModel + DCLSectionPromoPluginModel, DCLCalculatorPluginModel ) from .models import VMTemplate @@ -76,7 +76,7 @@ class DCLSectionPromoPlugin(CMSPluginBase): class DCLCalculatorPlugin(CMSPluginBase): module = "Datacenterlight" name = "DCL Calculator Plugin" - model = DCLSectionPluginModel + model = DCLCalculatorPluginModel render_template = "datacenterlight/cms/calculator.html" cache = False allow_children = True From 4d6fdf2de97d6ba35397a9b83e71f82a2ed4b8f5 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 9 Apr 2018 21:32:53 +0200 Subject: [PATCH 05/67] Add DCLCalculatorPluginModel and VMPricing models --- .../migrations/0019_auto_20180409_1923.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 datacenterlight/migrations/0019_auto_20180409_1923.py diff --git a/datacenterlight/migrations/0019_auto_20180409_1923.py b/datacenterlight/migrations/0019_auto_20180409_1923.py new file mode 100644 index 00000000..4766cb5e --- /dev/null +++ b/datacenterlight/migrations/0019_auto_20180409_1923.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2018-04-09 19:23 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('datacenterlight', '0018_auto_20180403_1930'), + ] + + operations = [ + migrations.CreateModel( + name='DCLCalculatorPluginModel', + fields=[ + ('dclsectionpluginmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='datacenterlight.DCLSectionPluginModel')), + ], + options={ + 'abstract': False, + }, + bases=('datacenterlight.dclsectionpluginmodel',), + ), + migrations.CreateModel( + name='VMPricing', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, unique=True)), + ('vat_inclusive', models.BooleanField(default=True)), + ('vat_percentage', models.DecimalField(blank=True, decimal_places=2, default=0, max_digits=7)), + ('cores_unit_price', models.DecimalField(decimal_places=2, default=0, max_digits=7)), + ('ram_unit_price', models.DecimalField(decimal_places=2, default=0, max_digits=7)), + ('ssd_unit_price', models.DecimalField(decimal_places=2, default=0, max_digits=7)), + ('hdd_unit_price', models.DecimalField(decimal_places=2, default=0, max_digits=7)), + ], + ), + migrations.AddField( + model_name='dclcalculatorpluginmodel', + name='pricing', + field=models.ForeignKey(default=None, help_text='Choose a pricing that will be associated with this Calculator', on_delete=django.db.models.deletion.CASCADE, to='datacenterlight.VMPricing'), + ), + ] From 76c9b20cc9534e603b6caa6df59607c5eda706bd Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 9 Apr 2018 21:34:09 +0200 Subject: [PATCH 06/67] Add VMPricing init migration --- .../migrations/0020_auto_20180409_1928.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 datacenterlight/migrations/0020_auto_20180409_1928.py diff --git a/datacenterlight/migrations/0020_auto_20180409_1928.py b/datacenterlight/migrations/0020_auto_20180409_1928.py new file mode 100644 index 00000000..9a659acc --- /dev/null +++ b/datacenterlight/migrations/0020_auto_20180409_1928.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2018-04-09 19:28 +from __future__ import unicode_literals + +from django.db import migrations + +DEFAULT_VMPRICING_NAME='default' + + +def create_default_pricing(apps, schema_editor): + """ + Create default pricing + :param apps: + :param schema_editor: + :return: + """ + VMPricing = apps.get_model('datacenterlight', 'VMPricing') + if not VMPricing.objects.count(): + vm_pricing = VMPricing( + name=DEFAULT_VMPRICING_NAME, + vat_inclusive=True, + cores_unit_price=5, + ram_unit_price=2, + ssd_unit_price=0.6, + hdd_unit_price=0.1, + ) + vm_pricing.save() + + +def undo_vm_pricing(apps, schema_editor): + """Deleting all entries for this model""" + + VMPricing = apps.get_model("datacenterlight", "VMPricing") + VMPricing.objects.all().delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('datacenterlight', '0019_auto_20180409_1923'), + ] + + operations = [ + migrations.RunPython( + create_default_pricing, + reverse_code=undo_vm_pricing + ), + ] From 1116812a994291c35493e12036db0fefb217289d Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 9 Apr 2018 21:40:03 +0200 Subject: [PATCH 07/67] Correct hdd price in VMPricing init --- datacenterlight/migrations/0020_auto_20180409_1928.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/migrations/0020_auto_20180409_1928.py b/datacenterlight/migrations/0020_auto_20180409_1928.py index 9a659acc..cea83a4c 100644 --- a/datacenterlight/migrations/0020_auto_20180409_1928.py +++ b/datacenterlight/migrations/0020_auto_20180409_1928.py @@ -22,7 +22,7 @@ def create_default_pricing(apps, schema_editor): cores_unit_price=5, ram_unit_price=2, ssd_unit_price=0.6, - hdd_unit_price=0.1, + hdd_unit_price=0.01, ) vm_pricing.save() From 588f513f2a1330a30829d3cb9f575f1acd814a39 Mon Sep 17 00:00:00 2001 From: PCoder Date: Thu, 12 Apr 2018 07:59:04 +0200 Subject: [PATCH 08/67] Remove initial VMPricing code from migration --- ...409_1923.py => 0019_auto_20180410_1948.py} | 2 +- .../migrations/0020_auto_20180409_1928.py | 48 ------------------- 2 files changed, 1 insertion(+), 49 deletions(-) rename datacenterlight/migrations/{0019_auto_20180409_1923.py => 0019_auto_20180410_1948.py} (97%) delete mode 100644 datacenterlight/migrations/0020_auto_20180409_1928.py diff --git a/datacenterlight/migrations/0019_auto_20180409_1923.py b/datacenterlight/migrations/0019_auto_20180410_1948.py similarity index 97% rename from datacenterlight/migrations/0019_auto_20180409_1923.py rename to datacenterlight/migrations/0019_auto_20180410_1948.py index 4766cb5e..64a13128 100644 --- a/datacenterlight/migrations/0019_auto_20180409_1923.py +++ b/datacenterlight/migrations/0019_auto_20180410_1948.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.9.4 on 2018-04-09 19:23 +# Generated by Django 1.9.4 on 2018-04-10 19:48 from __future__ import unicode_literals from django.db import migrations, models diff --git a/datacenterlight/migrations/0020_auto_20180409_1928.py b/datacenterlight/migrations/0020_auto_20180409_1928.py deleted file mode 100644 index cea83a4c..00000000 --- a/datacenterlight/migrations/0020_auto_20180409_1928.py +++ /dev/null @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.9.4 on 2018-04-09 19:28 -from __future__ import unicode_literals - -from django.db import migrations - -DEFAULT_VMPRICING_NAME='default' - - -def create_default_pricing(apps, schema_editor): - """ - Create default pricing - :param apps: - :param schema_editor: - :return: - """ - VMPricing = apps.get_model('datacenterlight', 'VMPricing') - if not VMPricing.objects.count(): - vm_pricing = VMPricing( - name=DEFAULT_VMPRICING_NAME, - vat_inclusive=True, - cores_unit_price=5, - ram_unit_price=2, - ssd_unit_price=0.6, - hdd_unit_price=0.01, - ) - vm_pricing.save() - - -def undo_vm_pricing(apps, schema_editor): - """Deleting all entries for this model""" - - VMPricing = apps.get_model("datacenterlight", "VMPricing") - VMPricing.objects.all().delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('datacenterlight', '0019_auto_20180409_1923'), - ] - - operations = [ - migrations.RunPython( - create_default_pricing, - reverse_code=undo_vm_pricing - ), - ] From d50f282057a1a73c0ad81c1ae2ab388e69697e24 Mon Sep 17 00:00:00 2001 From: PCoder Date: Thu, 12 Apr 2018 08:01:43 +0200 Subject: [PATCH 09/67] Add create_vm_pricing management command --- .../commands/create_default_vm_pricing.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 datacenterlight/management/commands/create_default_vm_pricing.py diff --git a/datacenterlight/management/commands/create_default_vm_pricing.py b/datacenterlight/management/commands/create_default_vm_pricing.py new file mode 100644 index 00000000..c1b36eea --- /dev/null +++ b/datacenterlight/management/commands/create_default_vm_pricing.py @@ -0,0 +1,36 @@ +from django.core.management.base import BaseCommand + +from datacenterlight.models import VMPricing + + +class Command(BaseCommand): + help = '''Creates default VMPricing object''' + DEFAULT_VMPRICING_NAME = 'default' + + def handle(self, *args, **options): + self.create_default_vm_pricing() + + def create_default_vm_pricing(self): + obj, created = VMPricing.objects.get_or_create( + name=self.DEFAULT_VMPRICING_NAME, + defaults={ + "vat_inclusive": True, + "cores_unit_price": 5, + "ram_unit_price": 2, + "ssd_unit_price": 0.6, + "hdd_unit_price": 0.01 + } + ) + + if created: + print( + 'Successfully created {} VMPricing object'.format( + self.DEFAULT_VMPRICING_NAME + ) + ) + else: + print( + '{} VMPricing exists already.'.format( + self.DEFAULT_VMPRICING_NAME + ) + ) From 3e1d5ba0e20e37c80a1dc66f7de42354cc3fd404 Mon Sep 17 00:00:00 2001 From: PCoder Date: Thu, 12 Apr 2018 08:03:12 +0200 Subject: [PATCH 10/67] Improve string representation of VMPricing object --- datacenterlight/models.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/datacenterlight/models.py b/datacenterlight/models.py index 3a376747..a67d108c 100644 --- a/datacenterlight/models.py +++ b/datacenterlight/models.py @@ -1,5 +1,9 @@ +import logging + from django.db import models +logger = logging.getLogger(__name__) + class VMTemplate(models.Model): name = models.CharField(max_length=50) @@ -32,14 +36,22 @@ class VMPricing(models.Model): ) def __str__(self): - return self.name + '-' + 'VAT' if self.vat_inclusive else 'NO_VAT' + return self.name + '-' + ' - '.join([ + '{}/Core'.format(self.cores_unit_price), + '{}/GB RAM'.format(self.ram_unit_price), + '{}/GB SSD'.format(self.ssd_unit_price), + '{}/GB HDD'.format(self.hdd_unit_price), + '{}% VAT'.format(self.vat_percentage) + if not self.vat_inclusive else 'NO_VAT', ] + ) @classmethod def get_default_pricing(cls): """ Returns the default pricing or None """ try: default_pricing = VMPricing.objects.get(name='default') - except: + except Exception as e: + logger.error(str(e)) default_pricing = None return default_pricing From 0ea9051de119fc937150e840110401bec5f532b0 Mon Sep 17 00:00:00 2001 From: PCoder Date: Thu, 12 Apr 2018 08:38:10 +0200 Subject: [PATCH 11/67] Change the name of the DCL Calculator Plugin DCL Caclulator Plugin -> DCL Calculator Section Plugin Note: We do not change the plugin name itself because it causes data loss --- datacenterlight/cms_plugins.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datacenterlight/cms_plugins.py b/datacenterlight/cms_plugins.py index 26ee9162..fbc32b00 100644 --- a/datacenterlight/cms_plugins.py +++ b/datacenterlight/cms_plugins.py @@ -75,8 +75,8 @@ class DCLSectionPromoPlugin(CMSPluginBase): @plugin_pool.register_plugin class DCLCalculatorPlugin(CMSPluginBase): module = "Datacenterlight" - name = "DCL Calculator Plugin" - model = DCLCalculatorPluginModel + name = "DCL Calculator Section Plugin" + model = DCLSectionPluginModel render_template = "datacenterlight/cms/calculator.html" cache = False allow_children = True From 283a0d25d183366ce3465891c693c58da1562a6a Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:31:55 +0200 Subject: [PATCH 12/67] Update get_vm_price method to use pricing defined in VMPricing --- utils/hosting_utils.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index 3c193ad7..d8c49b53 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -1,6 +1,7 @@ import logging from oca.pool import WrongIdError +from datacenterlight.models import VMPricing from hosting.models import UserHostingKey, VMDetail from opennebula_api.serializers import VirtualMachineSerializer @@ -49,14 +50,29 @@ def get_or_create_vm_detail(user, manager, vm_id): return vm_detail_obj -def get_vm_price(cpu, memory, disk_size): +def get_vm_price(cpu, memory, disk_size, hdd_size=0, pricing_name='default'): """ A helper function that computes price of a VM from given cpu, ram and ssd parameters :param cpu: Number of cores of the VM :param memory: RAM of the VM - :param disk_size: Disk space of the VM + :param disk_size: Disk space of the VM (SSD) + :param hdd_size: The HDD size + :param pricing_name: The pricing name to be used :return: The price of the VM """ - return (cpu * 5) + (memory * 2) + (disk_size * 0.6) + try: + pricing = VMPricing.objects.get(name=pricing_name) + except Exception as ex: + logger.error( + "Error getting VMPricing object for {pricing_name}." + "Details: {details}".format( + pricing_name=pricing_name, details=str(ex) + ) + ) + return None + return ((cpu * pricing.cores_unit_price) + + (memory * pricing.ram_unit_price) + + (disk_size * pricing.sdd_unit_price) + + (hdd_size * pricing.hdd_unit_price)) From 74393ac6ace4ab766e5a0abc43a423237a42a2b8 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:32:53 +0200 Subject: [PATCH 13/67] Optimize imports --- datacenterlight/cms_plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/cms_plugins.py b/datacenterlight/cms_plugins.py index fbc32b00..9e3376eb 100644 --- a/datacenterlight/cms_plugins.py +++ b/datacenterlight/cms_plugins.py @@ -6,7 +6,7 @@ from .cms_models import ( DCLFooterPluginModel, DCLLinkPluginModel, DCLNavbarDropdownPluginModel, DCLSectionIconPluginModel, DCLSectionImagePluginModel, DCLSectionPluginModel, DCLNavbarPluginModel, - DCLSectionPromoPluginModel, DCLCalculatorPluginModel + DCLSectionPromoPluginModel ) from .models import VMTemplate From 82a2014fa5b7b458b675045f5b0024c57e562d59 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:34:55 +0200 Subject: [PATCH 14/67] Pass vm_pricing context from default VMPricing object --- datacenterlight/cms_plugins.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/datacenterlight/cms_plugins.py b/datacenterlight/cms_plugins.py index 9e3376eb..9bb87bd8 100644 --- a/datacenterlight/cms_plugins.py +++ b/datacenterlight/cms_plugins.py @@ -8,7 +8,7 @@ from .cms_models import ( DCLSectionPluginModel, DCLNavbarPluginModel, DCLSectionPromoPluginModel ) -from .models import VMTemplate +from .models import VMTemplate, VMPricing @plugin_pool.register_plugin @@ -91,6 +91,8 @@ class DCLCalculatorPlugin(CMSPluginBase): context['templates'] = VMTemplate.objects.all() context['children_to_side'] = [] context['children_to_content'] = [] + context['vm_pricing'] = VMPricing.get_default_pricing() + if instance.child_plugin_instances is not None: context['children_to_content'].extend( instance.child_plugin_instances From aa55c1e868bdc5df1cb7f0956213c0b82cda30a8 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:37:06 +0200 Subject: [PATCH 15/67] Update main.js to compute total from the unitprice's defined in the window context --- datacenterlight/static/datacenterlight/js/main.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/datacenterlight/static/datacenterlight/js/main.js b/datacenterlight/static/datacenterlight/js/main.js index 6753695c..35f2b247 100644 --- a/datacenterlight/static/datacenterlight/js/main.js +++ b/datacenterlight/static/datacenterlight/js/main.js @@ -171,7 +171,18 @@ } function _calcPricing() { - var total = (cardPricing['cpu'].value * 5) + (2 * cardPricing['ram'].value) + (0.6 * cardPricing['storage'].value); + if(typeof window.coresUnitPrice === 'undefined'){ + window.coresUnitPrice = 5; + } + if(typeof window.ramUnitPrice === 'undefined'){ + window.coresUnitPrice = 2; + } + if(typeof window.ssdUnitPrice === 'undefined'){ + window.ssdUnitPrice = 0.6; + } + var total = (cardPricing['cpu'].value * window.coresUnitPrice) + + (cardPricing['ram'].value * window.ramUnitPrice) + + (cardPricing['storage'].value * window.ssdUnitPrice); total = parseFloat(total.toFixed(2)); $("#total").text(total); } From c738888ab2dcb118816607938eff3c61583e4c4f Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:39:01 +0200 Subject: [PATCH 16/67] Set vm unit price parameters from the passed context --- .../datacenterlight/includes/_calculator_form.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/datacenterlight/templates/datacenterlight/includes/_calculator_form.html b/datacenterlight/templates/datacenterlight/includes/_calculator_form.html index f38150bb..05201b11 100644 --- a/datacenterlight/templates/datacenterlight/includes/_calculator_form.html +++ b/datacenterlight/templates/datacenterlight/includes/_calculator_form.html @@ -1,4 +1,14 @@ {% load staticfiles i18n%} +{% if vm_pricing %} + +{% endif %}
{% csrf_token %}
@@ -7,9 +17,11 @@
15 CHF/{% trans "month" %} + {% if vm_pricing.vat_inclusive %}

{% trans "VAT included" %}

+ {% endif %}
@@ -78,5 +90,6 @@
+ From 558e187e11ac749ba8cb0bfecf7d5ade0a7672a7 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:39:41 +0200 Subject: [PATCH 17/67] Update text: including/excluding VAT --- datacenterlight/templates/datacenterlight/landing_payment.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datacenterlight/templates/datacenterlight/landing_payment.html b/datacenterlight/templates/datacenterlight/landing_payment.html index f21dc54b..b808e033 100644 --- a/datacenterlight/templates/datacenterlight/landing_payment.html +++ b/datacenterlight/templates/datacenterlight/landing_payment.html @@ -78,7 +78,7 @@

{% trans "Configuration"%} {{request.session.template.name}}


-

{%trans "Total" %}  ({%trans "including VAT" %}) {{request.session.specs.price|intcomma}} CHF/{% trans "Month" %}

+

{%trans "Total" %}  ({% if vm_pricing.vat_inclusive %}{%trans "including VAT" %}{% else %}{%trans "excluding VAT" %}{% endif %}) {{request.session.specs.price|intcomma}} CHF/{% trans "Month" %}

From 63a12ffe0636b5cdb1a11671e004044c0057201b Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:42:39 +0200 Subject: [PATCH 18/67] Use updated get_vm_price method --- datacenterlight/views.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index af3b774c..1089ceed 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -106,6 +106,7 @@ class IndexView(CreateView): storage = request.POST.get('storage') storage_field = forms.IntegerField(validators=[self.validate_storage]) template_id = int(request.POST.get('config')) + vm_pricing_name = request.POST.get('pricing_name') template = VMTemplate.objects.filter( opennebula_vm_template_id=template_id ).first() @@ -140,7 +141,10 @@ class IndexView(CreateView): return HttpResponseRedirect(referer_url + "#order_form") amount_to_be_charged = get_vm_price( - cpu=cores, memory=memory, disk_size=storage + cpu=cores, + memory=memory, + disk_size=storage, + pricing_name=vm_pricing_name ) specs = { 'cpu': cores, From 962c96067fa9b30d2f8093ad4c1602d9d06bba1f Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 20:55:39 +0200 Subject: [PATCH 19/67] Add get_vm_pricing_by_name VMPricing method --- datacenterlight/models.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/datacenterlight/models.py b/datacenterlight/models.py index a67d108c..86158394 100644 --- a/datacenterlight/models.py +++ b/datacenterlight/models.py @@ -45,6 +45,18 @@ class VMPricing(models.Model): if not self.vat_inclusive else 'NO_VAT', ] ) + @classmethod + def get_vm_pricing_by_name(cls, name): + try: + pricing = VMPricing.objects.get(name=name) + except Exception as e: + logger.error( + "Error getting VMPricing with name {name}. " + "Details: {details}".format(name=name, details=str(e)) + ) + pricing = VMPricing.get_default_pricing() + return pricing + @classmethod def get_default_pricing(cls): """ Returns the default pricing or None """ From e9a883bf2e45ec064c4a4307c74726a73fee2dde Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 20:57:10 +0200 Subject: [PATCH 20/67] Fix a bug: use ssd_unit_price instead of sdd_unit_price --- utils/hosting_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index d8c49b53..26fdeb94 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -74,5 +74,5 @@ def get_vm_price(cpu, memory, disk_size, hdd_size=0, pricing_name='default'): return None return ((cpu * pricing.cores_unit_price) + (memory * pricing.ram_unit_price) + - (disk_size * pricing.sdd_unit_price) + + (disk_size * pricing.ssd_unit_price) + (hdd_size * pricing.hdd_unit_price)) From 957cec00a0c7540ad6071af1f137ddc4c1c43980 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 20:59:31 +0200 Subject: [PATCH 21/67] Add get_vm_price_with_vat method --- utils/hosting_utils.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index 26fdeb94..1367138c 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -76,3 +76,38 @@ def get_vm_price(cpu, memory, disk_size, hdd_size=0, pricing_name='default'): (memory * pricing.ram_unit_price) + (disk_size * pricing.ssd_unit_price) + (hdd_size * pricing.hdd_unit_price)) + + +def get_vm_price_with_vat(cpu, memory, disk_size, hdd_size=0, + pricing_name='default'): + """ + A helper function that computes price of a VM from given cpu, ram and + ssd, hdd and the pricing parameters + + :param cpu: Number of cores of the VM + :param memory: RAM of the VM + :param disk_size: Disk space of the VM (SSD) + :param hdd_size: The HDD size + :param pricing_name: The pricing name to be used + :return: The a tuple containing the price of the VM and the VAT + """ + try: + pricing = VMPricing.objects.get(name=pricing_name) + except Exception as ex: + logger.error( + "Error getting VMPricing object for {pricing_name}." + "Details: {details}".format( + pricing_name=pricing_name, details=str(ex) + ) + ) + return None + + price = float((cpu * pricing.cores_unit_price) + + (memory * pricing.ram_unit_price) + + (disk_size * pricing.ssd_unit_price) + + (hdd_size * pricing.hdd_unit_price)) + if pricing.vat_inclusive: + vat = 0 + else: + vat = price * float(pricing.vat_percentage) * 0.01 + return price, vat From 23bd0fa147b5234caeb369f6bd9aefc4cac1846c Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 21:03:31 +0200 Subject: [PATCH 22/67] Pass context params to various landing templates --- datacenterlight/views.py | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 1089ceed..e2d28245 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -19,11 +19,11 @@ from hosting.models import HostingOrder from membership.models import CustomUser, StripeCustomer from opennebula_api.serializers import VMTemplateSerializer from utils.forms import BillingAddressForm, BillingAddressFormSignup -from utils.hosting_utils import get_vm_price +from utils.hosting_utils import get_vm_price, get_vm_price_with_vat from utils.stripe_utils import StripeUtils from utils.tasks import send_plain_email_task from .forms import ContactForm -from .models import VMTemplate +from .models import VMTemplate, VMPricing from .utils import get_cms_integration logger = logging.getLogger(__name__) @@ -93,7 +93,8 @@ class IndexView(CreateView): @cache_control(no_cache=True, must_revalidate=True, no_store=True) def get(self, request, *args, **kwargs): - for session_var in ['specs', 'user', 'billing_address_data']: + for session_var in ['specs', 'user', 'billing_address_data', + 'pricing_name']: if session_var in request.session: del request.session[session_var] return HttpResponseRedirect(reverse('datacenterlight:cms_index')) @@ -106,13 +107,30 @@ class IndexView(CreateView): storage = request.POST.get('storage') storage_field = forms.IntegerField(validators=[self.validate_storage]) template_id = int(request.POST.get('config')) - vm_pricing_name = request.POST.get('pricing_name') + pricing_name = request.POST.get('pricing_name') + vm_pricing = VMPricing.get_vm_pricing_by_name(pricing_name) + template = VMTemplate.objects.filter( opennebula_vm_template_id=template_id ).first() template_data = VMTemplateSerializer(template).data referer_url = request.META['HTTP_REFERER'] + if vm_pricing is None: + vm_pricing_name_msg = _( + "Incorrect pricing name. Please contact support" + "{support_email}".format( + support_email=settings.DCL_SUPPORT_FROM_ADDRESS + ) + ) + messages.add_message( + self.request, messages.ERROR, vm_pricing_name_msg, + extra_tags='pricing' + ) + return HttpResponseRedirect(referer_url + "#order_form") + else: + vm_pricing_name = vm_pricing.name + try: cores = cores_field.clean(cores) except ValidationError as err: @@ -140,7 +158,7 @@ class IndexView(CreateView): ) return HttpResponseRedirect(referer_url + "#order_form") - amount_to_be_charged = get_vm_price( + amount_to_be_charged, vat = get_vm_price_with_vat( cpu=cores, memory=memory, disk_size=storage, @@ -150,7 +168,10 @@ class IndexView(CreateView): 'cpu': cores, 'memory': memory, 'disk_size': storage, - 'price': amount_to_be_charged + 'price': amount_to_be_charged, + 'vat': vat, + 'total_price': amount_to_be_charged + vat, + 'pricing_name': vm_pricing_name } request.session['specs'] = specs request.session['template'] = template_data @@ -224,7 +245,10 @@ class PaymentOrderView(FormView): 'site_url': reverse('datacenterlight:index'), 'login_form': HostingUserLoginForm(prefix='login_form'), 'billing_address_form': billing_address_form, - 'cms_integration': get_cms_integration('default') + 'cms_integration': get_cms_integration('default'), + 'vm_pricing': VMPricing.get_vm_pricing_by_name( + self.request.session['specs']['pricing_name'] + ) }) return context @@ -493,7 +517,7 @@ class OrderConfirmationView(DetailView): stripe_subscription_obj.id, card_details_dict) for session_var in ['specs', 'template', 'billing_address', 'billing_address_data', - 'token', 'customer']: + 'token', 'customer', 'pricing_name']: if session_var in request.session: del request.session[session_var] From 40b984be1506e2eab0aca0eee0a99091522aaa76 Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 21:04:06 +0200 Subject: [PATCH 23/67] Update order_detail landing template --- .../templates/datacenterlight/order_detail.html | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/datacenterlight/templates/datacenterlight/order_detail.html b/datacenterlight/templates/datacenterlight/order_detail.html index 78ed43c0..20ff4db3 100644 --- a/datacenterlight/templates/datacenterlight/order_detail.html +++ b/datacenterlight/templates/datacenterlight/order_detail.html @@ -65,9 +65,15 @@ {% trans "Disk space" %}: {{vm.disk_size|intcomma}} GB

+ {% if vm.vat > 0 %} +

+ {% trans "VAT" %}: + {{vm.vat|floatformat|intcomma}} CHF +

+ {% endif %}

{% trans "Total" %} - {{vm.price|intcomma}} CHF + {{vm.total_price|floatformat|intcomma}} CHF

@@ -78,7 +84,7 @@ {% csrf_token %}
-
{% blocktrans with vm_price=request.session.specs.price %}By clicking "Place order" this plan will charge your credit card account with the fee of {{ vm_price }}CHF/month{% endblocktrans %}.
+
{% blocktrans with vm_total_price=vm.total_price|floatformat|intcomma %}By clicking "Place order" this plan will charge your credit card account with the fee of {{vm_total_price}} CHF/month{% endblocktrans %}.
@@ -84,7 +84,7 @@ {% csrf_token %}
-
{% blocktrans with vm_total_price=vm.total_price|floatformat|intcomma %}By clicking "Place order" this plan will charge your credit card account with the fee of {{vm_total_price}} CHF/month{% endblocktrans %}.
+
{% blocktrans with vm_total_price=vm.total_price|floatformat:2|intcomma %}By clicking "Place order" this plan will charge your credit card account with the fee of {{vm_total_price}} CHF/month{% endblocktrans %}.
From 602ad1b2c07986a3e65a48c4fbfedc4735f32c3e Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 16 Apr 2018 04:32:27 +0200 Subject: [PATCH 52/67] Reformat code --- hosting/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hosting/views.py b/hosting/views.py index ca40f205..56f9386a 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -1103,7 +1103,8 @@ class VirtualMachineView(LoginRequiredMixin, View): context = { 'virtual_machine': serializer.data, 'order': HostingOrder.objects.get( - vm_id=serializer.data['vm_id']) + vm_id=serializer.data['vm_id'] + ) } except Exception as ex: logger.debug("Exception generated {}".format(str(ex))) From 6cc40cb67f68c0da20370748a7fd1ec94fb38367 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 16 Apr 2018 04:34:40 +0200 Subject: [PATCH 53/67] virtual machine detail: show price upto 2 decimal places --- hosting/templates/hosting/virtual_machine_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hosting/templates/hosting/virtual_machine_detail.html b/hosting/templates/hosting/virtual_machine_detail.html index 61b16112..68894851 100644 --- a/hosting/templates/hosting/virtual_machine_detail.html +++ b/hosting/templates/hosting/virtual_machine_detail.html @@ -45,7 +45,7 @@

{% trans "Billing" %}

{% trans "Current Pricing" %}
-
{{order.price|floatformat|intcomma}} CHF/{% trans "Month" %}
+
{{order.price|floatformat:2|intcomma}} CHF/{% trans "Month" %}
{% trans "See Invoice" %}
From 731fef8ad9c8735f3b746a5e9caeacd63192ae93 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 16 Apr 2018 04:39:21 +0200 Subject: [PATCH 54/67] Show VAT details in hosting/order_details if it is set --- hosting/templates/hosting/order_detail.html | 6 ++++++ hosting/views.py | 1 + 2 files changed, 7 insertions(+) diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index f5ee80b6..099aaab8 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -127,6 +127,12 @@ {% trans "Disk space" %}: {{vm.disk_size}} GB

+ {% if vm.vat > 0 %} +

+ {% trans "VAT" %}: + {{vm.vat|floatformat:2|intcomma}} CHF +

+ {% endif %}

{% trans "Total" %} {{vm.price|intcomma}} CHF diff --git a/hosting/views.py b/hosting/views.py index 56f9386a..1f531784 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -756,6 +756,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView): pricing_name=(obj.vm_pricing.name if obj.vm_pricing else 'default') ) + context['vm']['vat'] = vat context['vm']['price'] = price + vat context['subscription_end_date'] = vm_detail.end_date() except VMDetail.DoesNotExist: From 1e768648217b8a2120161858e106a7e3372bce05 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 16 Apr 2018 04:46:43 +0200 Subject: [PATCH 55/67] Get vm price and vat and pass it to context --- hosting/views.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hosting/views.py b/hosting/views.py index 1f531784..88593969 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -766,6 +766,15 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView): ) vm = manager.get_vm(obj.vm_id) context['vm'] = VirtualMachineSerializer(vm).data + price, vat = get_vm_price_with_vat( + cpu=context['vm']['cores'], + ssd_size=context['vm']['disk_size'], + memory=context['vm']['memory'], + pricing_name=(obj.vm_pricing.name + if obj.vm_pricing else 'default') + ) + context['vm']['vat'] = vat + context['vm']['price'] = price + vat except WrongIdError: messages.error( self.request, From 3fca9dbb0df0d564f73a111d13c9c8eae825836f Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 16 Apr 2018 05:03:48 +0200 Subject: [PATCH 56/67] Fix a bug creating hostingorder --- datacenterlight/tasks.py | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/datacenterlight/tasks.py b/datacenterlight/tasks.py index c97c6c54..db479b43 100644 --- a/datacenterlight/tasks.py +++ b/datacenterlight/tasks.py @@ -97,30 +97,22 @@ def create_vm_task(self, vm_template_id, user, specs, template, if vm_id is None: raise Exception("Could not create VM") - if 'pricing_name' in specs: - vm_pricing = VMPricing.get_vm_pricing_by_name( - name=specs['pricing_name'] - ) - # Create a Hosting Order - order = HostingOrder.create( - price=final_price, - vm_id=vm_id, - customer=customer, - billing_address=billing_address, - vm_pricing=vm_pricing - ) - else: - # Create a Hosting Order - order = HostingOrder.create( - price=final_price, - vm_id=vm_id, - customer=customer, - billing_address=billing_address - ) + vm_pricing = VMPricing.get_vm_pricing_by_name( + name=specs['pricing_name'] + ) if 'pricing_name' in specs else VMPricing.get_default_pricing() + # Create a Hosting Order + order = HostingOrder.create( + price=final_price, + vm_id=vm_id, + customer=customer, + billing_address=billing_address, + vm_pricing=vm_pricing + ) # Create a Hosting Bill HostingBill.create( - customer=customer, billing_address=billing_address) + customer=customer, billing_address=billing_address + ) # Create Billing Address for User if he does not have one if not customer.user.billing_addresses.count(): From d15a4da84061798ca824dd271dad704459e8d159 Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Tue, 17 Apr 2018 18:03:10 +0200 Subject: [PATCH 57/67] Check if child plugin instances exist before looping over them --- datacenterlight/cms_plugins.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/datacenterlight/cms_plugins.py b/datacenterlight/cms_plugins.py index 2ad07249..6533adc7 100644 --- a/datacenterlight/cms_plugins.py +++ b/datacenterlight/cms_plugins.py @@ -92,13 +92,14 @@ class DCLCalculatorPlugin(CMSPluginBase): context['children_to_side'] = [] context['children_to_content'] = [] pricing_plugin_model = None - for child in instance.child_plugin_instances: - if child.__class__.__name__ == 'DCLCustomPricingModel': - # The second clause is just to make sure we pick up the most - # recent CustomPricing, if more than one is present - if (pricing_plugin_model is None or child.pricing_id > - pricing_plugin_model.model.pricing_id): - pricing_plugin_model = child + if instance.child_plugin_instances: + for child in instance.child_plugin_instances: + if child.__class__.__name__ == 'DCLCustomPricingModel': + # The second clause is just to make sure we pick up the + # most recent CustomPricing, if more than one is present + if (pricing_plugin_model is None or child.pricing_id > + pricing_plugin_model.model.pricing_id): + pricing_plugin_model = child if pricing_plugin_model: context['vm_pricing'] = VMPricing.get_vm_pricing_by_name( From e4e7d93275c2306154704152e9ce1b06c3d5c282 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 17 Apr 2018 20:50:41 +0200 Subject: [PATCH 58/67] Fix flake8 errors --- datacenterlight/admin.py | 1 + utils/hosting_utils.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/datacenterlight/admin.py b/datacenterlight/admin.py index 3e5927e8..28adf28b 100644 --- a/datacenterlight/admin.py +++ b/datacenterlight/admin.py @@ -7,5 +7,6 @@ from .models import VMPricing class CMSIntegrationAdmin(PlaceholderAdminMixin, admin.ModelAdmin): list_display = ('name', 'domain') + admin.site.register(CMSIntegration, CMSIntegrationAdmin) admin.site.register(VMPricing) diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index 87b69534..c267cc0b 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -74,9 +74,9 @@ def get_vm_price(cpu, memory, disk_size, hdd_size=0, pricing_name='default'): ) return None price = ((decimal.Decimal(cpu) * pricing.cores_unit_price) + - (decimal.Decimal(memory) * pricing.ram_unit_price) + - (decimal.Decimal(disk_size) * pricing.ssd_unit_price) + - (decimal.Decimal(hdd_size) * pricing.hdd_unit_price)) + (decimal.Decimal(memory) * pricing.ram_unit_price) + + (decimal.Decimal(disk_size) * pricing.ssd_unit_price) + + (decimal.Decimal(hdd_size) * pricing.hdd_unit_price)) cents = decimal.Decimal('.01') price = price.quantize(cents, decimal.ROUND_HALF_UP) return float(price) From a50fa77c8a9f7598b7a12e7741ad9b02a8236b13 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 17 Apr 2018 21:36:08 +0200 Subject: [PATCH 59/67] Update get_vm_price_with_vat: Return vat_percentage also --- utils/hosting_utils.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/utils/hosting_utils.py b/utils/hosting_utils.py index c267cc0b..04ed658a 100644 --- a/utils/hosting_utils.py +++ b/utils/hosting_utils.py @@ -93,7 +93,8 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0, :param ssd_size: Disk space of the VM (SSD) :param hdd_size: The HDD size :param pricing_name: The pricing name to be used - :return: The a tuple containing the price of the VM and the VAT + :return: The a tuple containing the price of the VM, the VAT and the + VAT percentage """ try: pricing = VMPricing.objects.get(name=pricing_name) @@ -112,10 +113,12 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0, (decimal.Decimal(hdd_size) * pricing.hdd_unit_price)) if pricing.vat_inclusive: vat = decimal.Decimal(0) + vat_percent = decimal.Decimal(0) else: vat = price * pricing.vat_percentage * decimal.Decimal(0.01) + vat_percent = pricing.vat_percentage cents = decimal.Decimal('.01') price = price.quantize(cents, decimal.ROUND_HALF_UP) vat = vat.quantize(cents, decimal.ROUND_HALF_UP) - return float(price), float(vat) + return float(price), float(vat), float(vat_percent) From c2513dc7c3527afc4f94cb577062a47c9a906d74 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 17 Apr 2018 21:38:28 +0200 Subject: [PATCH 60/67] Show vat_percent and subtotal for vat exclusive case --- datacenterlight/templates/datacenterlight/order_detail.html | 6 +++++- datacenterlight/views.py | 3 ++- hosting/views.py | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/datacenterlight/templates/datacenterlight/order_detail.html b/datacenterlight/templates/datacenterlight/order_detail.html index f26bc450..543f3934 100644 --- a/datacenterlight/templates/datacenterlight/order_detail.html +++ b/datacenterlight/templates/datacenterlight/order_detail.html @@ -67,7 +67,11 @@

{% if vm.vat > 0 %}

- {% trans "VAT" %}: + {% trans "Subtotal" %}: + {{vm.price|floatformat:2|intcomma}} CHF +

+

+ {% trans "VAT" %} ({{ vm.vat_percent|floatformat:2|intcomma }}%): {{vm.vat|floatformat:2|intcomma}} CHF

{% endif %} diff --git a/datacenterlight/views.py b/datacenterlight/views.py index 87a0e660..cccd4277 100644 --- a/datacenterlight/views.py +++ b/datacenterlight/views.py @@ -158,7 +158,7 @@ class IndexView(CreateView): ) return HttpResponseRedirect(referer_url + "#order_form") - price, vat = get_vm_price_with_vat( + price, vat, vat_percent = get_vm_price_with_vat( cpu=cores, memory=memory, ssd_size=storage, @@ -170,6 +170,7 @@ class IndexView(CreateView): 'disk_size': storage, 'price': price, 'vat': vat, + 'vat_percent': vat_percent, 'total_price': price + vat, 'pricing_name': vm_pricing_name } diff --git a/hosting/views.py b/hosting/views.py index 88593969..a7aeca1e 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -749,7 +749,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView): context['vm'] = vm_detail.__dict__ context['vm']['name'] = '{}-{}'.format( context['vm']['configuration'], context['vm']['vm_id']) - price, vat = get_vm_price_with_vat( + price, vat, vat_percent = get_vm_price_with_vat( cpu=context['vm']['cores'], ssd_size=context['vm']['disk_size'], memory=context['vm']['memory'], @@ -766,7 +766,7 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView): ) vm = manager.get_vm(obj.vm_id) context['vm'] = VirtualMachineSerializer(vm).data - price, vat = get_vm_price_with_vat( + price, vat, vat_percent = get_vm_price_with_vat( cpu=context['vm']['cores'], ssd_size=context['vm']['disk_size'], memory=context['vm']['memory'], From a454cd252280c383da0b475433773340c1b73abc Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 17 Apr 2018 21:38:53 +0200 Subject: [PATCH 61/67] Update datacenterlight's django.po --- datacenterlight/locale/de/LC_MESSAGES/django.po | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index 3dc4650b..b937805c 100644 --- a/datacenterlight/locale/de/LC_MESSAGES/django.po +++ b/datacenterlight/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-15 23:37+0000\n" +"POT-Creation-Date: 2018-04-17 19:26+0000\n" "PO-Revision-Date: 2018-03-30 23:22+0000\n" "Last-Translator: b'Anonymous User '\n" "Language-Team: LANGUAGE \n" @@ -97,6 +97,7 @@ msgstr "Deine E-Mail-Adresse" msgid "Password" msgstr "Passwort" +#, python-format msgid "" "You can reset your password here." @@ -379,15 +380,20 @@ msgstr "Bestellungsübersicht" msgid "Product" msgstr "Produkt" +#, fuzzy +msgid "Subtotal" +msgstr "Zwischensumme" + msgid "VAT" msgstr "Mehrwertsteuer" +#, python-format msgid "" "By clicking \"Place order\" this plan will charge your credit card account " "with the fee of %(vm_total_price)s CHF/month" msgstr "" -"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit %(vm_total_price)s CHF " -"pro Monat belastet" +"Wenn Du \"bestellen\" auswählst, wird Deine Kreditkarte mit " +"%(vm_total_price)s CHF pro Monat belastet" msgid "Place order" msgstr "Bestellen" From 4c21110c00807b5c44849768c4bcaac174f13b50 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 17 Apr 2018 21:47:02 +0200 Subject: [PATCH 62/67] Remove fuzzy and python-format --- datacenterlight/locale/de/LC_MESSAGES/django.po | 2 -- 1 file changed, 2 deletions(-) diff --git a/datacenterlight/locale/de/LC_MESSAGES/django.po b/datacenterlight/locale/de/LC_MESSAGES/django.po index b937805c..50dbfbe8 100644 --- a/datacenterlight/locale/de/LC_MESSAGES/django.po +++ b/datacenterlight/locale/de/LC_MESSAGES/django.po @@ -380,14 +380,12 @@ msgstr "Bestellungsübersicht" msgid "Product" msgstr "Produkt" -#, fuzzy msgid "Subtotal" msgstr "Zwischensumme" msgid "VAT" msgstr "Mehrwertsteuer" -#, python-format msgid "" "By clicking \"Place order\" this plan will charge your credit card account " "with the fee of %(vm_total_price)s CHF/month" From 2ac1ac7d9728db5ec30e434aae0495c19385c3a2 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 17 Apr 2018 22:20:36 +0200 Subject: [PATCH 63/67] Add subtotal and VAT to hosting order detail too --- hosting/templates/hosting/order_detail.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 099aaab8..45b68cae 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -129,13 +129,17 @@

{% if vm.vat > 0 %}

- {% trans "VAT" %}: + {% trans "Subtotal" %}: + {{vm.price|floatformat:2|intcomma}} CHF +

+

+ {% trans "VAT" %} ({{ vm.vat_percent|floatformat:2|intcomma }}%): {{vm.vat|floatformat:2|intcomma}} CHF

{% endif %}

{% trans "Total" %} - {{vm.price|intcomma}} CHF + {% if vm.total_price %}{{vm.total_price|floatformat:2|intcomma}}{% else %}{{vm.price|floatformat:2|intcomma}}{% endif %} CHF

From 36c0b9a0a67a474dcb395dafdc75cd3329312e74 Mon Sep 17 00:00:00 2001 From: PCoder Date: Tue, 17 Apr 2018 22:23:46 +0200 Subject: [PATCH 64/67] Differentiate price and total_price in hosting order_detail --- hosting/views.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hosting/views.py b/hosting/views.py index a7aeca1e..ec36836a 100644 --- a/hosting/views.py +++ b/hosting/views.py @@ -757,7 +757,9 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView): if obj.vm_pricing else 'default') ) context['vm']['vat'] = vat - context['vm']['price'] = price + vat + context['vm']['price'] = price + context['vm']['vat_percent'] = vat_percent + context['vm']['total_price'] = price + vat context['subscription_end_date'] = vm_detail.end_date() except VMDetail.DoesNotExist: try: @@ -774,7 +776,9 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView): if obj.vm_pricing else 'default') ) context['vm']['vat'] = vat - context['vm']['price'] = price + vat + context['vm']['price'] = price + context['vm']['vat_percent'] = vat_percent + context['vm']['total_price'] = price + vat except WrongIdError: messages.error( self.request, From 4e3211b62fb08ae6835f71a2fba6aae015bb83ed Mon Sep 17 00:00:00 2001 From: PCoder Date: Wed, 18 Apr 2018 21:37:12 +0200 Subject: [PATCH 65/67] Make total and subtotal texts bold --- datacenterlight/templates/datacenterlight/order_detail.html | 4 ++-- hosting/templates/hosting/order_detail.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/datacenterlight/templates/datacenterlight/order_detail.html b/datacenterlight/templates/datacenterlight/order_detail.html index 543f3934..95bfa3c6 100644 --- a/datacenterlight/templates/datacenterlight/order_detail.html +++ b/datacenterlight/templates/datacenterlight/order_detail.html @@ -67,7 +67,7 @@

{% if vm.vat > 0 %}

- {% trans "Subtotal" %}: + {% trans "Subtotal" %}: {{vm.price|floatformat:2|intcomma}} CHF

@@ -76,7 +76,7 @@

{% endif %}

- {% trans "Total" %} + {% trans "Total" %} {{vm.total_price|floatformat:2|intcomma}} CHF

diff --git a/hosting/templates/hosting/order_detail.html b/hosting/templates/hosting/order_detail.html index 45b68cae..2568aafc 100644 --- a/hosting/templates/hosting/order_detail.html +++ b/hosting/templates/hosting/order_detail.html @@ -129,7 +129,7 @@

{% if vm.vat > 0 %}

- {% trans "Subtotal" %}: + {% trans "Subtotal" %}: {{vm.price|floatformat:2|intcomma}} CHF

@@ -138,7 +138,7 @@

{% endif %}

- {% trans "Total" %} + {% trans "Total" %} {% if vm.total_price %}{{vm.total_price|floatformat:2|intcomma}}{% else %}{{vm.price|floatformat:2|intcomma}}{% endif %} CHF

From 1e97d0ba380a382a92f6e76a6e2014fb84b36141 Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 20 Apr 2018 17:51:46 +0530 Subject: [PATCH 66/67] Update cms_plugins.py --- datacenterlight/cms_plugins.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/datacenterlight/cms_plugins.py b/datacenterlight/cms_plugins.py index 6533adc7..19dc0b39 100644 --- a/datacenterlight/cms_plugins.py +++ b/datacenterlight/cms_plugins.py @@ -89,10 +89,12 @@ class DCLCalculatorPlugin(CMSPluginBase): context, instance, placeholder ) context['templates'] = VMTemplate.objects.all() - context['children_to_side'] = [] context['children_to_content'] = [] pricing_plugin_model = None - if instance.child_plugin_instances: + if instance.child_plugin_instances is not None: + context['children_to_content'].extend( + instance.child_plugin_instances + ) for child in instance.child_plugin_instances: if child.__class__.__name__ == 'DCLCustomPricingModel': # The second clause is just to make sure we pick up the @@ -108,10 +110,6 @@ class DCLCalculatorPlugin(CMSPluginBase): else: context['vm_pricing'] = VMPricing.get_default_pricing() - if instance.child_plugin_instances is not None: - context['children_to_content'].extend( - instance.child_plugin_instances - ) return context From 8f6260b063269d127dbfff2eda68ad930672c77d Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 20 Apr 2018 17:54:23 +0530 Subject: [PATCH 67/67] Update _calculator_form.html --- .../includes/_calculator_form.html | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/datacenterlight/templates/datacenterlight/includes/_calculator_form.html b/datacenterlight/templates/datacenterlight/includes/_calculator_form.html index 05201b11..e3fe8676 100644 --- a/datacenterlight/templates/datacenterlight/includes/_calculator_form.html +++ b/datacenterlight/templates/datacenterlight/includes/_calculator_form.html @@ -1,14 +1,16 @@ {% load staticfiles i18n%} + {% if vm_pricing %} - + {% endif %} +
{% csrf_token %}