forked from uncloud/uncloud
Add the Pricing Page and update the pricing model
This commit is contained in:
parent
eb86c7e189
commit
8ca5b2d104
13 changed files with 287 additions and 78 deletions
|
@ -1,50 +1,3 @@
|
||||||
/*-------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
Template Name: Payyed
|
|
||||||
Description: Money Transfer and Online Payments HTML Template
|
|
||||||
Template URI: http://demo.harnishdesign.net/html/payyed
|
|
||||||
Author: Harnish Design
|
|
||||||
Author URI: https://themeforest.net/user/harnishdesign
|
|
||||||
|
|
||||||
|
|
||||||
=========================================
|
|
||||||
Table of Contents
|
|
||||||
=========================================
|
|
||||||
|
|
||||||
- Basic
|
|
||||||
- Helpers Classes
|
|
||||||
- Layouts
|
|
||||||
- Header
|
|
||||||
- Logo
|
|
||||||
- Primary Menu
|
|
||||||
- Secondary Nav
|
|
||||||
- Page Header
|
|
||||||
- Profile
|
|
||||||
- Dashboard
|
|
||||||
- Cards & Bank Account Page
|
|
||||||
- Blog
|
|
||||||
- Elements
|
|
||||||
- Featured Box
|
|
||||||
- Team
|
|
||||||
- Accordion & Toggle
|
|
||||||
- Tabs
|
|
||||||
- Easy Responsive Tab Accordion
|
|
||||||
- Custom Background
|
|
||||||
- Owl Carousel
|
|
||||||
- Brands Grid
|
|
||||||
- Banner
|
|
||||||
- Simple ul
|
|
||||||
- Steps Progress bar
|
|
||||||
- Footer
|
|
||||||
- Social Icons
|
|
||||||
- Back to Top
|
|
||||||
- Extra
|
|
||||||
|
|
||||||
-------------------------------------------------------------*/
|
|
||||||
/* =================================== */
|
|
||||||
/* Basic Style
|
|
||||||
/* =================================== */
|
|
||||||
body, html {
|
body, html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -559,7 +512,7 @@ body, html {
|
||||||
.section {
|
.section {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 104px 0;
|
padding: 104px 0;
|
||||||
padding: 6.5rem 0;
|
padding: 5.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767.98px) {
|
@media (max-width: 767.98px) {
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
<h4 class="text-3 text-white text-uppercase font-weight-400 mb-3">{% trans "Information" %}</h4>
|
<h4 class="text-3 text-white text-uppercase font-weight-400 mb-3">{% trans "Information" %}</h4>
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
<li class="nav-item"> <a class="nav-link" href="#">{% trans "About Us" %}</a></li>
|
<li class="nav-item"> <a class="nav-link" href="#">{% trans "About Us" %}</a></li>
|
||||||
<li class="nav-item"> <a class="nav-link" href="#">{% trans "Subscription Plans" %}</a></li>
|
<li class="nav-item"> <a class="nav-link" href="{% url 'matrix:pricing' %}">{% trans "Subscription Plans" %}</a></li>
|
||||||
<li class="nav-item"> <a class="nav-link" href="#">{% trans "Affiliate" %}</a></li>
|
<li class="nav-item"> <a class="nav-link" href="{% url 'matrix:pricing' %}">{% trans "Fees" %}</a></li>
|
||||||
<li class="nav-item"> <a class="nav-link" href="#">{% trans "Fees" %}</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 col-md mb-3 mb-md-0">
|
<div class="col-sm-6 col-md mb-3 mb-md-0">
|
||||||
|
|
|
@ -20,18 +20,19 @@
|
||||||
{% url 'matrix:orders' as orders_url %}
|
{% url 'matrix:orders' as orders_url %}
|
||||||
{% url 'matrix:instances' as instances_url %}
|
{% url 'matrix:instances' as instances_url %}
|
||||||
{% url 'matrix:billing' as payments_url %}
|
{% url 'matrix:billing' as payments_url %}
|
||||||
|
{% url 'matrix:pricing' as pricing_url %}
|
||||||
<nav class="primary-menu navbar navbar-expand-lg">
|
<nav class="primary-menu navbar navbar-expand-lg">
|
||||||
<div id="header-nav" class="collapse navbar-collapse">
|
<div id="header-nav" class="collapse navbar-collapse">
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<li class="{% if request.path == index_url %}active{%endif%}"><a href="{{index_url}}">{%trans "Home" %}</a></li>
|
<li class="{% if request.path == index_url %}active{%endif%}"><a href="{{index_url}}">{%trans "Home" %}</a></li>
|
||||||
{% if not request.user.is_authenticated %}
|
{% if not request.user.is_authenticated %}
|
||||||
<li><a href="">Pricing</a></li>
|
<li class="{% if pricing_url in request.path %}active{%endif%}" ><a href="{% url 'matrix:pricing' %}">{%trans "Pricing" %}</a></li>
|
||||||
<li><a href="">Contact Us</a></li>
|
<li><a href="">{%trans "Contact Us" %}</a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="{% if orders_url in request.path %}active{%endif%}"><a href="{{orders_url}}">Orders</a></li>
|
<li class="{% if orders_url in request.path %}active{%endif%}"><a href="{{orders_url}}">{%trans "Orders" %}</a></li>
|
||||||
<li class="{% if instances_url in request.path %}active{%endif%}"><a href="{{instances_url}}">Instances</a></li>
|
<li class="{% if instances_url in request.path %}active{%endif%}"><a href="{{instances_url}}">{%trans "Instances" %}</a></li>
|
||||||
<li class="{% if payments_url in request.path %}active{%endif%}"><a href="{{payments_url}}">{%trans "Billing" %}</a></li>
|
<li class="{% if payments_url in request.path %}active{%endif%}"><a href="{{payments_url}}">{%trans "Billing" %}</a></li>
|
||||||
<li><a href="">Help</a></li>
|
<li><a href="">{%trans "Help" %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
195
matrixhosting/templates/matrixhosting/pricing.html
Normal file
195
matrixhosting/templates/matrixhosting/pricing.html
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
{% extends "matrixhosting/base.html" %}
|
||||||
|
|
||||||
|
{% load static i18n %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
|
||||||
|
<section class="hero-wrap section">
|
||||||
|
<div class="hero-mask opacity-6 bg-dark"></div>
|
||||||
|
<div class="hero-bg hero-bg-scroll" style="background-image:url({% static 'matrixhosting/images/how.jpg' %});"></div>
|
||||||
|
<div class="hero-content">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 col-lg-7 col-xl-6 text-center text-lg-left">
|
||||||
|
<h1 class="text-11 text-white mb-4">{%trans "We Promise Low Fees" %}<br>
|
||||||
|
{%trans "and No Extra Charges" %}</h1>
|
||||||
|
<p class="text-5 text-white line-height-4 mb-4">{% trans "Signing up today and join the matrix global networks. Create your account today and start!" %}</p>
|
||||||
|
<a href="{% url 'matrix:payment' %}" class="btn btn-primary my-2 mr-2">{%trans "Open a Free Account" %}</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section bg-white">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="text-9">{%trans "How the pricing works?" %}</h2>
|
||||||
|
<p class="lead mb-5">{%trans "We try to be as transparent as possible for our Matrix pricing. The pricing is made of 2 essential parts." %}</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-lg-6 mb-5 mb-lg-0">
|
||||||
|
<div class="featured-box">
|
||||||
|
<h3>{%trans "One-time set up fee" %}</h3>
|
||||||
|
<p class="text-3">{%trans "For initially setting up the Matrix instance for you. We set up the Matrix and also customize* the login page with your own logo and text." %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-6 mb-5 mb-sm-0">
|
||||||
|
<div class="featured-box">
|
||||||
|
<h3>{%trans "Monthly maintenance fee" %}</h3>
|
||||||
|
<p class="text-3">{%trans "includes the price of a dedicated virtual machine(VM)** and the fee for maintaining the service" %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-lg-6 mb-5 mb-lg-0">
|
||||||
|
<p class="text-3">{%trans "Further customization such as favicon, background and more is possible at additional fee, get in touch with us to learn more." %}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-6 mb-5 mb-lg-0">
|
||||||
|
<p class="text-3">{%trans "The number of users or size of rooms depend on the size of your VM, and you can scale them anytime you want. The extention will be done according to our standard VM pricing." %}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="text-9 text-center text-uppercase font-weight-400">{%trans "Matrix Light" %}</h2>
|
||||||
|
<p class="lead text-center mb-5">{%trans "Matrix Light is an economic and practical plan for using Matrix chat. If you are not familiar with Matrix and want to start chatting on it you can start with Matrix Light plans. You can easily upgrading to bigger Matrix Light or to Matrix Pro anytime you want." %}</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-lg-4 mb-4">
|
||||||
|
<div class="bg-white shadow-sm rounded">
|
||||||
|
<h5 class="bg-light p-3">{%trans "Matrix Light 1 (47.5 CHF/Month)" %}</h5>
|
||||||
|
<div class="text-2 px-3">
|
||||||
|
<ul class="list-unstyled line-height-5">
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Suitable for chatting with up to 25 users" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "VM with 1 Core, 2 GB RAM, 10 GB SSD and 100 GB HDD" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Maintenance fee 30 CHF/month included" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Application firewall included" %}</li>
|
||||||
|
<li class="mt-2"><a href="{% url 'matrix:payment' %}?product=matrix-light-1">{%trans "Initial setup fee 50 CHF" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="py-3">
|
||||||
|
<a href="{% url 'matrix:payment' %}?product=matrix-light-1" class="btn btn-outline-primary btn-sm shadow-none">{%trans "Order Now!" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-4 mb-4">
|
||||||
|
<div class="bg-white shadow-sm rounded">
|
||||||
|
<h5 class="bg-light p-3">{%trans "Matrix Light 2 (66.5 CHF/Month)" %}</h5>
|
||||||
|
<div class="text-2 px-3">
|
||||||
|
<ul class="list-unstyled line-height-5">
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Suitable for chatting with up to 50 users" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "VM with 2 Core, 4 GB RAM, 10 GB SSD and 500 GB HDD" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Maintenance fee 30 CHF/month included" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Application firewall included" %}</li>
|
||||||
|
<li class="mt-2"><a href="{% url 'matrix:payment' %}?product=matrix-light-2">{%trans "Initial setup fee 50 CHF" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="py-3">
|
||||||
|
<a href="{% url 'matrix:payment' %}?product=matrix-light-2" class="btn btn-outline-primary btn-sm shadow-none">{%trans "Order Now!" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-4 mb-4">
|
||||||
|
<div class="bg-white shadow-sm rounded">
|
||||||
|
<h5 class="bg-light p-3">{%trans "Matrix Light 3 (92.5 CHF/Month)" %}</h5>
|
||||||
|
<div class="text-2 px-3">
|
||||||
|
<ul class="list-unstyled line-height-5">
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Suitable for chatting with up to 100 users" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "VM with 2 Core, 8 GB RAM, 10 GB SSD and 1000 GB HDD" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Maintenance fee 30 CHF/month included" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Application firewall included" %}</li>
|
||||||
|
<li class="mt-2"><a href="{% url 'matrix:payment' %}?product=matrix-light-3">{%trans "Initial setup fee 50 CHF" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="py-3">
|
||||||
|
<a href="{% url 'matrix:payment' %}?product=matrix-light-3" class="btn btn-outline-primary btn-sm shadow-none">{%trans "Order Now!" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="section bg-white">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="text-9 text-center text-uppercase font-weight-400">{%trans "Matrix Pro" %}</h2>
|
||||||
|
<p class="lead text-center mb-5">{%trans "For communities with more frequent and dynamic use, we recommend Matrix Pro plans. Matrix Pro Chat offers fast reaction and optimal perfomance. Matrix Pro is designed to fit the nature of Matrix which benefits a lot from memory caching." %}</p>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-lg-4 mb-4">
|
||||||
|
<div class="bg-white shadow-sm rounded">
|
||||||
|
<h5 class="bg-light p-3">{%trans "Matrix Pro 1 (108.5 CHF/Month)" %}</h5>
|
||||||
|
<div class="text-2 px-3">
|
||||||
|
<ul class="list-unstyled line-height-5">
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Suitable for communities up to 50 users" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "VM with 2 Cores, 16 GB RAM, 10 GB SSD and 200 GB HDD" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Maintenance fee 30 CHF/month included" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Application firewall included" %}</li>
|
||||||
|
<li class="mt-2"><a href="{% url 'matrix:payment' %}?product=matrix-pro-1">{%trans "Initial setup fee 50 CHF" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="py-3">
|
||||||
|
<a href="{% url 'matrix:payment' %}?product=matrix-pro-1" class="btn btn-outline-primary btn-sm shadow-none">{%trans "Order Now!" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-4 mb-4">
|
||||||
|
<div class="bg-white shadow-sm rounded">
|
||||||
|
<h5 class="bg-light p-3">{%trans "Matrix Pro 2 (322.5 CHF/Month)" %}</h5>
|
||||||
|
<div class="text-2 px-3">
|
||||||
|
<ul class="list-unstyled line-height-5">
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Suitable for communities with 50-100 users" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "VM with 4 Core, 64 GB RAM, 10 GB SSD and 1000 GB HDD" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Maintenance fee 30 CHF/month included" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Application firewall included" %}</li>
|
||||||
|
<li class="mt-2"><a href="{% url 'matrix:payment' %}?product=matrix-pro-2">{%trans "Initial setup fee 50 CHF" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="py-3">
|
||||||
|
<a href="{% url 'matrix:payment' %}?product=matrix-pro-2" class="btn btn-outline-primary btn-sm shadow-none">{%trans "Order Now!" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-4 mb-4">
|
||||||
|
<div class="bg-white shadow-sm rounded">
|
||||||
|
<h5 class="bg-light p-3">{%trans "Matrix Pro 3 (958.5 CHF/Month)" %}</h5>
|
||||||
|
<div class="text-2 px-3">
|
||||||
|
<ul class="list-unstyled line-height-5">
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Suitable for communities with 100+ users" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "VM with 8 Core, 200 GB RAM, 10 GB SSD and 5000 GB HDD" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Maintenance fee 30 CHF/month included" %}</li>
|
||||||
|
<li><i class="fas fa-check mr-2"></i> {%trans "Application firewall included" %}</li>
|
||||||
|
<li class="mt-2"><a href="{% url 'matrix:payment' %}?product=matrix-pro-3">{%trans "Initial setup fee 50 CHF" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="py-3">
|
||||||
|
<a href="{% url 'matrix:payment' %}?product=matrix-pro-3" class="btn btn-outline-primary btn-sm shadow-none">{%trans "Order Now!" %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="bg-light">
|
||||||
|
<div class="hero-content py-5">
|
||||||
|
<div class="container text-center">
|
||||||
|
<p class="lead">{%trans "Your usecase doesn't fit the offers below? We do custom-sized deployment for you. Get in touch with us by email or even on matrix, via" %} <a href="https://matrix.to/#/%23matrix:ungleich.ch">#matrix:ungleich.ch</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="bg-primary opacity-7">
|
||||||
|
<div class="hero-content py-5">
|
||||||
|
<div class="container text-center">
|
||||||
|
<h2 class="text-9 text-white">{%trans "Custom deployment consultancy" %}</h2>
|
||||||
|
<p class="lead text-white mb-4">{%trans "It is possible to integrate your Matrix instance into your other projects and apps. There are a lot of ways to best utilize the security and federation Matrix offers to best fit your usecase. Talk to us about your ideas and we will help you realise how to customize your Matrix. Get in touch with us via support@ungleich.ch and you will hear from our team." %}
|
||||||
|
</p>
|
||||||
|
<a href="mailto:support@ungleich.ch" class="btn btn-light">{%trans "Contact US" %}</a></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -38,7 +38,7 @@ class VMInstanceTestCase(TestCase):
|
||||||
'matrix_domain': '',
|
'matrix_domain': '',
|
||||||
})
|
})
|
||||||
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
||||||
ram_unit_price=4, storage_unit_price=0.02)
|
ram_unit_price=4, storage_ssd_unit_price=0.35, storage_hd_unit_price=0.02)
|
||||||
self.ba = BillingAddress.objects.create(
|
self.ba = BillingAddress.objects.create(
|
||||||
owner=self.user,
|
owner=self.user,
|
||||||
organization = 'Test org',
|
organization = 'Test org',
|
||||||
|
|
|
@ -16,5 +16,6 @@ urlpatterns = [
|
||||||
path('billing/bills', BillsView.as_view(), name='bills'),
|
path('billing/bills', BillsView.as_view(), name='bills'),
|
||||||
path('instances/', InstancesView.as_view(), name='instances'),
|
path('instances/', InstancesView.as_view(), name='instances'),
|
||||||
path('orders/', OrdersView.as_view(), name='orders'),
|
path('orders/', OrdersView.as_view(), name='orders'),
|
||||||
|
path('pricing/', PricingView.as_view(), name='pricing'),
|
||||||
path('', IndexView.as_view(), name='index'),
|
path('', IndexView.as_view(), name='index'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import decimal
|
import decimal
|
||||||
|
from django.views.generic.base import TemplateView
|
||||||
from stripe.error import CardError
|
from stripe.error import CardError
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
@ -32,6 +33,10 @@ from .utils import *
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PricingView(TemplateView):
|
||||||
|
template_name = "matrixhosting/pricing.html"
|
||||||
|
|
||||||
class IndexView(FormView):
|
class IndexView(FormView):
|
||||||
template_name = "matrixhosting/index.html"
|
template_name = "matrixhosting/index.html"
|
||||||
form_class = InitialRequestForm
|
form_class = InitialRequestForm
|
||||||
|
@ -80,6 +85,11 @@ class OrderPaymentView(FormView):
|
||||||
) if old_active else BillingAddressForm(
|
) if old_active else BillingAddressForm(
|
||||||
initial={'active': True, 'owner': self.request.user.id}
|
initial={'active': True, 'owner': self.request.user.id}
|
||||||
)
|
)
|
||||||
|
if self.request.GET.get('product', False):
|
||||||
|
matched_prod = Product.objects.filter(name=self.request.GET.get('product')).first()
|
||||||
|
if matched_prod:
|
||||||
|
self.request.session['order'] = matched_prod.config
|
||||||
|
|
||||||
details_form = InitialRequestForm(
|
details_form = InitialRequestForm(
|
||||||
initial=self.request.session.get('order', {'pricing_name': default_pricing.name})
|
initial=self.request.session.get('order', {'pricing_name': default_pricing.name})
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
ALLOWED_HOSTS=
|
ALLOWED_HOSTS=
|
||||||
STRIPE_KEY=
|
STRIPE_KEY=
|
||||||
STRIPE_PUBLIC_KEY=
|
STRIPE_PUBLIC_KEY=p
|
||||||
DATABASE_ENGINE=django.db.backends.sqlite3
|
DATABASE_ENGINE=django.db.backends.sqlite3
|
||||||
DATABASE_NAME=
|
DATABASE_NAME=
|
||||||
DATABASE_HOST=
|
DATABASE_HOST=
|
||||||
|
@ -16,4 +16,4 @@ GITLAB_PROJECT_ID=
|
||||||
GITLAB_OAUTH_TOKEN=
|
GITLAB_OAUTH_TOKEN=
|
||||||
GITLAB_AUTHOR_EMAIL=
|
GITLAB_AUTHOR_EMAIL=
|
||||||
GITLAB_AUTHOR_NAME=
|
GITLAB_AUTHOR_NAME=
|
||||||
WKHTMLTOPDF_CMD=
|
WKHTMLTOPDF_CMD=/usr/local/bin/wkhtmltopdf
|
23
uncloud_pay/migrations/0029_auto_20210817_1129.py
Normal file
23
uncloud_pay/migrations/0029_auto_20210817_1129.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 3.2.4 on 2021-08-17 11:29
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('uncloud_pay', '0028_bill_currency'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='pricingplan',
|
||||||
|
old_name='storage_unit_price',
|
||||||
|
new_name='storage_hd_unit_price',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='pricingplan',
|
||||||
|
name='storage_ssd_unit_price',
|
||||||
|
field=models.DecimalField(decimal_places=2, default=0, max_digits=7),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.4 on 2021-08-17 16:18
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('uncloud_pay', '0029_auto_20210817_1129'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='pricingplan',
|
||||||
|
name='monthly_maintenance_fees',
|
||||||
|
field=models.DecimalField(decimal_places=2, default=0, max_digits=7),
|
||||||
|
),
|
||||||
|
]
|
|
@ -571,13 +571,19 @@ class PricingPlan(models.Model):
|
||||||
set_up_fees = models.DecimalField(
|
set_up_fees = models.DecimalField(
|
||||||
max_digits=7, decimal_places=2, default=0
|
max_digits=7, decimal_places=2, default=0
|
||||||
)
|
)
|
||||||
|
monthly_maintenance_fees = models.DecimalField(
|
||||||
|
max_digits=7, decimal_places=2, default=0
|
||||||
|
)
|
||||||
cores_unit_price = models.DecimalField(
|
cores_unit_price = models.DecimalField(
|
||||||
max_digits=7, decimal_places=2, default=0
|
max_digits=7, decimal_places=2, default=0
|
||||||
)
|
)
|
||||||
ram_unit_price = models.DecimalField(
|
ram_unit_price = models.DecimalField(
|
||||||
max_digits=7, decimal_places=2, default=0
|
max_digits=7, decimal_places=2, default=0
|
||||||
)
|
)
|
||||||
storage_unit_price = models.DecimalField(
|
storage_hd_unit_price = models.DecimalField(
|
||||||
|
max_digits=7, decimal_places=2, default=0
|
||||||
|
)
|
||||||
|
storage_ssd_unit_price = models.DecimalField(
|
||||||
max_digits=7, decimal_places=2, default=0
|
max_digits=7, decimal_places=2, default=0
|
||||||
)
|
)
|
||||||
discount_name = models.CharField(max_length=255, null=True, blank=True)
|
discount_name = models.CharField(max_length=255, null=True, blank=True)
|
||||||
|
@ -591,7 +597,8 @@ class PricingPlan(models.Model):
|
||||||
'{} Setup'.format(self.set_up_fees.normalize()),
|
'{} Setup'.format(self.set_up_fees.normalize()),
|
||||||
'{}/Core'.format(self.cores_unit_price.normalize()),
|
'{}/Core'.format(self.cores_unit_price.normalize()),
|
||||||
'{}/GB RAM'.format(self.ram_unit_price.normalize()),
|
'{}/GB RAM'.format(self.ram_unit_price.normalize()),
|
||||||
'{}/GB SSD'.format(self.storage_unit_price.normalize()),
|
'{}/GB SSD'.format(self.storage_ssd_unit_price.normalize()),
|
||||||
|
'{}/GB HD'.format(self.storage_hd_unit_price.normalize()),
|
||||||
'{}% VAT'.format(self.vat_percentage.normalize())
|
'{}% VAT'.format(self.vat_percentage.normalize())
|
||||||
if not self.vat_inclusive else 'VAT-Incl',
|
if not self.vat_inclusive else 'VAT-Incl',
|
||||||
])
|
])
|
||||||
|
@ -926,13 +933,14 @@ class Order(models.Model):
|
||||||
def calculate_recurring_price(self):
|
def calculate_recurring_price(self):
|
||||||
try:
|
try:
|
||||||
config = json.loads(self.config)
|
config = json.loads(self.config)
|
||||||
recurring_price = 0
|
recurring_price = self.pricing_plan.monthly_maintenance_fees
|
||||||
if 'cores' in config:
|
if 'cores' in config:
|
||||||
recurring_price += self.pricing_plan.cores_unit_price * int(config['cores'])
|
recurring_price += self.pricing_plan.cores_unit_price * int(config['cores'])
|
||||||
if 'memory' in config:
|
if 'memory' in config:
|
||||||
recurring_price += self.pricing_plan.ram_unit_price * int(config['memory'])
|
recurring_price += self.pricing_plan.ram_unit_price * int(config['memory'])
|
||||||
if 'storage' in config:
|
if 'storage' in config:
|
||||||
recurring_price += self.pricing_plan.storage_unit_price * int(config['storage'])
|
#TODO Fix the ssd static value
|
||||||
|
recurring_price += (10 * self.pricing_plan.storage_ssd_unit_price) + (self.pricing_plan.storage_hd_unit_price * int(config['storage']))
|
||||||
|
|
||||||
vat_rate = VATRate.get_vat_rate(self.billing_address)
|
vat_rate = VATRate.get_vat_rate(self.billing_address)
|
||||||
vat_validation_status = "verified" if self.billing_address.vat_number_validated_on and self.billing_address.vat_number_verified else False
|
vat_validation_status = "verified" if self.billing_address.vat_number_validated_on and self.billing_address.vat_number_verified else False
|
||||||
|
@ -1171,7 +1179,7 @@ class BillRecord(models.Model):
|
||||||
@property
|
@property
|
||||||
def sum(self):
|
def sum(self):
|
||||||
if self.is_recurring_record:
|
if self.is_recurring_record:
|
||||||
return self.order.recurring_price * Decimal(self.quantity)
|
return round(float(self.order.recurring_price) * self.quantity, 2)
|
||||||
else:
|
else:
|
||||||
return self.order.one_time_price
|
return self.order.one_time_price
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ class OrderTestCase(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
||||||
ram_unit_price=4, storage_unit_price=0.02)
|
ram_unit_price=4, storage_ssd_unit_price=0.35, storage_hd_unit_price=0.02)
|
||||||
self.user = get_user_model().objects.create(
|
self.user = get_user_model().objects.create(
|
||||||
username='random_user',
|
username='random_user',
|
||||||
email='jane.random@domain.tld')
|
email='jane.random@domain.tld')
|
||||||
|
@ -140,7 +140,7 @@ class OrderTestCase(TestCase):
|
||||||
config=order_config)
|
config=order_config)
|
||||||
|
|
||||||
self.assertEqual(o.one_time_price, 0)
|
self.assertEqual(o.one_time_price, 0)
|
||||||
self.assertEqual(o.recurring_price, 13.0)
|
self.assertEqual(o.recurring_price, 16.5)
|
||||||
|
|
||||||
def test_change_order(self):
|
def test_change_order(self):
|
||||||
"""
|
"""
|
||||||
|
@ -160,7 +160,7 @@ class OrderTestCase(TestCase):
|
||||||
config=order_config)
|
config=order_config)
|
||||||
|
|
||||||
self.assertEqual(order1.one_time_price, 0)
|
self.assertEqual(order1.one_time_price, 0)
|
||||||
self.assertEqual(order1.recurring_price, 26.0)
|
self.assertEqual(order1.recurring_price, 29.5)
|
||||||
|
|
||||||
|
|
||||||
class ModifyOrderTestCase(TestCase):
|
class ModifyOrderTestCase(TestCase):
|
||||||
|
@ -176,7 +176,7 @@ class ModifyOrderTestCase(TestCase):
|
||||||
username='random_user',
|
username='random_user',
|
||||||
email='jane.random@domain.tld')
|
email='jane.random@domain.tld')
|
||||||
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
||||||
ram_unit_price=4, storage_unit_price=0.02)
|
ram_unit_price=4, storage_ssd_unit_price=0.35, storage_hd_unit_price=0.02)
|
||||||
self.order1_config = json.dumps({
|
self.order1_config = json.dumps({
|
||||||
'cores': 2,
|
'cores': 2,
|
||||||
'memory':4,
|
'memory':4,
|
||||||
|
@ -307,7 +307,7 @@ class BillTestCase(TestCase):
|
||||||
RecurringPeriod.populate_db_defaults()
|
RecurringPeriod.populate_db_defaults()
|
||||||
|
|
||||||
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
self.pricing_plan = PricingPlan.objects.create(name="PricingSample", set_up_fees=35, cores_unit_price=3,
|
||||||
ram_unit_price=4, storage_unit_price=0.02)
|
ram_unit_price=4, storage_ssd_unit_price=0.35, storage_hd_unit_price=0.02)
|
||||||
|
|
||||||
self.user_without_address = get_user_model().objects.create(
|
self.user_without_address = get_user_model().objects.create(
|
||||||
username='no_home_person',
|
username='no_home_person',
|
||||||
|
@ -431,9 +431,9 @@ class BillTestCase(TestCase):
|
||||||
self.assertEqual(order.billrecord_set.count(), 2)
|
self.assertEqual(order.billrecord_set.count(), 2)
|
||||||
record = BillRecord.objects.filter(bill=bill2, order=order).first()
|
record = BillRecord.objects.filter(bill=bill2, order=order).first()
|
||||||
self.assertEqual(record.is_recurring_record, True)
|
self.assertEqual(record.is_recurring_record, True)
|
||||||
self.assertEqual(record.price, 13)
|
self.assertEqual(record.price, 16.5)
|
||||||
self.assertEqual(record.quantity, 1)
|
self.assertEqual(record.quantity, 1)
|
||||||
self.assertEqual(record.sum, 13)
|
self.assertEqual(record.sum, 16.5)
|
||||||
|
|
||||||
def test_bill_one_time_one_bill_record(self):
|
def test_bill_one_time_one_bill_record(self):
|
||||||
"""
|
"""
|
||||||
|
@ -452,13 +452,13 @@ class BillTestCase(TestCase):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = self.order_product()
|
order = self.order_product()
|
||||||
self.assertEqual(order.recurring_price, 13.0)
|
self.assertEqual(order.recurring_price, 16.5)
|
||||||
bill = Bill.create_next_bill_for_user_address(self.user_addr)
|
bill = Bill.create_next_bill_for_user_address(self.user_addr)
|
||||||
self.assertEqual(order.billrecord_set.count(), 1)
|
self.assertEqual(order.billrecord_set.count(), 1)
|
||||||
record = order.billrecord_set.first()
|
record = order.billrecord_set.first()
|
||||||
self.assertEqual(record.price, 13)
|
self.assertEqual(record.price, 16.5)
|
||||||
self.assertEqual(record.quantity, 1)
|
self.assertEqual(record.quantity, 1)
|
||||||
self.assertEqual(bill.sum, 13)
|
self.assertEqual(bill.sum, 16.5)
|
||||||
|
|
||||||
|
|
||||||
def test_bill_creates_record_for_recurring_order(self):
|
def test_bill_creates_record_for_recurring_order(self):
|
||||||
|
|
|
@ -143,9 +143,10 @@ def get_order_total_with_vat(cores, memory, storage,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
recurring_price = (decimal.Decimal(cores) * pricing.cores_unit_price) + \
|
recurring_price = pricing.monthly_maintenance_fees + (decimal.Decimal(cores) * pricing.cores_unit_price) + \
|
||||||
(decimal.Decimal(memory) * pricing.ram_unit_price) + \
|
(decimal.Decimal(memory) * pricing.ram_unit_price) + \
|
||||||
(decimal.Decimal(storage) * (pricing.storage_unit_price))
|
(decimal.Decimal(10) * (pricing.storage_ssd_unit_price)) + \
|
||||||
|
(decimal.Decimal(storage) * (pricing.storage_hd_unit_price))
|
||||||
subtotal = pricing.set_up_fees + recurring_price
|
subtotal = pricing.set_up_fees + recurring_price
|
||||||
subtotal, subtotal_after_discount, price_after_discount_with_vat, vat, vat_percent, vat_amount, discount = \
|
subtotal, subtotal_after_discount, price_after_discount_with_vat, vat, vat_percent, vat_amount, discount = \
|
||||||
apply_vat_discount(subtotal, pricing, vat_rate, vat_validation_status)
|
apply_vat_discount(subtotal, pricing, vat_rate, vat_validation_status)
|
||||||
|
|
Loading…
Reference in a new issue