Merge branch 'feature/6561/show-multiple-line-items' into 'master'

Feature/6561/show multiple line items

See merge request ungleich-public/dynamicweb!697
This commit is contained in:
pcoder116 2019-04-20 19:00:09 +02:00
commit 3c4494f35c
5 changed files with 169 additions and 70 deletions

View file

@ -473,6 +473,51 @@ class HostingBillLineItem(AssignPermissionsMixin, models.Model):
('view_hostingbilllineitem', 'View Monthly Hosting Bill Line Item'),
)
def amount_in_chf(self):
"""
Returns amount in chf. The amount in this model is in cents (as in
Stripe). Hence we multiply it by 0.01 to obtain the result
:return:
"""
return self.amount * 0.01
def unit_amount_in_chf(self):
"""
Returns unit amount in chf. If its 0, we obtain it from amount and
quantity.
:return:
"""
if self.unit_amount == 0:
return round((self.amount / self.quantity) * 0.01, 2)
else:
return self.unit_amount * 0.01
def get_item_detail_str(self):
"""
Returns line item html string representation
:return:
"""
item_detail = ""
if self.metadata is not None and len(self.metadata) > 0:
try:
vm_dict = json.loads(self.metadata)
item_detail = "VM ID: {}<br/>".format(vm_dict["VM_ID"])
except ValueError as ve:
logger.error(
"Could not parse VM in metadata {}. Detail {}".format(
self.metadata, str(ve)
)
)
vm_conf = StripeUtils.get_vm_config_from_stripe_id(
self.stripe_plan.stripe_plan_id
)
item_detail += ("<b>Cores</b>: {}<br/><b>RAM</b>: {} GB<br/>"
"<b>SSD</b>: {} GB<br/>").format(
vm_conf['cores'], int(float(vm_conf['ram'])), vm_conf['ssd']
)
return item_detail
class VMDetail(models.Model):
user = models.ForeignKey(CustomUser)

View file

@ -113,3 +113,16 @@
.dcl-place-order-text {
color: #808080;
}
table {
border-collapse: collapse;
}
tr.border_bottom td {
border-bottom:1pt solid #eee;
}
tr.grand-total-padding td {
padding-top: 10px;
font-weight: bold;
}

View file

@ -89,6 +89,16 @@
<div>
<h4>{% trans "Invoice summary" %}</h4>
{% if vm %}
{% if line_items %}
<table>
<tr><th style="width: 35%">Product</th><th style="width: 20%">Period</th><th style="text-align: center; width: 10%">Qty</th><th align="center" style="width: 10%; text-align: center;">Unit Price</th><th style="width: 10%; text-align: right;">Total</th></tr>
{% for line_item in line_items %}
<tr class="border_bottom"><td>{% if line_item.description|length > 0 %}{{line_item.description}}{% else %}{{line_item.get_item_detail_str|safe}}{% endif %}</td><td>{{ line_item.period_start | date:'Y-m-d' }} &mdash; {{ line_item.period_end | date:'Y-m-d' }}</td><td align="center">{{line_item.quantity}}</td><td align="center">{{line_item.unit_amount_in_chf}}</td><td align="right">{{line_item.amount_in_chf}}</td></tr>
{% endfor %}
<tr class="grand-total-padding"><td colspan="4">Grand Total</td><td align="right">{{total_in_chf}}</td></tr>
</table>
{% else %}
<p>
<strong>{% trans "Product" %}:</strong>&nbsp;
{% if vm.name %}
@ -163,6 +173,7 @@
</p>
</div>
</div>
{% endif %}
{% else %}
<p>
<strong>{% trans "Product" %}:</strong>&nbsp;

View file

@ -1284,8 +1284,8 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
# fallback to get it from the infrastructure
try:
manager = OpenNebulaManager(
email=self.request.email,
password=self.request.password
email=self.request.user.email,
password=self.request.user.password
)
vm = manager.get_vm(vm_id)
context['vm'] = VirtualMachineSerializer(vm).data
@ -1322,6 +1322,9 @@ class InvoiceDetailView(LoginRequiredMixin, DetailView):
context['total_in_chf'] = obj.total_in_chf()
context['invoice_number'] = obj.invoice_number
context['discount_on_stripe'] = obj.discount_in_chf()
if obj.lines_data_count > 1:
# special case, we pass the details of each of the line items
context['line_items'] = obj.hostingbilllineitem_set.all()
return context
else:
raise Http404

View file

@ -1,4 +1,5 @@
import logging
import re
import stripe
from django.conf import settings
from datacenterlight.models import StripePlan
@ -376,6 +377,32 @@ class StripeUtils(object):
else:
return stripe_plan_id_string
@staticmethod
def get_vm_config_from_stripe_id(stripe_id):
"""
Given a string like "dcl-v1-cpu-2-ram-5gb-ssd-10gb" return different
configuration params as a dict
:param stripe_id|str
:return: dict
"""
pattern = re.compile(r'^dcl-v(\d+)-cpu-(\d+)-ram-(\d+\.?\d*)gb-ssd-(\d+)gb-?(\d*\.?\d*)(chf)?$')
match_res = pattern.match(stripe_id)
if match_res is not None:
price = None
try:
price=match_res.group(5)
except IndexError as ie:
logger.debug("Did not find price in {}".format(stripe_id))
return {
'version': match_res.group(1),
'cores': match_res.group(2),
'ram': match_res.group(3),
'ssd': match_res.group(4),
'price': price
}
@staticmethod
def get_stripe_plan_name(cpu, memory, disk_size, price):
"""