Merge tag '2.10.2' into branch-2.10.3b
Introduce base price for VMs and let admins add stripe_coupon_id
This commit is contained in:
		
				commit
				
					
						580960548e
					
				
			
		
					 12 changed files with 62 additions and 24 deletions
				
			
		|  | @ -1,3 +1,10 @@ | |||
| 2.10.5: 2020-03-17 | ||||
|    * Introduce base price for VMs and let admins add stripe_coupon_id (MR!730) | ||||
|    Notes for deployment: | ||||
|    1. Add env variable `VM_BASE_PRICE` | ||||
|    2. Migrate datacenterlight app. This introduces the stripe_coupon_code field in the VMPricing. | ||||
|    3. Create a coupon in stripe with the desired value and note down the stripe's coupon id | ||||
|    4. Update the discount amount and set the corresponding coupon id in the admin | ||||
| 2.10.3b: 2020-03-05 | ||||
|    * #7773: Use username for communicating with opennebula all the time | ||||
| 2.10.2b: 2020-02-25 | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| from cms.plugin_base import CMSPluginBase | ||||
| from cms.plugin_pool import plugin_pool | ||||
| from django.conf import settings | ||||
| 
 | ||||
| from .cms_models import ( | ||||
|     DCLBannerItemPluginModel, DCLBannerListPluginModel, DCLContactPluginModel, | ||||
|  | @ -100,6 +101,7 @@ class DCLCalculatorPlugin(CMSPluginBase): | |||
|                 vm_type=instance.vm_type | ||||
|             ).order_by('name') | ||||
|         context['instance'] = instance | ||||
|         context['vm_base_price'] = settings.VM_BASE_PRICE | ||||
|         context['min_ram'] = 0.5 if instance.enable_512mb_ram else 1 | ||||
|         return context | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,20 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by Django 1.9.4 on 2020-02-04 03:16 | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('datacenterlight', '0030_dclnavbarpluginmodel_show_non_transparent_navbar_always'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='vmpricing', | ||||
|             name='stripe_coupon_id', | ||||
|             field=models.CharField(blank=True, max_length=255, null=True), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -54,6 +54,7 @@ class VMPricing(models.Model): | |||
|     discount_amount = models.DecimalField( | ||||
|         max_digits=6, decimal_places=2, default=0 | ||||
|     ) | ||||
|     stripe_coupon_id = models.CharField(max_length=255, null=True, blank=True) | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         display_str = self.name + ' => ' + ' - '.join([ | ||||
|  |  | |||
|  | @ -225,8 +225,8 @@ | |||
|         } | ||||
|         var total = (cardPricing['cpu'].value * window.coresUnitPrice) + | ||||
|                     (cardPricing['ram'].value * window.ramUnitPrice) + | ||||
|                     (cardPricing['storage'].value * window.ssdUnitPrice) - | ||||
|                     window.discountAmount; | ||||
|                     (cardPricing['storage'].value * window.ssdUnitPrice) + | ||||
|                     window.vmBasePrice - window.discountAmount; | ||||
|         total = parseFloat(total.toFixed(2)); | ||||
|         $("#total").text(total); | ||||
|     } | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <div class="price-calc-section"> | ||||
|   <div class="card"> | ||||
|     {% include "datacenterlight/includes/_calculator_form.html" with vm_pricing=instance.pricing %} | ||||
|     {% include "datacenterlight/includes/_calculator_form.html" with vm_pricing=instance.pricing vm_base_price=vm_base_price %} | ||||
|   </div> | ||||
| </div> | ||||
|  | @ -9,6 +9,7 @@ | |||
|         window.ssdUnitPrice = {{vm_pricing.ssd_unit_price|default:0}}; | ||||
|         window.hddUnitPrice = {{vm_pricing.hdd_unit_price|default:0}}; | ||||
|         window.discountAmount = {{vm_pricing.discount_amount|default:0}}; | ||||
|         window.vmBasePrice = {{vm_base_price|default:0}}; | ||||
|         window.minRam = {{min_ram}}; | ||||
|         window.minRamErr = '{% blocktrans with min_ram=min_ram %}Please enter a value in range {{min_ram}} - 200.{% endblocktrans %}'; | ||||
|     </script> | ||||
|  |  | |||
|  | @ -678,9 +678,9 @@ class OrderConfirmationView(DetailView, FormView): | |||
|                 vm_specs["vat_percent"] = vat_percent | ||||
|                 vm_specs["vat_validation_status"] = request.session["vat_validation_status"] if "vat_validation_status" in request.session else "" | ||||
|             vm_specs["vat_country"] = user_vat_country | ||||
|             vm_specs["price_with_vat"] = round_up(price * (1 + vm_specs["vat_percent"] * 0.01), 2) | ||||
|             vm_specs["price_after_discount"] = round_up(price - discount['amount'], 2) | ||||
|             vm_specs["price_after_discount_with_vat"] = round_up((price - discount['amount']) * (1 + vm_specs["vat_percent"] * 0.01), 2) | ||||
|             vm_specs["price_with_vat"] = round(price * (1 + vm_specs["vat_percent"] * 0.01), 2) | ||||
|             vm_specs["price_after_discount"] = round(price - discount['amount'], 2) | ||||
|             vm_specs["price_after_discount_with_vat"] = round((price - discount['amount']) * (1 + vm_specs["vat_percent"] * 0.01), 2) | ||||
|             discount["amount_with_vat"] = round(vm_specs["price_with_vat"] - vm_specs["price_after_discount_with_vat"], 2) | ||||
|             vm_specs["total_price"] = vm_specs["price_after_discount_with_vat"] | ||||
|             vm_specs["discount"] = discount | ||||
|  | @ -933,11 +933,11 @@ class OrderConfirmationView(DetailView, FormView): | |||
|             subscription_result = stripe_utils.subscribe_customer_to_plan( | ||||
|                 stripe_api_cus_id, | ||||
|                 [{"plan": stripe_plan.get('response_object').stripe_plan_id}], | ||||
|                 coupon='ipv6-discount-8chf' if ( | ||||
|                     'name' in discount and | ||||
|                     discount['name'] is not None and | ||||
|                     'ipv6' in discount['name'].lower() | ||||
|                 ) else "", | ||||
|                 coupon=(discount['stripe_coupon_id'] | ||||
|                     if 'name' in discount and | ||||
|                        'ipv6' in discount['name'].lower() and | ||||
|                        discount['stripe_coupon_id'] | ||||
|                     else ""), | ||||
|                 tax_rates=[stripe_tax_rate.tax_rate_id] if stripe_tax_rate else [], | ||||
|             ) | ||||
|             stripe_subscription_obj = subscription_result.get('response_object') | ||||
|  |  | |||
|  | @ -761,6 +761,7 @@ OTP_VERIFY_ENDPOINT = env('OTP_VERIFY_ENDPOINT') | |||
| FIRST_VM_ID_AFTER_EU_VAT = int_env('FIRST_VM_ID_AFTER_EU_VAT') | ||||
| PRE_EU_VAT_RATE = float(env('PRE_EU_VAT_RATE')) | ||||
| 
 | ||||
| VM_BASE_PRICE = float(env('VM_BASE_PRICE')) | ||||
| 
 | ||||
| if DEBUG: | ||||
|     from .local import *  # flake8: noqa | ||||
|  |  | |||
|  | @ -266,8 +266,8 @@ $( document ).ready(function() { | |||
|         } | ||||
|         var total = (cardPricing['cpu'].value * window.coresUnitPrice) + | ||||
|                     (cardPricing['ram'].value * window.ramUnitPrice) + | ||||
|                     (cardPricing['storage'].value * window.ssdUnitPrice) - | ||||
|                     window.discountAmount; | ||||
|                     (cardPricing['storage'].value * window.ssdUnitPrice) + | ||||
|                     window.vmBasePrice - window.discountAmount; | ||||
|         total = parseFloat(total.toFixed(2)); | ||||
|         $("#total").text(total); | ||||
|     } | ||||
|  |  | |||
|  | @ -1185,7 +1185,11 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView): | |||
|         subscription_result = stripe_utils.subscribe_customer_to_plan( | ||||
|             stripe_api_cus_id, | ||||
|             [{"plan": stripe_plan.get('response_object').stripe_plan_id}], | ||||
|             coupon='ipv6-discount-8chf' if 'name' in discount and 'ipv6' in discount['name'].lower() else "", | ||||
|             coupon=(discount['stripe_coupon_id'] | ||||
|                     if 'name' in discount and | ||||
|                        'ipv6' in discount['name'].lower() and | ||||
|                        discount['stripe_coupon_id'] | ||||
|                     else ""), | ||||
|             tax_rates=[stripe_tax_rate.tax_rate_id] if stripe_tax_rate else [], | ||||
|         ) | ||||
|         stripe_subscription_obj = subscription_result.get('response_object') | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ import logging | |||
| import math | ||||
| import subprocess | ||||
| 
 | ||||
| from django.conf import settings | ||||
| 
 | ||||
| from oca.pool import WrongIdError | ||||
| 
 | ||||
| from datacenterlight.models import VMPricing | ||||
|  | @ -79,7 +81,8 @@ def get_vm_price(cpu, memory, disk_size, hdd_size=0, pricing_name='default'): | |||
|     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(hdd_size) * pricing.hdd_unit_price) + | ||||
|              decimal.Decimal(settings.VM_BASE_PRICE)) | ||||
|     cents = decimal.Decimal('.01') | ||||
|     price = price.quantize(cents, decimal.ROUND_HALF_UP) | ||||
|     return round(float(price), 2) | ||||
|  | @ -102,7 +105,8 @@ def get_vm_price_for_given_vat(cpu, memory, ssd_size, hdd_size=0, | |||
|         (decimal.Decimal(cpu) * pricing.cores_unit_price) + | ||||
|         (decimal.Decimal(memory) * pricing.ram_unit_price) + | ||||
|         (decimal.Decimal(ssd_size) * pricing.ssd_unit_price) + | ||||
|         (decimal.Decimal(hdd_size) * pricing.hdd_unit_price) | ||||
|         (decimal.Decimal(hdd_size) * pricing.hdd_unit_price) + | ||||
|         decimal.Decimal(settings.VM_BASE_PRICE) | ||||
|     ) | ||||
| 
 | ||||
|     discount_name = pricing.discount_name | ||||
|  | @ -118,7 +122,8 @@ def get_vm_price_for_given_vat(cpu, memory, ssd_size, hdd_size=0, | |||
|     discount = { | ||||
|         'name': discount_name, | ||||
|         'amount': discount_amount, | ||||
|         'amount_with_vat': round(float(discount_amount_with_vat), 2) | ||||
|         'amount_with_vat': round(float(discount_amount_with_vat), 2), | ||||
|         'stripe_coupon_id': pricing.stripe_coupon_id | ||||
|     } | ||||
|     return (round(float(price), 2), round(float(vat), 2), | ||||
|             round(float(vat_percent), 2), discount) | ||||
|  | @ -154,7 +159,8 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0, | |||
|         (decimal.Decimal(cpu) * pricing.cores_unit_price) + | ||||
|         (decimal.Decimal(memory) * pricing.ram_unit_price) + | ||||
|         (decimal.Decimal(ssd_size) * pricing.ssd_unit_price) + | ||||
|         (decimal.Decimal(hdd_size) * pricing.hdd_unit_price) | ||||
|         (decimal.Decimal(hdd_size) * pricing.hdd_unit_price) + | ||||
|         decimal.Decimal(settings.VM_BASE_PRICE) | ||||
|     ) | ||||
|     if pricing.vat_inclusive: | ||||
|         vat = decimal.Decimal(0) | ||||
|  | @ -168,7 +174,8 @@ def get_vm_price_with_vat(cpu, memory, ssd_size, hdd_size=0, | |||
|     vat = vat.quantize(cents, decimal.ROUND_HALF_UP) | ||||
|     discount = { | ||||
|         'name': pricing.discount_name, | ||||
|         'amount': round(float(pricing.discount_amount), 2) | ||||
|         'amount': round(float(pricing.discount_amount), 2), | ||||
|         'stripe_coupon_id': pricing.stripe_coupon_id | ||||
|     } | ||||
|     return (round(float(price), 2), round(float(vat), 2), | ||||
|             round(float(vat_percent), 2), discount) | ||||
|  | @ -215,11 +222,6 @@ def get_ip_addresses(vm_id): | |||
|         return "--" | ||||
| 
 | ||||
| 
 | ||||
| def round_up(n, decimals=0): | ||||
|     multiplier = 10 ** decimals | ||||
|     return math.ceil(n * multiplier) / multiplier | ||||
| 
 | ||||
| 
 | ||||
| class HostingUtils: | ||||
|     @staticmethod | ||||
|     def clear_items_from_list(from_list, items_list): | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue