commit
7cd2f1884d
12 changed files with 371 additions and 5 deletions
|
@ -5,7 +5,8 @@ from django.core.urlresolvers import reverse
|
||||||
from utils.mailer import BaseEmail
|
from utils.mailer import BaseEmail
|
||||||
|
|
||||||
from .forms import HostingOrderAdminForm
|
from .forms import HostingOrderAdminForm
|
||||||
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, ManageVM
|
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, \
|
||||||
|
ManageVM, HostingBill
|
||||||
from .opennebula_functions import HostingManageVMAdmin
|
from .opennebula_functions import HostingManageVMAdmin
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,3 +99,4 @@ admin.site.register(HostingOrder, HostingOrderAdmin)
|
||||||
admin.site.register(VirtualMachineType)
|
admin.site.register(VirtualMachineType)
|
||||||
admin.site.register(VirtualMachinePlan, VirtualMachinePlanAdmin)
|
admin.site.register(VirtualMachinePlan, VirtualMachinePlanAdmin)
|
||||||
admin.site.register(ManageVM, HostingManageVMAdmin)
|
admin.site.register(ManageVM, HostingManageVMAdmin)
|
||||||
|
admin.site.register(HostingBill)
|
||||||
|
|
24
hosting/migrations/0028_managevms.py
Normal file
24
hosting/migrations/0028_managevms.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2017-04-24 04:24
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('hosting', '0027_auto_20160711_0210'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ManageVMs',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'managed': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
24
hosting/migrations/0029_managevm.py
Normal file
24
hosting/migrations/0029_managevm.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2017-04-24 04:25
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('hosting', '0028_managevms'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ManageVM',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'managed': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
31
hosting/migrations/0030_hostingbill.py
Normal file
31
hosting/migrations/0030_hostingbill.py
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2017-05-05 11:50
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import utils.mixins
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('utils', '0005_auto_20170322_1443'),
|
||||||
|
('membership', '0006_auto_20160526_0445'),
|
||||||
|
('hosting', '0029_managevm'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='HostingBill',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('billing_address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='utils.BillingAddress')),
|
||||||
|
('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='membership.StripeCustomer')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'permissions': (('view_hostingbill', 'View Hosting Bill'),),
|
||||||
|
},
|
||||||
|
bases=(utils.mixins.AssignPermissionsMixin, models.Model),
|
||||||
|
),
|
||||||
|
]
|
20
hosting/migrations/0031_hostingbill_total_price.py
Normal file
20
hosting/migrations/0031_hostingbill_total_price.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2017-05-06 12:30
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('hosting', '0030_hostingbill'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='hostingbill',
|
||||||
|
name='total_price',
|
||||||
|
field=models.FloatField(default=0.0),
|
||||||
|
),
|
||||||
|
]
|
16
hosting/migrations/0037_merge.py
Normal file
16
hosting/migrations/0037_merge.py
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9.4 on 2017-05-07 04:49
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('hosting', '0031_hostingbill_total_price'),
|
||||||
|
('hosting', '0036_auto_20170506_2312'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
]
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import oca
|
import socket
|
||||||
|
|
||||||
|
import oca
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
@ -15,6 +16,7 @@ from membership.models import StripeCustomer, CustomUser
|
||||||
from utils.models import BillingAddress
|
from utils.models import BillingAddress
|
||||||
from utils.mixins import AssignPermissionsMixin
|
from utils.mixins import AssignPermissionsMixin
|
||||||
from .managers import VMPlansManager
|
from .managers import VMPlansManager
|
||||||
|
from oca.exceptions import OpenNebulaException
|
||||||
from oca.pool import WrongNameError
|
from oca.pool import WrongNameError
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
@ -313,6 +315,47 @@ class ManageVM(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
managed = False
|
managed = False
|
||||||
|
|
||||||
|
class HostingBill(AssignPermissionsMixin, models.Model):
|
||||||
|
customer = models.ForeignKey(StripeCustomer)
|
||||||
|
billing_address = models.ForeignKey(BillingAddress)
|
||||||
|
total_price = models.FloatField(default=0.0)
|
||||||
|
|
||||||
|
permissions = ('view_hostingbill',)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
('view_hostingbill', 'View Hosting Bill'),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s" % (self.customer.user.email)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, customer=None, billing_address=None):
|
||||||
|
instance = cls.objects.create(customer=customer, billing_address=billing_address)
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def get_vms(self):
|
||||||
|
email = self.customer.user.email
|
||||||
|
# Get opennebula client
|
||||||
|
opennebula_client = OpenNebulaManager(create_user=False)
|
||||||
|
|
||||||
|
# Get vm pool
|
||||||
|
vm_pool = opennebula_client.get_vms(email)
|
||||||
|
|
||||||
|
# Reset total price
|
||||||
|
self.total_price = 0
|
||||||
|
vms = []
|
||||||
|
# Add vm in vm_pool to context
|
||||||
|
for vm in vm_pool:
|
||||||
|
vm_data = OpenNebulaManager.parse_vm(vm)
|
||||||
|
self.total_price += vm_data['price']
|
||||||
|
vms.append(vm_data)
|
||||||
|
self.save()
|
||||||
|
return vms
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_opennebula_password():
|
def get_user_opennebula_password():
|
||||||
'''
|
'''
|
||||||
|
|
91
hosting/templates/hosting/bill_detail.html
Normal file
91
hosting/templates/hosting/bill_detail.html
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
{% extends "hosting/base_short.html" %}
|
||||||
|
{% load staticfiles bootstrap3 %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="orders-container">
|
||||||
|
{# Adress bar #}
|
||||||
|
<div class="row">
|
||||||
|
<div class="invoice-title">
|
||||||
|
<h2>{% trans "Invoice"%}</h2><h3 class="pull-right">{% trans "Order #"%} {{bill.id}}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<address>
|
||||||
|
{{bill.customer.user.name}}<br>
|
||||||
|
{{bill.billing_address.street_address}},{{bill.billing_address.postal_code}}<br>
|
||||||
|
{{bill.billing_address.city}}, {{bill.billing_address.country}}.
|
||||||
|
</address>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 text-right">
|
||||||
|
<address>
|
||||||
|
{% trans "ungleich GmbH" %}<br>
|
||||||
|
{% trans "buchhaltung@ungleich.ch" %}<br>
|
||||||
|
{% trans "Hauptstrasse 14"%}<br>
|
||||||
|
{% trans "CH-8775 Luchsingen"%}<br>
|
||||||
|
{% trans "Mwst-Nummer: CHE-109.549.333 MWST"%}<br>
|
||||||
|
|
||||||
|
</address>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<table class="table table-bordered">
|
||||||
|
{# Bill header #}
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Cores</th>
|
||||||
|
<th>Memory</th>
|
||||||
|
<th>Disk Size</th>
|
||||||
|
<th>Price</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{# Bill items#}
|
||||||
|
{% for vm in vms %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ vm.name }}</td>
|
||||||
|
<td><span class="pull-right">{{ vm.cores }}</span></td>
|
||||||
|
<td><span class="pull-right">{{ vm.memory|floatformat }} GiB </span></td>
|
||||||
|
<td><span class="pull-right">{{ vm.disk_size|floatformat }} GiB </span></td>
|
||||||
|
<td><span class="pull-right">{{ vm.price|floatformat }} CHF</span></td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{# Bill total#}
|
||||||
|
<tr>
|
||||||
|
<td colspan=4> {% trans "Total:" %} </td>
|
||||||
|
<td> <span class="pull-right">{{ bill.total_price|floatformat}} CHF </span></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<hr>
|
||||||
|
{# Bill Footer #}
|
||||||
|
<div class="row">
|
||||||
|
{% trans "Alles Preise in CHF mit 8% Mehrwertsteuer." %}
|
||||||
|
{% trans "Betrag zahlbar innerhalb von 30 Tagen ab Rechnungseingang." %}
|
||||||
|
{% trans "Kontoverbindung:" %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{% trans "IBAN:" %}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{% trans "BIC:" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{% trans "CH02 ............" %}
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
{% trans "POFICHBEXXX" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
14
hosting/templates/hosting/bill_error.html
Normal file
14
hosting/templates/hosting/bill_error.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{% extends "hosting/base_short.html" %}
|
||||||
|
{% load staticfiles bootstrap3 %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="container orders-container">
|
||||||
|
<h1>Error</h1>
|
||||||
|
<p> Could not get HostingBill object for client. </p>
|
||||||
|
<p> Please create a HostingBill object via the admin page </p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
60
hosting/templates/hosting/bills.html
Normal file
60
hosting/templates/hosting/bills.html
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{% extends "hosting/base_short.html" %}
|
||||||
|
{% load staticfiles bootstrap3 %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="container orders-container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8 col-md-offset-2">
|
||||||
|
<table class="table borderless table-hover">
|
||||||
|
<h3>{% trans "Customers"%}</h3>
|
||||||
|
<br/>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Name"%}</th>
|
||||||
|
<th>{% trans "Email"%}</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ user.user.name}}</td>
|
||||||
|
<td>{{ user.user.email}}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-default"><a
|
||||||
|
href="{% url 'hosting:bills' user.id %}">{% trans "View Bill"%}</a>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{% if is_paginated %}
|
||||||
|
<div class="pagination">
|
||||||
|
<span class="page-links">
|
||||||
|
{% if page_obj.has_previous %}
|
||||||
|
<a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">{% trans "previous"%}</a>
|
||||||
|
{% endif %}
|
||||||
|
<span class="page-current">
|
||||||
|
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
|
||||||
|
</span>
|
||||||
|
{% if page_obj.has_next %}
|
||||||
|
<a href="{{ request.path }}?page={{ page_obj.next_page_number }}">{% trans "next"%}</a>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -5,7 +5,7 @@ from .views import DjangoHostingView, RailsHostingView, PaymentVMView,\
|
||||||
OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
|
OrdersHostingListView, OrdersHostingDetailView, VirtualMachinesPlanListView,\
|
||||||
VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \
|
VirtualMachineView, GenerateVMSSHKeysView, OrdersHostingDeleteView, NotificationsView, \
|
||||||
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\
|
MarkAsReadNotificationView, PasswordResetView, PasswordResetConfirmView, HostingPricingView,\
|
||||||
CreateVirtualMachinesView
|
CreateVirtualMachinesView, HostingBillListView, HostingBillDetailView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'index/?$', IndexView.as_view(), name='index'),
|
url(r'index/?$', IndexView.as_view(), name='index'),
|
||||||
|
@ -16,6 +16,8 @@ urlpatterns = [
|
||||||
url(r'payment/?$', PaymentVMView.as_view(), name='payment'),
|
url(r'payment/?$', PaymentVMView.as_view(), name='payment'),
|
||||||
url(r'orders/?$', OrdersHostingListView.as_view(), name='orders'),
|
url(r'orders/?$', OrdersHostingListView.as_view(), name='orders'),
|
||||||
url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'),
|
url(r'orders/(?P<pk>\d+)/?$', OrdersHostingDetailView.as_view(), name='orders'),
|
||||||
|
url(r'bills/?$', HostingBillListView.as_view(), name='bills'),
|
||||||
|
url(r'bills/(?P<pk>\d+)/?$', HostingBillDetailView.as_view(), name='bills'),
|
||||||
url(r'cancel_order/(?P<pk>\d+)/?$', OrdersHostingDeleteView.as_view(), name='delete_order'),
|
url(r'cancel_order/(?P<pk>\d+)/?$', OrdersHostingDeleteView.as_view(), name='delete_order'),
|
||||||
url(r'create-virtual-machine/?$', CreateVirtualMachinesView.as_view(), name='create-virtual-machine'),
|
url(r'create-virtual-machine/?$', CreateVirtualMachinesView.as_view(), name='create-virtual-machine'),
|
||||||
url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'),
|
url(r'my-virtual-machines/?$', VirtualMachinesPlanListView.as_view(), name='virtual_machines'),
|
||||||
|
|
|
@ -8,6 +8,7 @@ from django.views.generic import View, CreateView, FormView, ListView, DetailVie
|
||||||
DeleteView, TemplateView, UpdateView
|
DeleteView, TemplateView, UpdateView
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
|
from django.contrib import messages
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
|
|
||||||
|
@ -24,11 +25,14 @@ from utils.stripe_utils import StripeUtils
|
||||||
from utils.forms import BillingAddressForm, PasswordResetRequestForm
|
from utils.forms import BillingAddressForm, PasswordResetRequestForm
|
||||||
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin
|
from utils.views import PasswordResetViewMixin, PasswordResetConfirmViewMixin, LoginViewMixin
|
||||||
from utils.mailer import BaseEmail
|
from utils.mailer import BaseEmail
|
||||||
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, UserHostingKey
|
from .models import VirtualMachineType, VirtualMachinePlan, HostingOrder, HostingBill, UserHostingKey
|
||||||
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm
|
from .forms import HostingUserSignupForm, HostingUserLoginForm, UserHostingKeyForm
|
||||||
from .mixins import ProcessVMSelectionMixin
|
from .mixins import ProcessVMSelectionMixin
|
||||||
from .opennebula_functions import HostingManageVMAdmin, OpenNebulaManager
|
from .opennebula_functions import HostingManageVMAdmin, OpenNebulaManager
|
||||||
|
|
||||||
|
from oca.exceptions import OpenNebulaException
|
||||||
|
from oca.pool import WrongNameError
|
||||||
|
|
||||||
|
|
||||||
class DjangoHostingView(ProcessVMSelectionMixin, View):
|
class DjangoHostingView(ProcessVMSelectionMixin, View):
|
||||||
template_name = "hosting/django.html"
|
template_name = "hosting/django.html"
|
||||||
|
@ -317,6 +321,8 @@ class PaymentVMView(LoginRequiredMixin, FormView):
|
||||||
# Create a Hosting Order
|
# Create a Hosting Order
|
||||||
order = HostingOrder.create(vm_plan=plan, customer=customer,
|
order = HostingOrder.create(vm_plan=plan, customer=customer,
|
||||||
billing_address=billing_address)
|
billing_address=billing_address)
|
||||||
|
# Create a Hosting Bill
|
||||||
|
bill = HostingBill.create(customer=customer, billing_address=billing_address)
|
||||||
|
|
||||||
# Make stripe charge to a customer
|
# Make stripe charge to a customer
|
||||||
stripe_utils = StripeUtils()
|
stripe_utils = StripeUtils()
|
||||||
|
@ -378,7 +384,6 @@ class OrdersHostingDetailView(PermissionRequiredMixin, LoginRequiredMixin, Detai
|
||||||
permission_required = ['view_hostingorder']
|
permission_required = ['view_hostingorder']
|
||||||
model = HostingOrder
|
model = HostingOrder
|
||||||
|
|
||||||
|
|
||||||
class OrdersHostingListView(LoginRequiredMixin, ListView):
|
class OrdersHostingListView(LoginRequiredMixin, ListView):
|
||||||
template_name = "hosting/orders.html"
|
template_name = "hosting/orders.html"
|
||||||
login_url = reverse_lazy('hosting:login')
|
login_url = reverse_lazy('hosting:login')
|
||||||
|
@ -532,3 +537,37 @@ class VirtualMachineView(PermissionRequiredMixin, LoginRequiredMixin, View):
|
||||||
email.send()
|
email.send()
|
||||||
|
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
return HttpResponseRedirect(self.get_success_url())
|
||||||
|
|
||||||
|
class HostingBillListView(LoginRequiredMixin, ListView):
|
||||||
|
template_name = "hosting/bills.html"
|
||||||
|
login_url = reverse_lazy('hosting:login')
|
||||||
|
context_object_name = "users"
|
||||||
|
model = StripeCustomer
|
||||||
|
paginate_by = 10
|
||||||
|
ordering = '-id'
|
||||||
|
|
||||||
|
class HostingBillDetailView(PermissionRequiredMixin, LoginRequiredMixin, DetailView):
|
||||||
|
template_name = "hosting/bill_detail.html"
|
||||||
|
login_url = reverse_lazy('hosting:login')
|
||||||
|
permission_required = ['view_hostingview']
|
||||||
|
context_object_name = "bill"
|
||||||
|
model = HostingBill
|
||||||
|
|
||||||
|
def get_object(self, queryset=None):
|
||||||
|
#Get HostingBill for primary key (Select from customer users)
|
||||||
|
pk = self.kwargs['pk']
|
||||||
|
object = HostingBill.objects.filter(customer__id=pk).first()
|
||||||
|
if object is None:
|
||||||
|
self.template_name = 'hosting/bill_error.html'
|
||||||
|
return object
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
# Get context
|
||||||
|
context = super(DetailView, self).get_context_data(**kwargs)
|
||||||
|
# Get vms
|
||||||
|
try:
|
||||||
|
context['vms'] = self.get_object().get_vms()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
Loading…
Reference in a new issue