update invoice template

This commit is contained in:
Setyo Nugroho 2022-07-21 22:36:59 +07:00
parent e70423ce86
commit b6fda8e7f9
18 changed files with 441 additions and 275 deletions

View file

@ -13,7 +13,7 @@ class SettingForm(forms.SelfHandlingForm):
company_logo = forms.URLField(label=_("COMPANY LOGO URL"),
required=False)
company_address = forms.CharField(label=_("COMPANY ADDRESS"),
required=False)
required=False, widget=forms.Textarea())
email_admin = forms.EmailField(label=_("EMAIL ADMIN"),
required=True)

View file

@ -2,6 +2,7 @@ from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import tables
from horizon.utils import filters as utils_filters
class NotificationFilterAction(tables.FilterAction):
@ -15,7 +16,8 @@ class NotificationTable(tables.DataTable):
recipient = tables.Column("recipient", verbose_name=_("Recipient"))
sent_status = tables.Column("sent_status", verbose_name=_("Sent Status"))
is_read = tables.Column("is_read", verbose_name=_("Is Read"))
created_at = tables.Column("created_at", verbose_name=_("Created At"))
created_at = tables.Column("created_at", verbose_name=_("Date Time"), filters=(utils_filters.parse_isotime,),
sortable=True)
def get_object_id(self, obj):
return obj["id"]
@ -24,4 +26,4 @@ class NotificationTable(tables.DataTable):
name = "list_notification_center"
verbose_name = _("Notification Center")
multi_select = False
table_actions = (NotificationFilterAction, )
table_actions = (NotificationFilterAction,)

View file

@ -10,7 +10,7 @@
<dt>Project: </dt>
<dd>
<select id="selection" onchange="onSelection(this.value)">
<option value='{}'
<option value='null'
{% if not current_tenant_id %}selected {% endif %}
>All</option>

View file

@ -5,37 +5,35 @@
{% block main %}
<div class="row">
<div class="col-sm-12 text-right">
{% if not notification.sent_status %}
<a href="{% url 'horizon:admin:notification_center:resend' notification.id%}"
class="btn btn-primary" style="margin-bottom: 8px">Resend Notification</a>
{% endif %}
<a href="{% url 'horizon:admin:notification_center:resend' notification.id %}"
class="btn btn-primary" style="margin-bottom: 8px">Resend Notification</a>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading"><strong>{{ notification.title }}/{{ notification.id }}</strong></div>
<div class="panel-body">
<span><strong>Description:</strong></span>
<p>{{ notification.short_description }}</p>
</div>
<div class="panel-heading"><strong>{{ notification.title }}/{{ notification.id }}</strong></div>
<div class="panel-body">
<span><strong>Description:</strong></span>
<p>{{ notification.short_description }}</p>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">Recipient</th>
<th scope="col">Sent Status</th>
<th scope="col">Is Read</th>
<th scope="col">Created At</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ notification.project.email_notification }}</td>
<td>{{ notification.sent_status }}</td>
<td>{{ notification.is_read }}</td>
<td>{{ notification.created_at }}</td>
</tr>
</tbody>
<thead>
<tr>
<th scope="col">Recipient</th>
<th scope="col">Sent Status</th>
<th scope="col">Is Read</th>
<th scope="col">Created At</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ notification.project.email_notification }}</td>
<td>{{ notification.sent_status }}</td>
<td>{{ notification.is_read }}</td>
<td>{{ notification.created_at }}</td>
</tr>
</tbody>
</table>
</div>
</div>

View file

@ -9,7 +9,7 @@ class InvoiceAction(tables.LinkAction):
verbose_name = "Invoice"
def get_link_url(self, datum=None, *args, **kwargs):
return reverse("horizon:admin:projects_invoice:download_pdf", kwargs={
return reverse("horizon:admin:projects_invoice:invoice_detail", kwargs={
"id": datum['id'],
"project_id": datum['project_id'],
})

View file

@ -0,0 +1,155 @@
<style>
.invoice {
padding: 30px;
}
.invoice h2 {
margin-top: 0px;
line-height: 0.8em;
}
.invoice .small {
font-weight: 300;
}
.invoice hr {
margin-top: 10px;
border-color: #ddd;
}
.invoice .table tr.line {
border-bottom: 1px solid #ccc;
}
.invoice .table td {
border: none;
}
.invoice .identity {
margin-top: 10px;
font-size: 1.1em;
font-weight: 300;
}
.invoice .identity strong {
font-weight: 600;
}
.grid {
position: relative;
width: 100%;
background: #fff;
color: #666666;
border-radius: 2px;
margin-bottom: 25px;
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.1);
}
</style>
<div id="invoice">
<div class="container">
<div class="row">
<!-- BEGIN INVOICE -->
<div class="col-xs-12">
<div class="grid invoice">
<div class="grid-body">
<div class="invoice-title">
<div class="row">
<div class="col-xs-12">
<img src="{{ setting.company_logo }}" alt="" height="50">
</div>
</div>
<br>
<div class="row">
<div class="col-xs-12">
<h2>invoice<br>
<span class="small">order #{{ invoice.id }}</span></h2>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-xs-6">
<address style="max-width: 30%;">
{{ setting.company_name }} <br/>
{{ setting.company_address }}
</address>
</div>
<div class="col-xs-6 text-right">
<address>
<strong>Invoice Month:</strong><br>
{{ invoice.start_date|date:"M Y" }}
<br>
<br>
<strong>Invoice State:</strong><br>
{{ invoice.state_text }}
</address>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>ORDER SUMMARY</h3>
<table class="table table-striped">
<thead>
<tr class="line">
<td><strong>#</strong></td>
<td width="70%"><strong>COMPONENT</strong></td>
<td class="text-right"><strong>TOTAL COST</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><strong>Instance</strong></td>
<td class="text-right">{{ instance_cost }}</td>
</tr>
<tr>
<td>2</td>
<td><strong>Volume</strong></td>
<td class="text-right">{{ volume_cost }}</td>
</tr>
<tr>
<td>3</td>
<td><strong>Floating IP</strong></td>
<td class="text-right">{{ fip_cost }}</td>
</tr>
<tr>
<td>4</td>
<td><strong>Router</strong></td>
<td class="text-right">{{ router_cost }}</td>
</tr>
<tr>
<td>5</td>
<td><strong>Snapshot</strong></td>
<td class="text-right">{{ snapshot_cost }}</td>
</tr>
<tr class="line">
<td>6</td>
<td><strong>Image</strong></td>
<td class="text-right">{{ image_cost }}</td>
</tr>
<tr>
<td colspan="2" class="text-right"><strong>Subtotal</strong></td>
<td class="text-right"><strong>{{ invoice.subtotal_money }}</strong></td>
</tr>
{% if invoice.state != 1 %}
<tr>
<td colspan="2" class="text-right"><strong>Tax</strong></td>
<td class="text-right"><strong>{{ invoice.tax_money }}</strong></td>
</tr>
<tr>
<td colspan="2" class="text-right"><strong>Total</strong></td>
<td class="text-right"><strong>{{ invoice.total_money }}</strong></td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- END INVOICE -->
</div>
</div>
</div>

View file

@ -1,123 +0,0 @@
{% extends 'base.html' %}
{% block title %}{{ page_title }}{% endblock %}
{% block main %}
<button onclick="javascript:downloadPdf();" class="btn btn-default">Download PDF</button>
{% if invoice.state == 2 %}
<a class="btn btn-primary" href="{% url 'horizon:admin:projects_invoice:finish_invoice' invoice.id %}?next={{ request.path }}">Set to Finished</a>
{% endif %}
{% if invoice.state == 100 %}
<a class="btn btn-danger" href="{% url 'horizon:admin:projects_invoice:rollback_to_unpaid' invoice.id %}?next={{ request.path }}">Rollback to Unpaid</a>
{% endif %}
<br/>
<br/>
<div id="invoice">
<div>
<dl>
<dt>Invoice Month</dt>
<dd>
<h3>{{ invoice.start_date|date:"M Y" }}</h3>
</dd>
</dl>
<h5>Invoice State: {{ invoice.state_text }}</h5>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Component</th>
<th>Total Cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>Instance</td>
<td>{{ instance_cost }}</td>
</tr>
<tr>
<td>Volume</td>
<td>{{ volume_cost }}</td>
</tr>
<tr>
<td>Floating IP</td>
<td>{{ fip_cost }}</td>
</tr>
<tr>
<td>Router</td>
<td>{{ router_cost }}</td>
</tr>
<tr>
<td>Snapshot</td>
<td>{{ snapshot_cost }}</td>
</tr>
<tr>
<td>Image</td>
<td>{{ image_cost }}</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td><b>Subtotal:</b> {{ invoice.subtotal_money }}</td>
</tr>
{% if invoice.state != 1 %}
<tr>
<td></td>
<td><b>Tax:</b> {{ invoice.tax_money }}</td>
</tr>
<tr>
<td></td>
<td><b>Total:</b> {{ invoice.total_money }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
{% endblock %}
{% block js %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script>
<script type="text/javascript">
function downloadPdf() {
var pdf = new jsPDF('p', 'pt', 'letter');
// source can be HTML-formatted string, or a reference
// to an actual DOM element from which the text will be scraped.
source = $('#invoice')[0];
// we support special element handlers. Register them with jQuery-style
// ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
// There is no support for any other type of selectors
// (class, of compound) at this time.
specialElementHandlers = {
// element with id of "bypass" - jQuery style selector
'#bypassme': function (element, renderer) {
// true = "handled elsewhere, bypass text extraction"
return true
}
};
margins = {
top: 80,
bottom: 60,
left: 40,
width: 522
};
// all coords and widths are in jsPDF instance's declared units
// 'inches' in this case
pdf.fromHTML(
source, // HTML string or DOM elem ref.
margins.left, // x coord
margins.top, { // y coord
'width': margins.width, // max width of content on PDF
'elementHandlers': specialElementHandlers
},
function (dispose) {
// dispose: object with X, Y of the last line add to the PDF
// this allow the insertion of new lines after html
pdf.save('invoice.pdf');
}, margins);
}
</script>
{% endblock %}

View file

@ -0,0 +1,32 @@
{% extends 'base.html' %}
{% block title %}{{ page_title }}{% endblock %}
{% block main %}
<a class="btn btn-default" href="?print=true" target="_blank">Download PDF</a>
{% if invoice.state == 2 %}
<a class="btn btn-primary"
href="{% url 'horizon:admin:projects_invoice:finish_invoice' invoice.id %}?next={{ request.path }}">Set to
Finished</a>
{% endif %}
{% if invoice.state == 100 %}
<a class="btn btn-danger"
href="{% url 'horizon:admin:projects_invoice:rollback_to_unpaid' invoice.id %}?next={{ request.path }}">Rollback
to Unpaid</a>
{% endif %}
<br/>
<br/>
{% include 'admin/projects_invoice/base_invoice.html' %}
{% endblock %}
{% block js %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"
integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
function downloadPdf() {
window.print();
}
</script>
{% endblock %}

View file

@ -0,0 +1,13 @@
<html>
<head>
<title>Invoice Download</title>
{% include "_stylesheets.html" %}
</head>
<body>
{% include 'admin/projects_invoice/base_invoice.html' %}
{% include "horizon/_scripts.html" %}
<script type="text/javascript">
window.print();
</script>
</body>
</html>

View file

@ -16,7 +16,7 @@ from openstack_dashboard.dashboards.yuyu.admin.projects_invoice import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^invoice/pdf/(?P<project_id>[^/]+)/(?P<id>[^/]+)/$', views.InvoiceView.as_view(), name='download_pdf'),
url(r'^invoice/detail/(?P<project_id>[^/]+)/(?P<id>[^/]+)/$', views.InvoiceView.as_view(), name='invoice_detail'),
url(r'^invoice/usage/(?P<project_id>[^/]+)/(?P<id>[^/]+)/$', views.UsageCostView.as_view(), name='usage_cost'),
url(r'^invoice/finish/(?P<id>[^/]+)/$', views.FinishInvoice.as_view(), name='finish_invoice'),
url(r'^invoice/rollback_to_unpaid/(?P<id>[^/]+)/$', views.RollbackToUnpaidInvoice.as_view(),

View file

@ -27,6 +27,7 @@ from horizon import views
from openstack_dashboard import api
from openstack_dashboard.dashboards.yuyu.cases.invoice_use_case import InvoiceUseCase
from .tables import InvoiceTable
from ...cases.setting_use_case import SettingUseCase
from ...core.usage_cost.tables import InstanceCostTable, VolumeCostTable, FloatingIpCostTable, RouterCostTable, \
SnapshotCostTable, ImageCostTable
from ...core.utils.invoice_utils import state_to_text
@ -67,14 +68,21 @@ class IndexView(tables.DataTableView):
class InvoiceView(views.APIView):
page_title = _("Invoice")
template_name = "admin/projects_invoice/download_pdf.html"
invoice_uc = InvoiceUseCase()
setting_uc = SettingUseCase()
def get_template_names(self):
if self.request.GET.get('print', None):
return ['admin/projects_invoice/invoice_download.html']
else:
return ['admin/projects_invoice/invoice.html']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
invoice = self.invoice_uc.get_invoice(self.request, self.kwargs['id'], tenant_id=self.kwargs['project_id'])
context['invoice'] = invoice
context['setting'] = self.setting_uc.get_settings(self.request)
context['instance_cost'] = self.get_sum_price(invoice, 'instances')
context['volume_cost'] = self.get_sum_price(invoice, 'volumes')
context['fip_cost'] = self.get_sum_price(invoice, 'floating_ips')

View file

@ -10,7 +10,7 @@ class DetailAction(tables.LinkAction):
def get_link_url(self, datum=None, *args, **kwargs):
print(datum, args, kwargs)
return reverse("horizon:project:invoice:download_pdf", kwargs={"id": datum['id']})
return reverse("horizon:project:invoice:invoice_detail", kwargs={"id": datum['id']})
class InvoiceTable(tables.DataTable):

View file

@ -0,0 +1,155 @@
<style>
.invoice {
padding: 30px;
}
.invoice h2 {
margin-top: 0px;
line-height: 0.8em;
}
.invoice .small {
font-weight: 300;
}
.invoice hr {
margin-top: 10px;
border-color: #ddd;
}
.invoice .table tr.line {
border-bottom: 1px solid #ccc;
}
.invoice .table td {
border: none;
}
.invoice .identity {
margin-top: 10px;
font-size: 1.1em;
font-weight: 300;
}
.invoice .identity strong {
font-weight: 600;
}
.grid {
position: relative;
width: 100%;
background: #fff;
color: #666666;
border-radius: 2px;
margin-bottom: 25px;
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.1);
}
</style>
<div id="invoice">
<div class="container">
<div class="row">
<!-- BEGIN INVOICE -->
<div class="col-xs-12">
<div class="grid invoice">
<div class="grid-body">
<div class="invoice-title">
<div class="row">
<div class="col-xs-12">
<img src="{{ setting.company_logo }}" alt="" height="50">
</div>
</div>
<br>
<div class="row">
<div class="col-xs-12">
<h2>invoice<br>
<span class="small">order #{{ invoice.id }}</span></h2>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-xs-6">
<address style="max-width: 30%;">
{{ setting.company_name }} <br/>
{{ setting.company_address }}
</address>
</div>
<div class="col-xs-6 text-right">
<address>
<strong>Invoice Month:</strong><br>
{{ invoice.start_date|date:"M Y" }}
<br>
<br>
<strong>Invoice State:</strong><br>
{{ invoice.state_text }}
</address>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>ORDER SUMMARY</h3>
<table class="table table-striped">
<thead>
<tr class="line">
<td><strong>#</strong></td>
<td width="70%"><strong>COMPONENT</strong></td>
<td class="text-right"><strong>TOTAL COST</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><strong>Instance</strong></td>
<td class="text-right">{{ instance_cost }}</td>
</tr>
<tr>
<td>2</td>
<td><strong>Volume</strong></td>
<td class="text-right">{{ volume_cost }}</td>
</tr>
<tr>
<td>3</td>
<td><strong>Floating IP</strong></td>
<td class="text-right">{{ fip_cost }}</td>
</tr>
<tr>
<td>4</td>
<td><strong>Router</strong></td>
<td class="text-right">{{ router_cost }}</td>
</tr>
<tr>
<td>5</td>
<td><strong>Snapshot</strong></td>
<td class="text-right">{{ snapshot_cost }}</td>
</tr>
<tr class="line">
<td>6</td>
<td><strong>Image</strong></td>
<td class="text-right">{{ image_cost }}</td>
</tr>
<tr>
<td colspan="2" class="text-right"><strong>Subtotal</strong></td>
<td class="text-right"><strong>{{ invoice.subtotal_money }}</strong></td>
</tr>
{% if invoice.state != 1 %}
<tr>
<td colspan="2" class="text-right"><strong>Tax</strong></td>
<td class="text-right"><strong>{{ invoice.tax_money }}</strong></td>
</tr>
<tr>
<td colspan="2" class="text-right"><strong>Total</strong></td>
<td class="text-right"><strong>{{ invoice.total_money }}</strong></td>
</tr>
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- END INVOICE -->
</div>
</div>
</div>

View file

@ -1,116 +0,0 @@
{% extends 'base.html' %}
{% block title %}{{ page_title }}{% endblock %}
{% block main %}
<button onclick="javascript:downloadPdf();" class="btn btn-default">Download PDF</button>
<br/>
<br/>
<div id="invoice">
<div>
<dl>
<dt>Invoice Month</dt>
<dd>
<h3>{{ invoice.start_date|date:"M Y" }}</h3>
</dd>
</dl>
<h5>Invoice State: {{ invoice.state_text }}</h5>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Component</th>
<th>Total Cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>Instance</td>
<td>{{ instance_cost }}</td>
</tr>
<tr>
<td>Volume</td>
<td>{{ volume_cost }}</td>
</tr>
<tr>
<td>Floating IP</td>
<td>{{ fip_cost }}</td>
</tr>
<tr>
<td>Router</td>
<td>{{ router_cost }}</td>
</tr>
<tr>
<td>Snapshot</td>
<td>{{ snapshot_cost }}</td>
</tr>
<tr>
<td>Image</td>
<td>{{ image_cost }}</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td><b>Subtotal:</b> {{ invoice.subtotal_money }}</td>
</tr>
{% if invoice.state != 1 %}
<tr>
<td></td>
<td><b>Tax:</b> {{ invoice.tax_money }}</td>
</tr>
<tr>
<td></td>
<td><b>Total:</b> {{ invoice.total_money }}</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
{% endblock %}
{% block js %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script>
<script type="text/javascript">
function downloadPdf() {
var pdf = new jsPDF('p', 'pt', 'letter');
// source can be HTML-formatted string, or a reference
// to an actual DOM element from which the text will be scraped.
source = $('#invoice')[0];
// we support special element handlers. Register them with jQuery-style
// ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
// There is no support for any other type of selectors
// (class, of compound) at this time.
specialElementHandlers = {
// element with id of "bypass" - jQuery style selector
'#bypassme': function (element, renderer) {
// true = "handled elsewhere, bypass text extraction"
return true
}
};
margins = {
top: 80,
bottom: 60,
left: 40,
width: 522
};
// all coords and widths are in jsPDF instance's declared units
// 'inches' in this case
pdf.fromHTML(
source, // HTML string or DOM elem ref.
margins.left, // x coord
margins.top, { // y coord
'width': margins.width, // max width of content on PDF
'elementHandlers': specialElementHandlers
},
function (dispose) {
// dispose: object with X, Y of the last line add to the PDF
// this allow the insertion of new lines after html
pdf.save('invoice.pdf');
}, margins);
}
</script>
{% endblock %}

View file

@ -0,0 +1,21 @@
{% extends 'base.html' %}
{% block title %}{{ page_title }}{% endblock %}
{% block main %}
<a class="btn btn-default" href="?print=true" target="_blank">Download PDF</a>
<br/>
<br/>
{% include 'admin/projects_invoice/base_invoice.html' %}
{% endblock %}
{% block js %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"
integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
function downloadPdf() {
window.print();
}
</script>
{% endblock %}

View file

@ -0,0 +1,13 @@
<html>
<head>
<title>Invoice Download</title>
{% include "_stylesheets.html" %}
</head>
<body>
{% include 'project/invoice/base_invoice.html' %}
{% include "horizon/_scripts.html" %}
<script type="text/javascript">
window.print();
</script>
</body>
</html>

View file

@ -17,5 +17,5 @@ from openstack_dashboard.dashboards.yuyu.project.invoice import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^invoice/pdf/(?P<id>[^/]+)/$', views.InvoiceView.as_view(), name='download_pdf'),
url(r'^invoice/detail/(?P<id>[^/]+)/$', views.InvoiceView.as_view(), name='invoice_detail'),
]

View file

@ -25,6 +25,7 @@ from horizon import views
from openstack_dashboard import api
from openstack_dashboard.dashboards.yuyu.cases.invoice_use_case import InvoiceUseCase
from .tables import InvoiceTable
from ...cases.setting_use_case import SettingUseCase
from ...core.utils.invoice_utils import state_to_text
@ -55,15 +56,22 @@ class IndexView(tables.DataTableView):
class InvoiceView(views.APIView):
page_title = _("Invoice")
template_name = "project/invoice/download_pdf.html"
invoice_uc = InvoiceUseCase()
setting_uc = SettingUseCase()
def get_template_names(self):
if self.request.GET.get('print', None):
return ['project/invoice/invoice_download.html']
else:
return ['project/invoice/invoice.html']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
invoice = self.invoice_uc.get_invoice(self.request, self.kwargs['id'])
context['invoice'] = invoice
context['setting'] = self.setting_uc.get_settings(self.request)
context['instance_cost'] = self.get_sum_price(invoice, 'instances')
context['volume_cost'] = self.get_sum_price(invoice, 'volumes')
context['fip_cost'] = self.get_sum_price(invoice, 'floating_ips')