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
|
2.10.3b: 2020-03-05
|
||||||
* #7773: Use username for communicating with opennebula all the time
|
* #7773: Use username for communicating with opennebula all the time
|
||||||
2.10.2b: 2020-02-25
|
2.10.2b: 2020-02-25
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from cms.plugin_base import CMSPluginBase
|
from cms.plugin_base import CMSPluginBase
|
||||||
from cms.plugin_pool import plugin_pool
|
from cms.plugin_pool import plugin_pool
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from .cms_models import (
|
from .cms_models import (
|
||||||
DCLBannerItemPluginModel, DCLBannerListPluginModel, DCLContactPluginModel,
|
DCLBannerItemPluginModel, DCLBannerListPluginModel, DCLContactPluginModel,
|
||||||
|
@ -100,6 +101,7 @@ class DCLCalculatorPlugin(CMSPluginBase):
|
||||||
vm_type=instance.vm_type
|
vm_type=instance.vm_type
|
||||||
).order_by('name')
|
).order_by('name')
|
||||||
context['instance'] = instance
|
context['instance'] = instance
|
||||||
|
context['vm_base_price'] = settings.VM_BASE_PRICE
|
||||||
context['min_ram'] = 0.5 if instance.enable_512mb_ram else 1
|
context['min_ram'] = 0.5 if instance.enable_512mb_ram else 1
|
||||||
return context
|
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(
|
discount_amount = models.DecimalField(
|
||||||
max_digits=6, decimal_places=2, default=0
|
max_digits=6, decimal_places=2, default=0
|
||||||
)
|
)
|
||||||
|
stripe_coupon_id = models.CharField(max_length=255, null=True, blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
display_str = self.name + ' => ' + ' - '.join([
|
display_str = self.name + ' => ' + ' - '.join([
|
||||||
|
|
|
@ -225,8 +225,8 @@
|
||||||
}
|
}
|
||||||
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
|
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
|
||||||
(cardPricing['ram'].value * window.ramUnitPrice) +
|
(cardPricing['ram'].value * window.ramUnitPrice) +
|
||||||
(cardPricing['storage'].value * window.ssdUnitPrice) -
|
(cardPricing['storage'].value * window.ssdUnitPrice) +
|
||||||
window.discountAmount;
|
window.vmBasePrice - window.discountAmount;
|
||||||
total = parseFloat(total.toFixed(2));
|
total = parseFloat(total.toFixed(2));
|
||||||
$("#total").text(total);
|
$("#total").text(total);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="price-calc-section">
|
<div class="price-calc-section">
|
||||||
<div class="card">
|
<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>
|
||||||
</div>
|
</div>
|
|
@ -9,6 +9,7 @@
|
||||||
window.ssdUnitPrice = {{vm_pricing.ssd_unit_price|default:0}};
|
window.ssdUnitPrice = {{vm_pricing.ssd_unit_price|default:0}};
|
||||||
window.hddUnitPrice = {{vm_pricing.hdd_unit_price|default:0}};
|
window.hddUnitPrice = {{vm_pricing.hdd_unit_price|default:0}};
|
||||||
window.discountAmount = {{vm_pricing.discount_amount|default:0}};
|
window.discountAmount = {{vm_pricing.discount_amount|default:0}};
|
||||||
|
window.vmBasePrice = {{vm_base_price|default:0}};
|
||||||
window.minRam = {{min_ram}};
|
window.minRam = {{min_ram}};
|
||||||
window.minRamErr = '{% blocktrans with min_ram=min_ram %}Please enter a value in range {{min_ram}} - 200.{% endblocktrans %}';
|
window.minRamErr = '{% blocktrans with min_ram=min_ram %}Please enter a value in range {{min_ram}} - 200.{% endblocktrans %}';
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -678,9 +678,9 @@ class OrderConfirmationView(DetailView, FormView):
|
||||||
vm_specs["vat_percent"] = vat_percent
|
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_validation_status"] = request.session["vat_validation_status"] if "vat_validation_status" in request.session else ""
|
||||||
vm_specs["vat_country"] = user_vat_country
|
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_with_vat"] = round(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"] = round(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_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)
|
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["total_price"] = vm_specs["price_after_discount_with_vat"]
|
||||||
vm_specs["discount"] = discount
|
vm_specs["discount"] = discount
|
||||||
|
@ -933,11 +933,11 @@ class OrderConfirmationView(DetailView, FormView):
|
||||||
subscription_result = stripe_utils.subscribe_customer_to_plan(
|
subscription_result = stripe_utils.subscribe_customer_to_plan(
|
||||||
stripe_api_cus_id,
|
stripe_api_cus_id,
|
||||||
[{"plan": stripe_plan.get('response_object').stripe_plan_id}],
|
[{"plan": stripe_plan.get('response_object').stripe_plan_id}],
|
||||||
coupon='ipv6-discount-8chf' if (
|
coupon=(discount['stripe_coupon_id']
|
||||||
'name' in discount and
|
if 'name' in discount and
|
||||||
discount['name'] is not None and
|
'ipv6' in discount['name'].lower() and
|
||||||
'ipv6' in discount['name'].lower()
|
discount['stripe_coupon_id']
|
||||||
) else "",
|
else ""),
|
||||||
tax_rates=[stripe_tax_rate.tax_rate_id] if stripe_tax_rate else [],
|
tax_rates=[stripe_tax_rate.tax_rate_id] if stripe_tax_rate else [],
|
||||||
)
|
)
|
||||||
stripe_subscription_obj = subscription_result.get('response_object')
|
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')
|
FIRST_VM_ID_AFTER_EU_VAT = int_env('FIRST_VM_ID_AFTER_EU_VAT')
|
||||||
PRE_EU_VAT_RATE = float(env('PRE_EU_VAT_RATE'))
|
PRE_EU_VAT_RATE = float(env('PRE_EU_VAT_RATE'))
|
||||||
|
|
||||||
|
VM_BASE_PRICE = float(env('VM_BASE_PRICE'))
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
from .local import * # flake8: noqa
|
from .local import * # flake8: noqa
|
||||||
|
|
|
@ -266,8 +266,8 @@ $( document ).ready(function() {
|
||||||
}
|
}
|
||||||
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
|
var total = (cardPricing['cpu'].value * window.coresUnitPrice) +
|
||||||
(cardPricing['ram'].value * window.ramUnitPrice) +
|
(cardPricing['ram'].value * window.ramUnitPrice) +
|
||||||
(cardPricing['storage'].value * window.ssdUnitPrice) -
|
(cardPricing['storage'].value * window.ssdUnitPrice) +
|
||||||
window.discountAmount;
|
window.vmBasePrice - window.discountAmount;
|
||||||
total = parseFloat(total.toFixed(2));
|
total = parseFloat(total.toFixed(2));
|
||||||
$("#total").text(total);
|
$("#total").text(total);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1185,7 +1185,11 @@ class OrdersHostingDetailView(LoginRequiredMixin, DetailView, FormView):
|
||||||
subscription_result = stripe_utils.subscribe_customer_to_plan(
|
subscription_result = stripe_utils.subscribe_customer_to_plan(
|
||||||
stripe_api_cus_id,
|
stripe_api_cus_id,
|
||||||
[{"plan": stripe_plan.get('response_object').stripe_plan_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 [],
|
tax_rates=[stripe_tax_rate.tax_rate_id] if stripe_tax_rate else [],
|
||||||
)
|
)
|
||||||
stripe_subscription_obj = subscription_result.get('response_object')
|
stripe_subscription_obj = subscription_result.get('response_object')
|
||||||
|
|
|
@ -3,6 +3,8 @@ import logging
|
||||||
import math
|
import math
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from oca.pool import WrongIdError
|
from oca.pool import WrongIdError
|
||||||
|
|
||||||
from datacenterlight.models import VMPricing
|
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) +
|
price = ((decimal.Decimal(cpu) * pricing.cores_unit_price) +
|
||||||
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
||||||
(decimal.Decimal(disk_size) * pricing.ssd_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')
|
cents = decimal.Decimal('.01')
|
||||||
price = price.quantize(cents, decimal.ROUND_HALF_UP)
|
price = price.quantize(cents, decimal.ROUND_HALF_UP)
|
||||||
return round(float(price), 2)
|
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(cpu) * pricing.cores_unit_price) +
|
||||||
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
||||||
(decimal.Decimal(ssd_size) * pricing.ssd_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
|
discount_name = pricing.discount_name
|
||||||
|
@ -118,7 +122,8 @@ def get_vm_price_for_given_vat(cpu, memory, ssd_size, hdd_size=0,
|
||||||
discount = {
|
discount = {
|
||||||
'name': discount_name,
|
'name': discount_name,
|
||||||
'amount': discount_amount,
|
'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),
|
return (round(float(price), 2), round(float(vat), 2),
|
||||||
round(float(vat_percent), 2), discount)
|
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(cpu) * pricing.cores_unit_price) +
|
||||||
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
(decimal.Decimal(memory) * pricing.ram_unit_price) +
|
||||||
(decimal.Decimal(ssd_size) * pricing.ssd_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:
|
if pricing.vat_inclusive:
|
||||||
vat = decimal.Decimal(0)
|
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)
|
vat = vat.quantize(cents, decimal.ROUND_HALF_UP)
|
||||||
discount = {
|
discount = {
|
||||||
'name': pricing.discount_name,
|
'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),
|
return (round(float(price), 2), round(float(vat), 2),
|
||||||
round(float(vat_percent), 2), discount)
|
round(float(vat_percent), 2), discount)
|
||||||
|
@ -215,11 +222,6 @@ def get_ip_addresses(vm_id):
|
||||||
return "--"
|
return "--"
|
||||||
|
|
||||||
|
|
||||||
def round_up(n, decimals=0):
|
|
||||||
multiplier = 10 ** decimals
|
|
||||||
return math.ceil(n * multiplier) / multiplier
|
|
||||||
|
|
||||||
|
|
||||||
class HostingUtils:
|
class HostingUtils:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def clear_items_from_list(from_list, items_list):
|
def clear_items_from_list(from_list, items_list):
|
||||||
|
|
Loading…
Reference in a new issue