382 lines
12 KiB
Python

# encoding: utf-8
#
# Copyright (C) 2020 willipink.eu
# Author Moritz Münch moritzmuench@mailbox.org
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime, date
from json import dumps
from django.conf import settings
from django.http import HttpResponse, Http404
from django.template import loader
from django.template.defaultfilters import register
from django.views.decorators.http import condition
from django.utils.datastructures import MultiValueDictKeyError
from .cache import (get_last_modified_coin, set_last_modified_coin,
get_last_modified_country, set_last_modified_country)
from .models import Country, Stamp, Coin, User
from .helper import total_coin_sum, coin_sum_of_
@condition(last_modified_func=get_last_modified_coin)
def index(request):
''' index view '''
template = loader.get_template('coinc/index.html')
countrys = Country.objects.order_by('name')
users = User.objects.order_by('id')
coin_sum = total_coin_sum()
recent_coins = Coin.objects.order_by('-found_on')[:10]
for coin in range(len(recent_coins)):
recent_coins[coin].value /= 100
context = {
'countrys': countrys,
'users': users,
'coin_sum': f'{coin_sum:.2f}',
'recent_coins': recent_coins,
}
return HttpResponse(template.render(context, request))
@condition(last_modified_func=get_last_modified_country)
def detail_country(request, name_iso):
''' wrapper_view for a *single* country '''
template = loader.get_template('coinc/country.html')
try:
country = Country.objects.get(name_iso=name_iso)
except Country.DoesNotExist:
raise Http404(f"Das Land '{name_iso}' existiert nicht.")
context = show_country(country, single_country=True)
return HttpResponse(template.render(context, request))
@register.inclusion_tag('coinc/country.html')
def show_country(country, single_country=False):
''' detail_view for a country '''
c = {
'name_iso': country.name_iso,
'name': country.name,
'comment': country.comment,
'years': {}
}
coin_sum = coin_sum_of_(country)
irregular_stamps = {}
stamps = Stamp.objects.filter(country=country.name_iso).values(
'name_short', 'years')
if stamps:
temp_stamps = {}
for stamp in stamps:
stamp_name_short = stamp['name_short']
if stamp['years'] == "":
temp_stamps[stamp_name_short] = {}
else:
for year in stamp['years'].split(","):
irregular_stamps[year] = {}
irregular_stamps[year][stamp_name_short] = {}
temp_stamps[''] = {}
stamps = temp_stamps
else:
stamps = {'': {}}
year_now = datetime.now().year
for year in [str(i) for i in range(country.euro_member_since, year_now + 1)]:
stamps_per_year = stamps
if irregular_stamps and year in irregular_stamps:
for irregular_stamp, value in irregular_stamps[year].items():
stamps_per_year[irregular_stamp] = {}
# TODO this is not a fix, when more stamps with uniqe years get added
elif country.name_iso == 'gr':
stamps_per_year = {'': {}}
c['years'][year] = {}
for stamp in stamps_per_year:
c['years'][year][stamp] = {
1: {},
2: {},
5: {},
10: {},
20: {},
50: {},
100: {},
200: {},
201: {},
202: {},
203: {}
}
stamps_per_year = {}
coins = Coin.objects.all().filter(country=country)
for coin in coins:
td_class = ''
if not coin.exists:
td_class = 'noexist'
elif coin.buy_only:
td_class = 'buy_only'
elif coin.circulation and coin.circulation <= 1500000:
td_class = 'rare'
elif coin.value in [10, 20, 50]:
td_class = 'brass'
elif coin.found_by:
td_class = 'found'
else:
td_class = 'exist'
if coin.in_collector:
td_class += ' ec'
elif coin.checked:
td_class += ' checked'
div_class = ''
marker = ''
if coin.found_by:
div_class = f"found {coin.found_by}"
marker = ''
name = coin.name if coin.name else ''
special_class = ''
special_name = ''
if name:
if coin.value == 201:
special_name = 'special1_name'
elif coin.value == 202:
special_name = 'special2_name'
elif coin.value == 203:
special_name = 'special3_name'
if len(name) >= 18 and len(name) <= 42:
special_class = 'two_lines'
elif len(name) > 42:
special_class = 'three_lines'
stamp = coin.stamp.name_short if coin.stamp else ''
c['years'][str(coin.year)][stamp][coin.value] = {
'marker': marker,
'name': name,
'date_modified': coin.date_modified,
'td_class': td_class,
'div_class': div_class,
'special_class': special_class,
'special_name': special_name
}
return {
'country': c,
'single_country': single_country,
'users': User.objects.order_by('id').values('name','color'),
'coin_sum': f"{coin_sum:.2f}"
}
@register.inclusion_tag('coinc/year.html')
def show_year(country, year):
''' show a year '''
return {
'stamps': country['years'][year],
'year_short': year[2:4],
}
@register.inclusion_tag('coinc/coin.html')
def show_coin(coin, value):
''' show a coin '''
if coin:
return {
'value': value,
'marker': coin['marker'],
'name': coin['name'],
'date_modified': coin['date_modified'],
'td_class': coin['td_class'],
'div_class': coin['div_class'],
'special_class': coin['special_class'],
'special_name': coin['special_name']}
else:
return { 'value': value }
def response(status=0, message=''):
''' return generic json-formatted status output with http-headers '''
return HttpResponse(dumps({ 'status': status, 'message': message }))
def add_user(request, username, color):
''' add a user '''
try:
existing_user = User.objects.get(name=username)
return response(1, f"'{username}' ist schon vergeben.")
except User.DoesNotExist:
User.objects.create(name=username, color=color)
return response()
def edit_coin(request):
return response()
def add_coin(request, country, year, value):
''' add or update a coin
@params request.POST[field]
*field* mandatory default data type (internal) with limits
------------------------------------------------------------------------------------
value yes - int [1, 2, 5, 10, 20, 50, 100, 200, 201, 202, 203]
year yes - int [1999; 2098]
country yes - obj Country
stamp no None obj Stamp
exists no False bool
name no - str
found_by no None obj User
found_on no None str %Y-%m-%d
date-added no auto str %Y-%m-%d %H:%M:%S.%s
date-modified no auto str %Y-%m-%d %H:%M:%S.%s
circulation no 0 int [0; 1000000000]
buy_only no False bool
checked no False bool
ec no False bool
'''
# mandatory fields value, year, country
value = int(value)
year = int(year)
country = str(country)
try:
country = Country.objects.get(name_iso=country)
except Country.DoesNotExist:
return response(1, f"Das Land mit ISO-Kürzel '{country}' existiert nicht")
# optional fields stamp, exists, name, found_by, found_on, circulation, buy_only, ec, checked
stamp = request.POST.get('stamp')
stamp = str(stamp) if stamp else None
if stamp:
if len(stamp) > 10:
return response(1, f'Die Prägerei darf max. 10 Zeichen lang sein')
try:
stamp = Stamp.objects.get(name_short=stamp)
except Stamp.DoesNotExist:
return response(1, f"Die Prägerei '{stamp}' existiert nicht.")
exists = request.POST.get('exists', False)
exists = True if exists == 'true' else False
if not exists:
name = ''
found_by = None
found_on = date.today().strftime('%Y-%m-%d')
circulation = 0
buy_only = False
checked = False
ec = False
else:
name = request.POST.get('name')
name = str(name) if name else None
found_by = request.POST.get('found_by')
found_by = str(found_by) if found_by else None
if found_by:
try:
found_by = User.objects.get(name=found_by)
except User.DoesNotExist:
return response(1, f"Der Nutzer '{found_by}' existiert nicht.")
found_on = request.POST.get('found_on')
if found_on:
try:
found_on = datetime.strptime(found_on, '%d.%m.%Y')
found_on = found_on.strftime('%Y-%m-%d')
except ValueError:
return response(1, f"Das Datum '{found_on}' entspricht nicht dem Format 'DD.MM.YYYY'.")
else:
found_on = date.today().strftime('%Y-%m-%d')
circulation = request.POST.get('circulation', 0)
circulation = 0 if circulation == '' else circulation
try:
circulation = int(circulation.replace('.', ''))
except ValueError:
return response(1, f"Die Münzauflage '{circulation}' muss eine Zahl sein.")
if circulation < 0:
return response(1, f"Die Münzauflage '{circulation}' muss 0 oder positiv sein.")
elif circulation > 1000000000:
return response(1, f"Die Münzauflage '{circulation}' ist unrealistisch.")
buy_only = True if request.POST.get('buy_only') == 'true' else False
checked = True if request.POST.get('checked') == 'true' else False
ec = True if request.POST.get('ec') == 'true' else False
try:
coin = Coin.objects.get(
value=value,
year=year,
country=country,
stamp=stamp)
coin.name = name
coin.found_by = found_by
coin.found_on = found_on
coin.circulation = circulation
coin.buy_only = buy_only
coin.checked = checked
coin.in_collector = ec
coin.exists = exists
coin.save(force_update=True)
except Coin.DoesNotExist:
Coin.objects.create(
value = value,
year = year,
country = country,
stamp = stamp,
name = name,
found_by = found_by,
found_on = found_on,
circulation = circulation,
buy_only = buy_only,
checked = checked,
in_collector = ec,
exists = exists)
set_last_modified_coin()
set_last_modified_country(country.name_iso)
return response()
def statistic(request):
''' show statistics '''
return HttpResponse('Statistik')