From bb5081a78b947e1764ed585beca67c009a6bd66b Mon Sep 17 00:00:00 2001 From: Xeniac Date: Thu, 23 Nov 2017 22:02:40 +0100 Subject: [PATCH] Added a setting where the exported excel files should be stored. Added a option to send the exported excel as mail attachment. --- src/kasu/settings.py | 1 + .../management/commands/export_ranking.py | 66 +++++++++++++++---- src/mahjong_ranking/models.py | 43 ++++++------ 3 files changed, 79 insertions(+), 31 deletions(-) diff --git a/src/kasu/settings.py b/src/kasu/settings.py index a7a9009..ea63e90 100644 --- a/src/kasu/settings.py +++ b/src/kasu/settings.py @@ -273,6 +273,7 @@ KYU_RANKS = ( DAN_ALLOW_DROP_DOWN = True MIN_HANCHANS_FOR_LADDER = 5 +RANKING_EXPORT_PATH = path.join(PROJECT_PATH, 'backup', 'mahjong_ranking') try: from .local_settings import * # Ignore PyLintBear (W0401, W0614) diff --git a/src/mahjong_ranking/management/commands/export_ranking.py b/src/mahjong_ranking/management/commands/export_ranking.py index 4092565..247f5a2 100644 --- a/src/mahjong_ranking/management/commands/export_ranking.py +++ b/src/mahjong_ranking/management/commands/export_ranking.py @@ -1,11 +1,15 @@ """Export Mahjong Rankings as excel files.""" -import openpyxl -from django.core.management.base import BaseCommand -from django.utils.dateparse import parse_date -from openpyxl.styles import Border +import os from datetime import date, time, datetime + +import openpyxl +from django.conf import settings +from django.core.management.base import BaseCommand from django.utils import timezone +from django.utils.dateparse import parse_date +from django.core.mail import EmailMessage + from mahjong_ranking.models import SeasonRanking, KyuDanRanking THIN_BORDER = openpyxl.styles.Side(style='thin', color="d3d7cf") @@ -38,7 +42,19 @@ DATE_STYLE.font = DEFAULT_STYLE.font DATE_STYLE.border = DEFAULT_STYLE.border DATE_STYLE.number_format = 'dd.mm.yyyy' +MAIL_BODY = """ +Hallo! Ich bin's dein Server. + +Ich habe gerade die Mahjong Rankings als Excel exportiert und dachte mir das +ich sie dir am besten gleich schicke. +Bitte versuche nicht auf diese E-Mail zu antworten. +Ich bin nur ein dummes Programm. + +mit lieben Grüßen + +Der Kasu Server +""" def geneate_excel(): """Generate an excel .xlsx spreadsheet from json data of the kyu/dan rankings. @@ -108,7 +124,7 @@ def export_season_rankings(workbook, until): 'style': 'content', 'width': 25}, {'col': 'C', 'title': '⌀ Platz', 'attr': 'avg_placement', - 'style': 'int', 'width': 8}, + 'style': 'float', 'width': 8}, {'col': 'D', 'title': '⌀ Punkte', 'attr': 'avg_score', 'style': 'float', 'width': 12}, {'col': 'E', 'title': 'Hanchans', 'attr': 'hanchan_count', @@ -156,17 +172,43 @@ def export_kyu_dan_rankings(workbook, until): class Command(BaseCommand): """Exports the SeasonRankings""" + filename = str() + until = datetime def add_arguments(self, parser): - parser.add_argument('--until', nargs='?', type=parse_date) + parser.add_argument( + '--until', nargs='?', type=parse_date, + default=date.today(), metavar='YYYY-MM-DD', + help='Calculate and export rankings until the given date.') + parser.add_argument( + '--mail', nargs='*', type=str, metavar='user@example.com', + help='Send the spreadsheet via eMail to the given recipient.') def handle(self, *args, **options): """Exports the current ladder ranking in a spreadsheet. This is useful as a backup in form of a hardcopy.""" - until = timezone.make_aware( - datetime.combine(options['until'] or date.today(), - time(23, 59, 59))) + self.until = timezone.make_aware(datetime.combine( + options['until'], time(23, 59, 59) + )) + + self.filename = os.path.join( + settings.RANKING_EXPORT_PATH, + 'mahjong_rankings_{:%Y-%m-%d}.xlsx'.format(self.until) + ) workbook = geneate_excel() - export_season_rankings(workbook, until=until) - export_kyu_dan_rankings(workbook, until=until) - workbook.save('mahjong_rankings_{:%Y-%m-%d}.xlsx'.format(until)) + export_season_rankings(workbook, until=self.until) + export_kyu_dan_rankings(workbook, until=self.until) + os.makedirs(settings.RANKING_EXPORT_PATH, exist_ok=True) + workbook.save(self.filename) + if options['mail']: + self.send_mail(options['mail']) + + def send_mail(self, recipients): + mail = EmailMessage( + subject='Mahjong Rankings vom {:%d.%m.%Y}'.format(self.until), + body=MAIL_BODY, + from_email=settings.DEFAULT_FROM_EMAIL, + to=recipients) + mail.attach_file(self.filename) + mail.send() + diff --git a/src/mahjong_ranking/models.py b/src/mahjong_ranking/models.py index e31bff7..18878b9 100644 --- a/src/mahjong_ranking/models.py +++ b/src/mahjong_ranking/models.py @@ -4,7 +4,9 @@ # werden dürfen. from __future__ import division + from datetime import datetime, time + from django.conf import settings from django.core.exceptions import ValidationError from django.core.urlresolvers import reverse @@ -463,8 +465,12 @@ class KyuDanRanking(models.Model): datetime.combine(self.legacy_date, time(0, 0, 0))) else: since = None - else: - since = self.last_hanchan_date or self.legacy_date + elif self.last_hanchan_date: + since = self.last_hanchan_date + elif self.legacy_date: + since = timezone.make_aware( + datetime.combine(self.legacy_date, time(0, 0, 0)) + ) LOGGER.info( "recalculating Kyu/Dan points for %(user)s since %(since)s...", {'user': self.user, 'since': str(since)} @@ -474,13 +480,11 @@ class KyuDanRanking(models.Model): if until: valid_hanchans = valid_hanchans.filter(start__lte=until) - """ TODO: Hanchan Punkte nur neu berechnen wenn sie nach hachan_start - lagen. Es müssen aber alle durch die Schleife rennen, damit die Punkte - richtig gezählt werden.""" self.hanchan_count += valid_hanchans.count() for hanchan in valid_hanchans: hanchan.get_playerdata(self.user) - if since and since < hanchan.start: + if since and hanchan.start < since: + print(hanchan, "<", since, "no recalc") self.dan_points += hanchan.dan_points or 0 self.kyu_points += hanchan.kyu_points or 0 self.update_rank() @@ -495,19 +499,19 @@ class KyuDanRanking(models.Model): self.update_rank() hanchan.update_playerdata(self.user) hanchan.save(recalculate=False) - self.won_hanchans += 1 if hanchan.placement == 1 else 0 - self.good_hanchans += 1 if hanchan.placement == 2 else 0 - self.last_hanchan_date = hanchan.start - LOGGER.debug( - 'id: %(id)d, start: %(start)s, placement: %(placement)d, ' - 'score: %(score)d, kyu points: %(kyu_points)d, dan points: ' - '%(dan_points)d, bonus points: %(bonus_points)d', - {'id': hanchan.pk, 'start': hanchan.start, - 'placement': hanchan.placement, 'score': hanchan.game_score, - 'kyu_points': hanchan.kyu_points or 0, - 'dan_points': hanchan.dan_points or 0, - 'bonus_points': hanchan.bonus_points or 0} - ) + self.won_hanchans += 1 if hanchan.placement == 1 else 0 + self.good_hanchans += 1 if hanchan.placement == 2 else 0 + self.last_hanchan_date = hanchan.start + LOGGER.debug( + 'id: %(id)d, start: %(start)s, placement: %(placement)d, ' + 'score: %(score)d, kyu points: %(kyu_points)d, dan points: ' + '%(dan_points)d, bonus points: %(bonus_points)d', + {'id': hanchan.pk, 'start': hanchan.start, + 'placement': hanchan.placement, 'score': hanchan.game_score, + 'kyu_points': hanchan.kyu_points or 0, + 'dan_points': hanchan.dan_points or 0, + 'bonus_points': hanchan.bonus_points or 0} + ) self.save(force_update=True) @@ -564,6 +568,7 @@ class KyuDanRanking(models.Model): hanchan.kyu_points -= (self.kyu_points + hanchan.kyu_points) self.kyu_points += hanchan.kyu_points + # TODO: Merkwürdige Methode die zwar funktioniert aber nicht sehr # aussagekräfig ist. Überarbeiten? def update_rank(self):