import logging from datetime import date, timedelta, timezone from django.conf import settings from django.template.loader import render_to_string from django_q.tasks import async_task, schedule from django_q.models import Schedule from django.db.models import Q from uncloud_pay.models import Bill, Payment from uncloud_pay.selectors import has_enough_balance, get_balance_for_user from .models import VMInstance log = logging.getLogger(__name__) def send_warning_email(bill, html_message): schedule('django.core.mail.send_mail', 'Renewal Warning', None, settings.RENEWAL_FROM_EMAIL, [bill.owner.email], html_message, schedule_type=Schedule.ONCE, next_run=timezone.now() + timedelta(hours=1)) def charge_open_bills(): un_paid_bills = Bill.objects.filter(status="new") for bill in un_paid_bills: date_diff = (date.today() - bill.due_date.date()).days # If there is not enough money in the account 7 days before renewal, the system sends a warning # If there is not enough money in the account 3 days before renewal, the system sends a 2nd warning # If on renewal date there is not enough money in the account, delete the instance if date_diff == 7: if not has_enough_balance(bill.owner): context = {'name': bill.owner.name, 'message': "You don't have enough balance for renewal... upload to your account _here"} html_message = render_to_string('matrixhosting/emails/renewal_warning.html', context) send_warning_email(bill, html_message) elif date_diff == 3: if not has_enough_balance(bill.owner): context = {'name': bill.owner.name, 'message': "You don't have enough balance for renewal... Your instance will be deleted in 3 days"} html_message = render_to_string('matrixhosting/emails/renewal_warning.html', context) send_warning_email(bill, html_message) elif date_diff <= 0: if not has_enough_balance(bill.owner): VMInstance.delete_for_bill(bill) else: try: balance = get_balance_for_user(bill.owner) if balance < 0: payment = Payment.objects.create(owner=bill.owner, amount=balance, source='stripe') if payment: bill.close(status="paid") bill.close(status="cancelled") except Exception as e: log.error(f"It seems that there is issue in payment for {bill.owner.name}", e) # do nothing def process_recurring_orders(): """ Check for pending recurring and charge it and generate bills or send the customer warning """ Bill.create_bills_for_all_users() def delete_instance(instance_id): VMInstance.objects.delete(instance_id)