# 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.contrib.auth.decorators import login_required from django.http import HttpResponse from django.urls import reverse from payments import get_payment_model, RedirectNeeded, PaymentStatus from dash.models import Instance from django.db.models import Q from infrastructure.utils import create_vm_if_not_exists def default_ctx(title: str, username: str): """ Default context for all dashboard """ return { "title": title, "username": username, } @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) Payment = get_payment_model() now = datetime.now(tz=timezone.utc) delta = now - timedelta(seconds=(60 * 60 * 24 * 30)) # one month payment = None for p in Payment.objects.filter(date__gt=(delta), instance_name=instance_name): if p.status == PaymentStatus.CONFIRMED: return HttpResponse("BAD REQUEST: Already paid", status=400) elif any([p.status == PaymentStatus.INPUT, p.status == PaymentStatus.WAITING]): if payment is None: payment = p else: print(f"Duplicate payment {p}, deleting in favor of {payment}") p.delete() if payment is None: print("Payment not found, generating new payment") payment = Payment.objects.create( variant="stripe", # this is the variant from PAYMENT_VARIANTS instance=instance, ) return redirect(reverse("billing.invoice.details", args=(payment.public_ref,))) @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 ) 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")