24 changed files with 658 additions and 409 deletions
@ -1,4 +1,11 @@ |
|||||||
venv/ |
venv/ |
||||||
online/ |
online/ |
||||||
.idea/ |
.idea/ |
||||||
.DS_Store |
.DS_Store |
||||||
|
|
||||||
|
# local files |
||||||
|
server/ |
||||||
|
cashonly/web/static/bootstrap/**/* |
||||||
|
cashonly/web/static/jquery.min.js |
||||||
|
db.sqlite3 |
||||||
|
manage.py |
@ -1,75 +1,90 @@ |
|||||||
from cashonly.core.models import * |
from cashonly.core.models import * |
||||||
from django.conf import settings |
from django.conf import settings |
||||||
from django.core.mail import send_mass_mail |
from django.core.mail import send_mass_mail |
||||||
from django.core.management.base import BaseCommand, CommandError |
from django.core.management.base import BaseCommand |
||||||
from django.template import Context |
|
||||||
from django.template.loader import get_template |
from django.template.loader import get_template |
||||||
from django.utils import translation |
from django.utils import translation |
||||||
from django.utils.dateformat import DateFormat |
from django.utils.dateformat import DateFormat |
||||||
from django.utils.formats import get_format |
from django.utils.formats import get_format |
||||||
from django.utils.translation import ugettext as _ |
from django.utils.translation import gettext as _ |
||||||
import datetime |
import datetime |
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand): |
class Command(BaseCommand): |
||||||
help = 'Sends out a digest of transactions to recently active users' |
help = "Sends out a digest of transactions to recently active users" |
||||||
|
|
||||||
def handle(self, **options): |
def handle(self, **options): |
||||||
translation.activate('de') |
translation.activate("de") |
||||||
|
|
||||||
tpl = get_template('cashonly/core/daily_digest.txt') |
tpl = get_template("cashonly/core/daily_digest.txt") |
||||||
|
|
||||||
messages = [] |
messages = [] |
||||||
for a in Account.objects.filter(daily_digest=True): |
for a in Account.objects.filter(daily_digest=True): |
||||||
name = '%s %s' % (a.user.first_name, a.user.last_name) |
name = "%s %s" % (a.user.first_name, a.user.last_name) |
||||||
context = { |
context = { |
||||||
'name': name, |
"name": name, |
||||||
'credit': a.credit, |
"credit": a.credit, |
||||||
'range': settings.CASHONLY_DAILY_DIGEST_RANGE_HOURS, |
"range": settings.CASHONLY_DAILY_DIGEST_RANGE_HOURS, |
||||||
'url': settings.CASHONLY_USERSETTINGS_URL, |
"url": settings.CASHONLY_USERSETTINGS_URL, |
||||||
} |
} |
||||||
|
|
||||||
min_ts = datetime.datetime.now() - datetime.timedelta( |
min_ts = datetime.datetime.now() - datetime.timedelta( |
||||||
hours=settings.CASHONLY_DAILY_DIGEST_RANGE_HOURS |
hours=settings.CASHONLY_DAILY_DIGEST_RANGE_HOURS |
||||||
) |
) |
||||||
transactions = Transaction.objects.filter(account=a) \ |
transactions = Transaction.objects.filter(account=a).filter( |
||||||
.filter(timestamp__gte=min_ts) |
timestamp__gte=min_ts |
||||||
|
) |
||||||
|
|
||||||
if transactions.count() > 0: |
if transactions.count() > 0: |
||||||
lengths = {'timestamp': len(_('date')), |
lengths = { |
||||||
'description': len(_('subject')), |
"timestamp": len(_("date")), |
||||||
'amount': len(_('amount'))} |
"description": len(_("subject")), |
||||||
|
"amount": len(_("amount")), |
||||||
|
} |
||||||
|
|
||||||
sum = 0 |
sum = 0 |
||||||
for t in transactions: |
for t in transactions: |
||||||
lengths['timestamp'] = \ |
lengths["timestamp"] = max( |
||||||
max(lengths['timestamp'], len(DateFormat(t.timestamp) |
lengths["timestamp"], |
||||||
.format(get_format('SHORT_DATETIME_FORMAT')))) |
len( |
||||||
lengths['description'] = \ |
DateFormat(t.timestamp).format( |
||||||
max(lengths['description'], len(t.description)) |
get_format("SHORT_DATETIME_FORMAT") |
||||||
lengths['amount'] = \ |
) |
||||||
max(lengths['amount'], len(str(t.amount))) |
), |
||||||
t.description = t.description.split('\n') |
) |
||||||
|
lengths["description"] = max( |
||||||
|
lengths["description"], len(t.description) |
||||||
|
) |
||||||
|
lengths["amount"] = max(lengths["amount"], len(str(t.amount))) |
||||||
|
t.description = t.description.split("\n") |
||||||
|
|
||||||
sum += t.amount |
sum += t.amount |
||||||
|
|
||||||
lengths['sum'] = lengths['timestamp'] + \ |
lengths["sum"] = ( |
||||||
lengths['description'] + lengths['amount'] |
lengths["timestamp"] + lengths["description"] + lengths["amount"] |
||||||
context['lengths'] = lengths |
) |
||||||
context['tl'] = transactions |
context["lengths"] = lengths |
||||||
context['sum'] = sum |
context["tl"] = transactions |
||||||
|
context["sum"] = sum |
||||||
|
|
||||||
if a.user.email is not None and len(a.user.email) > 0: |
if a.user.email is not None and len(a.user.email) > 0: |
||||||
rcpts = ['%s <%s>' % (name, a.user.email)] |
rcpts = ["%s <%s>" % (name, a.user.email)] |
||||||
else: |
else: |
||||||
self.stdout.write(self.style.WARNING( |
self.stdout.write( |
||||||
'User "%s" has no Email address.' % (a.user.username) |
self.style.WARNING( |
||||||
)) |
'User "%s" has no Email address.' % (a.user.username) |
||||||
|
) |
||||||
|
) |
||||||
continue |
continue |
||||||
|
|
||||||
messages.append(('%s%s' % (settings.EMAIL_SUBJECT_PREFIX, |
messages.append( |
||||||
_('Account Statement')), |
( |
||||||
tpl.render(context), |
"%s%s" |
||||||
settings.DEFAULT_FROM_EMAIL, rcpts)) |
% (settings.EMAIL_SUBJECT_PREFIX, _("Account Statement")), |
||||||
|
tpl.render(context), |
||||||
|
settings.DEFAULT_FROM_EMAIL, |
||||||
|
rcpts, |
||||||
|
) |
||||||
|
) |
||||||
|
|
||||||
send_mass_mail(tuple(messages)) |
send_mass_mail(tuple(messages)) |
||||||
|
@ -1,33 +1,36 @@ |
|||||||
from django.conf.urls import url |
from django.urls import re_path |
||||||
from cashonly.web import views |
from cashonly.web import views |
||||||
|
|
||||||
urlpatterns = [ |
urlpatterns = [ |
||||||
url(r'^$', views.overview, name='overview'), |
re_path(r"^$", views.overview, name="overview"), |
||||||
|
re_path(r"^product/(?P<pk>\d+)/$", views.ProductView.as_view(), name="product"), |
||||||
url(r'^product/(?P<pk>\d+)/$', views.ProductView.as_view(), |
re_path( |
||||||
name='product'), |
r"transactions/$", |
||||||
|
views.transactions, |
||||||
url(r'transactions/$', views.transactions, {'detailed': False, 'page': 1}, |
{"detailed": False, "page": 1}, |
||||||
name='transactions'), |
name="transactions", |
||||||
|
), |
||||||
url(r'transactions/(?P<page>\d+)/$', views.transactions, |
re_path( |
||||||
{'detailed': False}, name='transactions'), |
r"transactions/(?P<page>\d+)/$", |
||||||
|
views.transactions, |
||||||
url(r'transactions/(?P<page>\d+)/detailed/$', views.transactions, |
{"detailed": False}, |
||||||
{'detailed': True}, name='transactions_detailed'), |
name="transactions", |
||||||
|
), |
||||||
url(r'products/((?P<category_id>\d+)/)?$', views.products, |
re_path( |
||||||
name='products'), |
r"transactions/(?P<page>\d+)/detailed/$", |
||||||
|
views.transactions, |
||||||
url(r'buy/(?P<product_id>\d+)/$', views.buy, name='buy'), |
{"detailed": True}, |
||||||
|
name="transactions_detailed", |
||||||
url(r'buy/(?P<product_id>\d+)/really/$', views.buy, |
), |
||||||
{'confirm': True}, name='buy_really'), |
re_path(r"products/((?P<category_id>\d+)/)?$", views.products, name="products"), |
||||||
|
re_path(r"buy/(?P<product_id>\d+)/$", views.buy, name="buy"), |
||||||
url(r'buy/thanks/$', views.buy_thanks, name='buy_thanks'), |
re_path( |
||||||
|
r"buy/(?P<product_id>\d+)/really/$", |
||||||
url(r'buy/error/$', views.buy_error, name='buy_error'), |
views.buy, |
||||||
|
{"confirm": True}, |
||||||
url(r'usersettings(/(?P<submit>\w+))?/$', views.usersettings, |
name="buy_really", |
||||||
name='usersettings'), |
), |
||||||
|
re_path(r"buy/thanks/$", views.buy_thanks, name="buy_thanks"), |
||||||
|
re_path(r"buy/error/$", views.buy_error, name="buy_error"), |
||||||
|
re_path(r"usersettings(/(?P<submit>\w+))?/$", views.usersettings, name="usersettings"), |
||||||
] |
] |
||||||
|
Loading…
Reference in new issue