# Copyright © 2022 Aravinth Manivannan # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from datetime import datetime, timedelta, timezone from django.shortcuts import get_object_or_404, redirect, render from django.template.response import TemplateResponse from django.core.mail import send_mail from django.contrib.auth.decorators import login_required from django.http import HttpResponse from django.template.loader import render_to_string from django.urls import reverse from django.db.models import Q from django.conf import settings from payments import get_payment_model, RedirectNeeded, PaymentStatus from dash.models import Instance from infrastructure.utils import create_vm_if_not_exists from dash.utils import footer_ctx from .utils import ( generate_invoice as generate_invoice_util, GenerateInvoiceErrorCode, GenerateInvoiceException, get_invoice_link, ) def default_ctx(title: str, username: str): """ Default context for all dashboard """ return { "title": title, "username": username, "footer": footer_ctx(), } @login_required def pending_invoices(request): PAGE_TITLE = "Pending Invoices" user = request.user Payment = get_payment_model() payments = Payment.objects.filter(~Q(status=PaymentStatus.CONFIRMED), paid_by=user) ctx = default_ctx(title=PAGE_TITLE, username=user.username) ctx["payments"] = payments return render(request, "billing/invoices/pending/index.html", context=ctx) @login_required def paid_invoices(request): PAGE_TITLE = "Payment Receipts" user = request.user Payment = get_payment_model() payments = Payment.objects.filter(status=PaymentStatus.CONFIRMED, paid_by=user) ctx = default_ctx(title=PAGE_TITLE, username=user.username) ctx["payments"] = payments return render(request, "billing/invoices/paid/index.html", context=ctx) @login_required def generate_invoice(request, instance_name: str): instance = get_object_or_404(Instance, name=instance_name, owned_by=request.user) try: payment = generate_invoice_util(instance=instance) return redirect(reverse("billing.invoice.details", args=(payment.public_ref,))) except GenerateInvoiceException as e: if e.code == GenerateInvoiceErrorCode.ALREADY_PAID: return HttpResponse("BAD REQUEST: Already paid", status=400) return redirect(reverse("dash.home")) @login_required def payment_details(request, payment_public_id): payment = get_object_or_404( get_payment_model(), public_ref=payment_public_id, paid_by=request.user ) try: form = payment.get_form(data=request.POST or None) except RedirectNeeded as redirect_to: return redirect(str(redirect_to)) PAGE_TITLE = f'Invoice for VM "{payment.instance_name}"' ctx = default_ctx(title=PAGE_TITLE, username=request.user.username) ctx["form"] = form ctx["payment"] = payment return render(request, "billing/index.html", ctx) @login_required def payment_success(request, payment_public_id): PAGE_TITLE = "Payment Success" ctx = default_ctx(title=PAGE_TITLE, username=request.user.username) payment = get_object_or_404( get_payment_model(), public_ref=payment_public_id, paid_by=request.user ) ctx = { "username": request.user.username, "payment": payment, "link": get_invoice_link(payment=payment), } body = render_to_string( "billing/emails/payment-receipt.txt", context=ctx, ) email = request.user.email sender = settings.DEFAULT_FROM_EMAIL send_mail( subject="[Gna!] Payment receipt for your Gna! VM", message=body, from_email=f"No reply Gna!<{sender}>", # TODO read from settings.py recipient_list=[email], ) return redirect(reverse("infra.create", args=(payment.instance_name,))) @login_required def payment_failure(request, payment_public_id): PAGE_TITLE = "Payment failure" payment = get_object_or_404( get_payment_model(), public_ref=payment_public_id, paid_by=request.user ) ctx = default_ctx(title=PAGE_TITLE, username=request.user.username) return HttpResponse(f"{payment} failed")