From 28de423a1475f1fc4f167311be292a4ab41d34eb Mon Sep 17 00:00:00 2001 From: PCoder Date: Fri, 6 Apr 2018 00:51:44 +0200 Subject: [PATCH 01/75] 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/75] 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/75] 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/75] 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/75] 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/75] 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/75] 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 be72b9628cdb0ef1895c79fc18e44d6d9da7221d Mon Sep 17 00:00:00 2001 From: "M.Ravi" Date: Tue, 10 Apr 2018 13:21:58 +0200 Subject: [PATCH 08/75] Add djangocms_blog namespace and urls --- dynamicweb/urls.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dynamicweb/urls.py b/dynamicweb/urls.py index ec43d1a5..edb7e3b7 100644 --- a/dynamicweb/urls.py +++ b/dynamicweb/urls.py @@ -67,6 +67,7 @@ urlpatterns += i18n_patterns( include('ungleich_page.urls', namespace='ungleich_page'), name='ungleich_page'), + url(r'^blog/', include('djangocms_blog.urls', namespace='djangocms_blog')), ) urlpatterns += [ From c0c2dc5c37aef76021d490bf62d62f5c1f00ee1d Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Thu, 12 Apr 2018 09:26:30 +0530 Subject: [PATCH 09/75] larger image used in email --- .../datacenterlight/img/datacenterlight.png | Bin 5135 -> 5897 bytes .../emails/user_activation.html | 2 +- .../datacenterlight/emails/welcome_user.html | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/datacenterlight/static/datacenterlight/img/datacenterlight.png b/datacenterlight/static/datacenterlight/img/datacenterlight.png index 1ae6ff53c6e1876d7ff5c2dc598020e32774f37e..9097af9bfa6894bb2da2fe71d2360b5215718ddd 100644 GIT binary patch literal 5897 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 DnJB5u diff --git a/datacenterlight/templates/datacenterlight/emails/user_activation.html b/datacenterlight/templates/datacenterlight/emails/user_activation.html index 6e70100f..403482a4 100644 --- a/datacenterlight/templates/datacenterlight/emails/user_activation.html +++ b/datacenterlight/templates/datacenterlight/emails/user_activation.html @@ -14,7 +14,7 @@ diff --git a/datacenterlight/templates/datacenterlight/emails/welcome_user.html b/datacenterlight/templates/datacenterlight/emails/welcome_user.html index e947ac97..f18f9750 100644 --- a/datacenterlight/templates/datacenterlight/emails/welcome_user.html +++ b/datacenterlight/templates/datacenterlight/emails/welcome_user.html @@ -14,7 +14,7 @@
- +
From 588f513f2a1330a30829d3cb9f575f1acd814a39 Mon Sep 17 00:00:00 2001 From: PCoder Date: Thu, 12 Apr 2018 07:59:04 +0200 Subject: [PATCH 10/75] 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 11/75] 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 12/75] 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 13/75] 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 479d6fbd4fa13c62c15dd98b061f591c7f7fc4ed Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 13 Apr 2018 15:45:06 +0530 Subject: [PATCH 14/75] change promo link color --- datacenterlight/static/datacenterlight/css/landing-page.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/datacenterlight/static/datacenterlight/css/landing-page.css b/datacenterlight/static/datacenterlight/css/landing-page.css index 33bf6425..f1d110d3 100755 --- a/datacenterlight/static/datacenterlight/css/landing-page.css +++ b/datacenterlight/static/datacenterlight/css/landing-page.css @@ -1231,6 +1231,10 @@ footer { background-position: center; } +.promo-section.promo-with-bg a { + color: #87B6EA; +} + .promo-section h3 { font-weight: 700; font-size: 36px; From ca480ce9c8e9775bc22addf480737236f71e033f Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 13 Apr 2018 16:23:17 +0530 Subject: [PATCH 15/75] darker shade for hover --- datacenterlight/static/datacenterlight/css/landing-page.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/datacenterlight/static/datacenterlight/css/landing-page.css b/datacenterlight/static/datacenterlight/css/landing-page.css index f1d110d3..8e9f2c2d 100755 --- a/datacenterlight/static/datacenterlight/css/landing-page.css +++ b/datacenterlight/static/datacenterlight/css/landing-page.css @@ -1235,6 +1235,11 @@ footer { color: #87B6EA; } +.promo-section.promo-with-bg a:hover, +.promo-section.promo-with-bg a:focus { + color: #77a6da; +} + .promo-section h3 { font-weight: 700; font-size: 36px; From 403f9b5a08119e2247b6afee0887fbafa3c4da54 Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 13 Apr 2018 17:55:08 +0530 Subject: [PATCH 16/75] change logo in hosting emails --- hosting/templates/hosting/emails/new_booked_vm.html | 2 +- hosting/templates/hosting/emails/password_reset_email.html | 2 +- hosting/templates/hosting/emails/vm_canceled.html | 2 +- hosting/templates/hosting/emails/vm_charged.html | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hosting/templates/hosting/emails/new_booked_vm.html b/hosting/templates/hosting/emails/new_booked_vm.html index b80aebe0..7bc0cf3a 100644 --- a/hosting/templates/hosting/emails/new_booked_vm.html +++ b/hosting/templates/hosting/emails/new_booked_vm.html @@ -14,7 +14,7 @@
- +
diff --git a/hosting/templates/hosting/emails/password_reset_email.html b/hosting/templates/hosting/emails/password_reset_email.html index 57831228..c7c1310a 100644 --- a/hosting/templates/hosting/emails/password_reset_email.html +++ b/hosting/templates/hosting/emails/password_reset_email.html @@ -14,7 +14,7 @@
- +
diff --git a/hosting/templates/hosting/emails/vm_canceled.html b/hosting/templates/hosting/emails/vm_canceled.html index 3142f6bc..9c2ec4c2 100644 --- a/hosting/templates/hosting/emails/vm_canceled.html +++ b/hosting/templates/hosting/emails/vm_canceled.html @@ -14,7 +14,7 @@
- +
diff --git a/hosting/templates/hosting/emails/vm_charged.html b/hosting/templates/hosting/emails/vm_charged.html index 33568d05..3a6c4f95 100644 --- a/hosting/templates/hosting/emails/vm_charged.html +++ b/hosting/templates/hosting/emails/vm_charged.html @@ -74,7 +74,7 @@
- +
@@ -100,7 +100,7 @@ From 7d05ab5f5f31e0abe54ba38b2c28b0a63827d5ba Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 13 Apr 2018 18:53:21 +0530 Subject: [PATCH 17/75] Update Changelog --- Changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog b/Changelog index 8442789d..912a466f 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,6 @@ +next: + * #4367: [dcl] email logo resolution fix + * #4376: [cms] dcl promo section plugin link color changed to brighter shade 1.6.5: 2018-04-08 * #4396: [ungleich] add favicon to ungleich blog * #4327: [dcl] fix navbar logo repeat From 3f4156ed8e64bcd9f8dd511eeb7593db9cccabf2 Mon Sep 17 00:00:00 2001 From: PCoder Date: Fri, 13 Apr 2018 20:52:58 +0200 Subject: [PATCH 18/75] Update Changelog --- Changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog b/Changelog index 912a466f..46b2534b 100644 --- a/Changelog +++ b/Changelog @@ -1,4 +1,5 @@ next: + * bgfix: [all] Make /blog available on all domains * #4367: [dcl] email logo resolution fix * #4376: [cms] dcl promo section plugin link color changed to brighter shade 1.6.5: 2018-04-08 From 283a0d25d183366ce3465891c693c58da1562a6a Mon Sep 17 00:00:00 2001 From: PCoder Date: Sun, 15 Apr 2018 13:31:55 +0200 Subject: [PATCH 19/75] 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 20/75] 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 21/75] 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 22/75] 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 23/75] 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 24/75] 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 25/75] 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 26/75] 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 27/75] 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 28/75] 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 29/75] 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 30/75] 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 5738dc8e1b5b2d2323a2e6a4c20f9039511a7715 Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 16 Apr 2018 04:31:42 +0200 Subject: [PATCH 58/75] Virtual machine detail: use hostingorder for obtaining the price, rather than the serializer --- 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 b77e1dca..61b16112 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" %}
-
{{virtual_machine.price|floatformat|intcomma}} CHF/{% trans "Month" %}
+
{{order.price|floatformat|intcomma}} CHF/{% trans "Month" %}
{% trans "See Invoice" %}
From 602ad1b2c07986a3e65a48c4fbfedc4735f32c3e Mon Sep 17 00:00:00 2001 From: PCoder Date: Mon, 16 Apr 2018 04:32:27 +0200 Subject: [PATCH 59/75] 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 60/75] 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 61/75] 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 62/75] 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 63/75] 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 64/75] 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 65/75] 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 66/75] 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 67/75] 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 68/75] 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 69/75] 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 70/75] 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 71/75] 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 72/75] 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 da13903ba2ebb1c83b784cf4fb14e5eb1b4170c0 Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 20 Apr 2018 16:42:50 +0530 Subject: [PATCH 73/75] remove padding --- datacenterlight/static/datacenterlight/css/header-slider.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/datacenterlight/static/datacenterlight/css/header-slider.css b/datacenterlight/static/datacenterlight/css/header-slider.css index e21e2b49..d01f02a7 100644 --- a/datacenterlight/static/datacenterlight/css/header-slider.css +++ b/datacenterlight/static/datacenterlight/css/header-slider.css @@ -120,6 +120,11 @@ .header_slider .intro-cap { font-size: 3.25em; } + + .header_slider > .carousel .item .container { + padding-left: 0; + padding-right: 0; + } } .header_slider .intro_lead { From 1e97d0ba380a382a92f6e76a6e2014fb84b36141 Mon Sep 17 00:00:00 2001 From: Arvind Tiwari Date: Fri, 20 Apr 2018 17:51:46 +0530 Subject: [PATCH 74/75] 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 75/75] 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 %}
- logo + logo
- Your virtual machine {{vm.name}} subscription has been charged,
you can view your invoice clicking on the button below. + Your virtual machine {{vm.name}} subscription has been charged,
you can view your invoice clicking on the button below.
{{ order.id }} {{ order.created_at | date:"M d, Y H:i" }}{{ order.price|intcomma }}{{ order.price|floatformat:2|intcomma }} {% trans 'See Invoice' %}