add tasks to replace cron-scheduled scripts

master
alice 4 years ago
parent 09ac0996b8
commit 3d73df081d

@ -21,10 +21,18 @@ app.conf.beat_schedule = {
'task': 'payments.tasks.check_subscriptions', 'task': 'payments.tasks.check_subscriptions',
'schedule': crontab(hour=1), 'schedule': crontab(hour=1),
}, },
'payments__cancel_old_payments': {
'task': 'payments.tasks.cancel_old_payments',
'schedule': crontab(hour=2),
},
'lambdainst__resync': { 'lambdainst__resync': {
'task': 'lambdainst.tasks.push_all_users', 'task': 'lambdainst.tasks.push_all_users',
'schedule': crontab(day_of_week=1), 'schedule': crontab(day_of_week=1),
}, },
'lambdainst__notify_account_expiration': {
'task': 'lambdainst.tasks.notify_account_expiration',
'schedule': crontab(hour='*/6'),
},
} }
# Load task modules from all registered Django app configs. # Load task modules from all registered Django app configs.

@ -1,9 +1,23 @@
import logging import logging
from datetime import timedelta
from celery import task
from django.db.models import Q, F
from django.db import transaction
from django.conf import settings
from django.utils import timezone
from django.template.loader import get_template
from django.core.mail import send_mass_mail
from constance import config as site_config
import django_lcore import django_lcore
from lambdainst.models import User
from ccvpn.common import parse_integer_list
from lambdainst.models import User, VPNUser
ROOT_URL = settings.ROOT_URL
SITE_NAME = settings.TICKETS_SITE_NAME
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
from celery import task
@task(autoretry_for=(Exception,), default_retry_delay=60*60) @task(autoretry_for=(Exception,), default_retry_delay=60*60)
def push_all_users(): def push_all_users():
@ -16,6 +30,7 @@ def push_all_users():
django_lcore.sync_user(u.vpnuser, fail_silently=False) django_lcore.sync_user(u.vpnuser, fail_silently=False)
@task(autoretry_for=(Exception,), max_retries=10, retry_backoff=True) @task(autoretry_for=(Exception,), max_retries=10, retry_backoff=True)
def push_user(user_id): def push_user(user_id):
user = User.objects.get(id=user_id) user = User.objects.get(id=user_id)
@ -23,3 +38,49 @@ def push_user(user_id):
django_lcore.sync_user(user.vpnuser, fail_silently=False) django_lcore.sync_user(user.vpnuser, fail_silently=False)
@task
def notify_account_expiration():
""" Notify users near the end of their subscription """
from_email = settings.DEFAULT_FROM_EMAIL
for v in parse_integer_list(site_config.NOTIFY_DAYS_BEFORE):
emails = []
users = list(get_next_expirations(v))
logging.info("sending -%d day notification to %d users", v, len(users))
with transaction.atomic():
for u in users:
# Ignore users with active subscriptions
# They will get notified only if it gets cancelled (payments
# processors will cancel after a few failed payments)
if u.get_subscription():
continue
ctx = dict(site_name=SITE_NAME, user=u.user,
exp=u.expiration, url=ROOT_URL)
text = get_template('lambdainst/mail_expire_soon.txt').render(ctx)
emails.append(("CCrypto VPN Expiration", text, from_email, [u.user.email]))
logging.debug("sending -%d days notify to %s" % (v, u.user.email))
u.last_expiry_notice = timezone.now()
u.save()
send_mass_mail(emails)
def get_next_expirations(days=3):
""" Gets users whose subscription will expire in some days """
limit_date = timezone.now() + timedelta(days=days)
users = VPNUser.objects.exclude(user__email__exact='')
users = users.filter(expiration__gt=timezone.now()) # Not expired
users = users.filter(expiration__lt=limit_date) # Expire in a few days
# Make sure we dont send the notice twice
users = users.filter(Q(last_expiry_notice__isnull=True)
| Q(expiration__gt=F('last_expiry_notice')
+ timedelta(days=days)))
return users

@ -1,9 +1,12 @@
import logging import logging
from datetime import timedelta
from django.utils import timezone
from celery import task
from .models import Subscription, ACTIVE_BACKENDS from payments.models import Payment
from .models import Payment, Subscription, ACTIVE_BACKENDS
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
from celery import task
@task @task
def check_subscriptions(): def check_subscriptions():
@ -14,3 +17,17 @@ def check_subscriptions():
sub.refresh_from_db() sub.refresh_from_db()
ACTIVE_BACKENDS['stripe'].refresh_subscription(sub) ACTIVE_BACKENDS['stripe'].refresh_subscription(sub)
sub.save() sub.save()
@task
def cancel_old_payments():
expdate = timezone.now() - timedelta(days=3)
expired = Payment.objects.filter(created__lte=expdate, status='new',
paid_amount=0)
logger.info("cancelling %d pending payments older than 3 days (%s)", len(expired), expdate.isoformat())
for p in expired:
logger.debug("cancelling payment #%d (%s): created on %s", p.id, p.user.username, p.created)
p.status = 'cancelled'
p.save()

Loading…
Cancel
Save