Implement the Success page of the order

This commit is contained in:
amalelshihaby 2021-08-02 11:24:19 +02:00
parent 5564400ef8
commit 030a0cd501
13 changed files with 328 additions and 47 deletions

View file

@ -26,9 +26,10 @@ $( document ).ready(function() {
} else {
// The payment has succeeded
// Display a success message
modal_btn.attr('href', data.redirect).removeClass('sr-only sr-only-focusable');
$('#createvm-modal-title').text("Order Succeeded");
$('#createvm-modal-body').html("Order has been added and the instance will be ready soon");
window.location.href = '/order/success/';
// modal_btn.attr('href', data.redirect).removeClass('sr-only sr-only-focusable');
// $('#createvm-modal-title').text("Order Succeeded");
// $('#createvm-modal-body').html("Order has been added and the instance will be ready soon");
}
}
});

View file

@ -10,7 +10,7 @@ function setBrandIcon(brand) {
$(document).ready(function () {
var hasCreditcard = window.hasCreditcard || false;
if (!hasCreditcard && window.stripeKey) {
if (hasCreditcard && window.stripeKey) {
var stripe = Stripe(window.stripeKey);
if (window.pm_id == undefined) {
var element_style = {

View file

@ -16,16 +16,18 @@
<!-- Primary Navigation
============================== -->
{% url 'matrix:index' as index_url %}
{% url 'matrix:payments' as payments_url %}
<nav class="primary-menu navbar navbar-expand-lg">
<div id="header-nav" class="collapse navbar-collapse">
<ul class="navbar-nav mr-auto">
<li><a href="{% url 'matrix:index' %}">Home</a></li>
<li class="{% if request.path == index_url %}active{%endif%}"><a href="{{index_url}}">Home</a></li>
{% if not request.user.is_authenticated %}
<li><a href="">Pricing</a></li>
<li><a href="">Contact Us</a></li>
{% else %}
<li><a href="">Dashboard</a></li>
<li><a href="">Instances</a></li>
<li><a href=>Dashboard</a></li>
<li class="{% if request.path == payments_url %}active{%endif%}"><a href="{{payments_url}}">Payments</a></li>
<li><a href="">Help</a></li>
{% endif %}
</ul>

View file

@ -0,0 +1,49 @@
{% load static i18n %}
{% get_current_language as LANGUAGE_CODE %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Matrix Hosting by ungleich" />
<meta name="author" content="ungleich glarus ag" />
<title>
Hosting Invoice
</title>
<!-- Web Fonts
======================= -->
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Rubik:300,300i,400,400i,500,500i,700,700i,900,900i' type='text/css'>
<!-- Stylesheet
======================= -->
<link href="{% static 'matrixhosting/css/bootstrap.min.css' %}" rel="stylesheet" />
</head>
<body>
<!-- Container -->
<div class="container-fluid invoice-container">
<!-- Header -->
<header>
<div class="row align-items-center">
<div class="col-sm-7 text-center text-sm-start mb-3 mb-sm-0">
<img id="logo" src="{% static 'matrixhosting/images/logo.png' %}" title="matrixhosting" alt="matrixhosting" />
</div>
<div class="col-sm-5 text-center text-sm-end">
<h4 class="text-7 mb-0">Invoice</h4>
</div>
</div>
<hr>
</header>
<!-- Main Content -->
<main>
</main>
<!-- Footer -->
<footer class="text-center mt-4">
</footer>
</div>
</body>
</html>

View file

@ -10,7 +10,7 @@
<div class="row mt-3 mb-4">
<div class="col-lg-12 mx-auto mb-4">
<div class="row widget-steps">
<div class="col-4 step disabled">
<div class="col-4 step complete">
<div class="step-name">{%trans "Details" %}</div>
<div class="progress">
<div class="progress-bar"></div>
@ -186,7 +186,7 @@ aria-hidden="true" data-backdrop="static" data-keyboard="false">
</div>
</div>
<div class="modal-footer mt-4">
<a id="createvm-modal-done-btn" class="btn btn-success btn-ok btn-wide sr-only sr-only-focusable" href="">{% trans "OK" %}</a>
<a id="createvm-modal-done-btn" class="btn btn-success btn-ok btn-wide sr-only sr-only-focusable" href="{% url 'matrix:order_success' %}">{% trans "OK" %}</a>
<button id="createvm-modal-close-btn" type="button" class="btn btn-danger btn-ok btn-wide sr-only sr-only-focusable" data-dismiss="modal" aria-label="create-vm-close">{% trans "Close" %}</button>
</div>
</div>
@ -196,16 +196,11 @@ aria-hidden="true" data-backdrop="static" data-keyboard="false">
{% endblock %}
{% block js_extra %}
{% if stripe_key %}
{% get_current_language as LANGUAGE_CODE %}
<script type="text/javascript">
var error_url = '{{ error_msg.redirect }}';
var success_url = '{{ success_msg.redirect }}';
</script>
{%endif%}
<script type="text/javascript">
var error_url = '{{ error_msg.redirect }}';
var success_url = '{{ success_msg.redirect }}';
</script>
<!-- jQuery -->
<script src="https://js.stripe.com/v3/"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"></script>
<!-- Custom JS -->
<script type="text/javascript" src="{% static 'matrixhosting/js/order.js' %}"></script>

View file

@ -233,9 +233,9 @@
<label class="custom-control-label" for="new-card"><h6 class="mb-0">{% trans "Add New Card" %}</h6></label>
</div>
<div class="text-right">
<button id="checkout-btn" class="btn btn-primary btn-wide" type="submit" name="payment-button">{%trans "Checkout" %}</button>
<button id="checkout-btn" class="btn btn-primary btn-wide" style="display:none;" type="submit" name="payment-button">{%trans "Checkout" %}</button>
</div>
<div id="newcard">
<div id="newcard" style="display:none;">
<div class="card-details-box p-4 bg-light">
{% include "matrixhosting/includes/_card.html" %}
</div>

View file

@ -0,0 +1,56 @@
{% extends "matrixhosting/base.html" %}
{% load static i18n %}
{% block title %} Request Details {% endblock %}
{% block content %}
<div class="container">
<div class="row mt-3 mb-4">
<div class="col-lg-12 mx-auto mb-4">
<div class="row widget-steps">
<div class="col-4 step complete">
<div class="step-name">{%trans "Details" %}</div>
<div class="progress">
<div class="progress-bar"></div>
</div>
<a href="#" class="step-dot"></a>
</div>
<div class="col-4 step complete">
<div class="step-name">{%trans "Confirm" %}</div>
<div class="progress">
<div class="progress-bar"></div>
</div>
<a href="#" class="step-dot"></a>
</div>
<div class="col-4 step complete">
<div class="step-name">{%trans "Success" %}</div>
<div class="progress">
<div class="progress-bar"></div>
</div>
<a href="#" class="step-dot"></a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-9 col-lg-7 col-xl-6 mx-auto">
<div class="bg-white text-center shadow-sm rounded p-3 pt-sm-4 pb-sm-5 px-sm-5 mb-4">
<div class="my-4">
<p class="text-success text-20 line-height-07"><i class="fas fa-check-circle"></i></p>
<p class="text-success text-8 font-weight-500 line-height-07">{%trans "Success!" %}</p>
<p class="lead">{%trans "Order has been successfully added" %}</p>
</div>
<p class="text-3 mb-4">{%trans "Your current balance is" %}<span class="text-4 font-weight-500"> {{balance}} CHF. </span>{%trans "See transaction details under" %} <a class="btn-link" href="{% url 'matrix:payments' %}">{%trans "Payments" %}</a>.</p>
<a href="{% url 'matrix:invoice_download' %}" class="btn btn-white border border-success text-success" role="button"><i class="fas fa-print"></i> {%trans "Download Invoice" %}</a>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js_extra %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"></script>
<!-- Custom JS -->
<script type="text/javascript" src="{% static 'matrixhosting/js/order.js' %}"></script>
{% endblock js_extra %}

View file

@ -0,0 +1,124 @@
{% extends "matrixhosting/base.html" %}
{% load static i18n %}
{% block title %} Payments {% endblock %}
{% block content %}
<div class="container">
<div class="bg-white shadow-md rounded p-4 m-4">
<div class="row">
<div class="col-md-3">
<ul class="nav nav-tabs flex-column" id="myTabVertical" role="tablist">
<li class="nav-item"> <a class="nav-link active" id="first-tab" data-toggle="tab" href="#transactions" role="tab" aria-controls="firstTab" aria-selected="true">All Transactions</a> </li>
<li class="nav-item"> <a class="nav-link" id="fourth-tab" data-toggle="tab" href="#cards" role="tab" aria-controls="fourthTab" aria-selected="false">Payment Methods</a> </li>
</ul>
</div>
<div class="col-md-9">
<div class="tab-content my-3" id="myTabContentVertical">
<div class="tab-pane fade show active" id="transactions" role="tabpanel" aria-labelledby="transactions">
<div class="">
<!-- Filter
============================================= -->
<div class="row">
<div class="col mb-2">
<form id="filterTransactions" method="post">
<div class="form-row">
<!-- Date Range
========================= -->
<div class="col-sm-6 col-md-6 form-group">
<input id="dateRange" type="text" class="form-control" placeholder="Date Range">
<span class="icon-inside"><i class="fas fa-calendar-alt"></i></span>
</div>
<div class="col col-sm-6 text-right text-2">
<div class="featured-box float-right style-3">
<div class="featured-box-icon text-9 text-light"> <i class="fas fa-wallet"></i> </div>
<h3 class="text-6 font-weight-400 text-dark">{{balance}} CHF</h3>
<p class="text-muted text-3 opacity-8">{% trans "Available Balance"%}</p>
</div>
</div>
<!-- All Filters
================================ -->
<div class="col-12 mb-3" id="allFilters">
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="allTransactions" name="allFilters" class="custom-control-input" checked="">
<label class="custom-control-label" for="allTransactions">{% trans "All Transactions"%}</label>
</div>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="withdrawal" name="allFilters" class="custom-control-input">
<label class="custom-control-label" for="withdrawal">{% trans "Withdrawal"%}</label>
</div>
<div class="custom-control custom-radio custom-control-inline">
<input type="radio" id="deposit" name="allFilters" class="custom-control-input">
<label class="custom-control-label" for="deposit">{% trans "Deposit"%}</label>
</div>
</div>
<!-- All Filters End -->
</div>
</form>
</div>
</div>
<!-- Filter End -->
<!-- All Transactions
============================================= -->
<div class="bg-white shadow-sm border border-light rounded py-4 mb-4">
<h3 class="text-5 font-weight-400 d-flex align-items-center px-4 mb-4">{% trans "All Transactions"%}</h3>
<!-- Title
=============================== -->
<div class="transaction-title py-2 px-4">
<div class="row">
<div class="col-1 col-sm-1 text-center"><span class="">{% trans "ID"%}</span></div>
<div class="col-2 col-sm-2 text-center"><span class="">{% trans "Date"%}</span></div>
<div class="col col-sm-4">{% trans "Description" %}</div>
<div class="col-auto col-sm-2 d-none d-sm-block text-center">{% trans "Type"%}</div>
<div class="col-3 col-sm-3 text-right">{% trans "Amount"%}</div>
</div>
</div>
<!-- Title End -->
<!-- Transaction List
=============================== -->
<div class="transaction-list">
{% for payment in object_list %}
<div class="transaction-item px-4 py-3" data-id={{payment.id}}>
<div class="row align-items-center flex-row">
<div class="col-1 col-sm-1 text-center"> <span class="d-block text-3 font-weight-400">#{{payment.id}}</span></div>
<div class="col-2 col-sm-2 text-center"> <span class="d-block text-3 font-weight-300">{{payment.timestamp|date:"M d, Y"}}</span> <span class="d-block text-1 font-weight-300 text-uppercase">{{payment.timestamp|date:"H:i"}}</span> </div>
<div class="col col-sm-4"> <span class="d-block text-muted text-3">{{payment.notes}}</span></div>
<div class="col-auto col-sm-2 d-none d-sm-block text-center text-2"> <span class=" text-uppercase">{{payment.type}}</span> </div>
<div class="col-3 col-sm-3 text-right text-3"> <span class="text-nowrap">{% if payment.type == 'withdraw' %}- {%else%}+ {%endif%}{{payment.amount}}</span> <span class="text-1 text-uppercase">({{payment.currency}})</span> </div>
</div>
</div>
{%endfor%}
</div>
<!-- Transaction List End -->
<!-- Pagination will handled later
============================================= -->
<ul class="pagination justify-content-center mt-4 mb-0" style="display: none;">
<li class="page-item disabled"> <a class="page-link" href="#" tabindex="-1"><i class="fas fa-angle-left"></i></a> </li>
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item active"> <a class="page-link" href="#">2 <span class="sr-only">(current)</span></a> </li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item d-flex align-content-center flex-wrap text-muted text-5 mx-1">......</li>
<li class="page-item"><a class="page-link" href="#">15</a></li>
<li class="page-item"> <a class="page-link" href="#"><i class="fas fa-angle-right"></i></a> </li>
</ul>
<!-- Paginations end -->
</div>
<!-- All Transactions End -->
</div>
</div>
<div class="tab-pane fade" id="cards" role="tabpanel" aria-labelledby="cards">
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js_extra %}
{% endblock js_extra %}

View file

@ -2,13 +2,16 @@ from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from .views import IndexView, OrderPaymentView, OrderDetailsView, Dashboard
from .views import *
app_name = 'matrixhosting'
urlpatterns = [
path('order/new/', OrderPaymentView.as_view(), name='payment'),
path('order/confirm/', OrderDetailsView.as_view(), name='order_confirmation'),
path('order/success/', OrderSuccessView.as_view(), name='order_success'),
path('order/invoice/download', InvoiceDownloadView.as_view(), name='invoice_download'),
path('payments/', PaymentsView.as_view(), name='payments'),
path('dashboard/', Dashboard.as_view(), name='dashboard'),
path('', IndexView.as_view(), name='index'),
]

19
matrixhosting/utils.py Normal file
View file

@ -0,0 +1,19 @@
import os
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from django.conf import settings
from xhtml2pdf import pisa
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
# pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
links = lambda uri, rel: os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ''))
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")),dest=result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None

View file

@ -15,7 +15,7 @@ from matrixhosting.forms import InitialRequestForm, RequestHostedVMForm, Billing
from django.urls import reverse
from django.conf import settings
from django.http import (
HttpResponseRedirect, JsonResponse
HttpResponseRedirect, JsonResponse, HttpResponse
)
from rest_framework import viewsets, permissions
@ -27,6 +27,7 @@ from uncloud_pay.selectors import get_billing_address_for_user, has_enough_balan
import uncloud_pay.stripe as uncloud_stripe
from .models import VMInstance
from .serializers import *
from .utils import render_to_pdf
logger = logging.getLogger(__name__)
@ -156,8 +157,6 @@ class OrderPaymentView(FormView):
amount = get_balance_for_user(self.request.user) - decimal.Decimal(pricing["total"])
if (amount < 0):
payment_id = Payment.deposit(request.user, abs(amount), source='stripe')
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>")
print(payment_id)
self.request.session['pricing'] = pricing
self.request.session['order'] = specs
self.request.session['vat_validation_status'] = vat_validation_status
@ -230,6 +229,42 @@ def finalize_order(request, customer, billing_address,
)
return order
class OrderSuccessView(DetailView):
template_name = "matrixhosting/order_success.html"
context_object_name = "order"
model = Order
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
def get(self, request, *args, **kwargs):
context = {
'order': self.request.session.get('order'),
'balance': get_balance_for_user(self.request.user)
}
# if ('order' not in request.session):
# return HttpResponseRedirect(reverse('matrix:index'))
return render(request, self.template_name, context)
class InvoiceDownloadView(View):
def get(self, request, *args, **kwargs):
data = {
'today': datetime.date.today(),
'amount': 39.99,
'customer_name': 'Cooper Mann',
'order_id': 1233434,
}
pdf = render_to_pdf('matrixhosting/invoice.html', data)
if pdf:
response = HttpResponse(pdf, content_type='application/pdf')
content = "inline; filename=invoice.pdf"
content = "attachment; filename=invoice.pdf"
response['Content-Disposition'] = content
return response
return HttpResponse("Not found")
class Dashboard(ListView):
template_name = "matrixhosting/dashboard.html"
@ -248,28 +283,6 @@ class Dashboard(ListView):
return JsonResponse({'message': 'Successfully Cancelled'})
def get_error_response_dict(request):
response = {
'status': False,
'redirect': "{url}#{section}".format(
url=(reverse('matrix:payment')),
section='payment_error'
),
'msg_title': str(_('Error.')),
'msg_body': str(
_('There was a payment related error.'
' On close of this popup, you will be redirected back to'
' the payment page.'))
}
return response
def show_error(msg, request):
messages.add_message(request, messages.ERROR, msg,
extra_tags='failed_payment')
return JsonResponse(get_error_response_dict(request))
class MachineViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = VMInstanceSerializer
permission_classes = [permissions.IsAuthenticated]
@ -278,3 +291,21 @@ class MachineViewSet(viewsets.ReadOnlyModelViewSet):
return VMInstance.objects.filter(owner=self.request.user)
class PaymentsView(ListView):
template_name = "matrixhosting/payments.html"
model = Payment
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
def get_context_data(self, **kwargs):
context = super(PaymentsView, self).get_context_data(**kwargs)
context.update({
'balance': get_balance_for_user(self.request.user)
})
return context
def get_queryset(self):
return Payment.objects.filter(owner=self.request.user)

View file

@ -8,6 +8,7 @@ psycopg2
ldap3
django-allauth
xmltodict
xhtml2pdf
parsedatetime
# Follow are for creating graph models
pyparsing

View file

@ -82,7 +82,7 @@ class Payment(models.Model):
choices = (
('withdraw', 'Withdraw Money'),
('deposit', 'Deposit Money')
), null=False, blank=False, default="send")
), null=False, blank=False, default="deposit")
notes = models.TextField(default="", null=True, blank=True)