# 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 enum import Enum, unique from urllib.parse import urlparse, urlunparse from datetime import datetime, timedelta, timezone from payments import get_payment_model, RedirectNeeded, PaymentStatus from django.core.mail import send_mail from django.urls import reverse from django.template.loader import render_to_string from django.contrib.auth.models import User from django.conf import settings from django.shortcuts import get_object_or_404 from dash.models import Instance Payment = get_payment_model() def __get_delta(): now = datetime.now(tz=timezone.utc) delta = now - timedelta(seconds=(60 * 60 * 24 * 30)) # one month return delta def get_invoice_link(payment: Payment): invoice_link = reverse("billing.invoice.details", args=(payment.public_ref,)) parsed = urlparse(settings.PAYMENT_HOST) return urlunparse((parsed.scheme, parsed.netloc, invoice_link, "", "", "")) def payment_fullfilled(instance: Instance) -> bool: delta = __get_delta() payment = None for p in Payment.objects.filter( date__gt=(delta), instance_name=instance.name, vm_deleted=False ): if p.status == PaymentStatus.CONFIRMED: return True return False @unique class GenerateInvoiceErrorCode(Enum): ALREADY_PAID = "already paid" DUPLICATE_PAYMENT = "DUPLICATE PAYMENT" def __str__(self) -> str: return self.name class GenerateInvoiceException(Exception): error: str code: GenerateInvoiceErrorCode def __init__(self, code: GenerateInvoiceErrorCode): self.error = str(code) self.code = code def __str__(self): return self.error def generate_invoice(instance: Instance) -> Payment: delta = __get_delta() payment = None for p in Payment.objects.filter( date__gt=(delta), instance_name=instance.name, vm_deleted=False ): if p.status == PaymentStatus.CONFIRMED: raise GenerateInvoiceException(code=GenerateInvoiceErrorCode.ALREADY_PAID) if 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 payment