diff --git a/coinmanager/coinc/models.py b/coinmanager/coinc/models.py index 6d1e61a..fe09904 100644 --- a/coinmanager/coinc/models.py +++ b/coinmanager/coinc/models.py @@ -18,7 +18,7 @@ -from datetime import datetime +from datetime import datetime, date from django.db.models import BooleanField, CASCADE, CharField, DateField, ForeignKey, Model, PositiveIntegerField, PositiveSmallIntegerField, TextField @@ -49,7 +49,7 @@ class Country(Model): def __str__(self): - return f"{self.name} - {self.name_iso}" + return f"{self.name} {self.name_iso} {self.comment}" @@ -81,9 +81,9 @@ class Coin(Model): name = TextField('Name', default='', blank=True) - found_by = ForeignKey('User', on_delete=CASCADE) + found_by = ForeignKey('User', on_delete=CASCADE, null=True, blank=True) - found_on = DateField('Gefunden am', auto_now_add=True) + found_on = DateField('Eingetragen am', default=date.today) circulation = PositiveIntegerField('Auflage', default=0) diff --git a/coinmanager/coinc/static/coinc/main.js b/coinmanager/coinc/static/coinc/main.js index d3f0915..b27ecb6 100644 --- a/coinmanager/coinc/static/coinc/main.js +++ b/coinmanager/coinc/static/coinc/main.js @@ -78,7 +78,6 @@ function render_login_color(color) { function render_found() { let checked = $('#found').prop('checked'); if (checked) { - console.log(settings); $('#found_by option[selected=selected]').html(settings['found_by']); let found_on = '' if (settings['found_on']) { @@ -103,6 +102,41 @@ function render_found() { } +// update table cell according to settings +function render_response(td, set) { + let td_class = ''; + let div_class = ''; + + if (!set['exists']) { + td_class = 'noexist'; + } else if (set['buy_only']) { + td_class = 'buy_only'; + } else if (set['circulation'] && set['circulation'] < 1500000 && set['circulation'] != 0) { + td_class = 'rare'; + } else if ([10, 20, 50].includes(Number($(td).attr('value')))) { + td_class = 'brass'; + } else if (set['found_by']) { + td_class = 'found'; + } + + if (set['ec']) { + td_class += ' ec'; + } else if (set['checked']) { + td_class += ' checked'; + } + + if (set['found'] && set['found_by'] && set['exists']) { + div_class = set['found_by']; + // TODO remove marker before marker + $(td).find('div.coin').append('x'); + } + $(td).removeClass(); + $(td).addClass('coin ' + td_class); + $(td).find('div[type=overlay]').removeClass(); + $(td).find('div[type=overlay]').addClass('found ' + div_class); +} + + // save/update global settings function save_settings() { settings['circulation'] = $('#circulation').val(); @@ -113,17 +147,16 @@ function save_settings() { settings['found_on'] = get_datetime(); } let found_by = $('#found_by option[selected=selected]').html(); - console.log(found_by); if (found_by) { settings['found_by'] = found_by; } - let checkboxes = $('#found, #buy_only, #checked, #ec').map(function() { + let checkboxes = $('#found, #buy_only, #checked, #ec, #exists').map(function() { return { [$(this).prop('id')]: $(this).prop('checked') } }).get(); for (let box of checkboxes) { for (let item in box) { settings[item] = box[item]; } } - console.log(settings); + settings['exists'] = !settings['exists'] } @@ -155,6 +188,11 @@ $(document).ready(function() { let found_by = (settings['found'] === true) ? settings['found_by'] : '' let found_on = (settings['found'] === true) ? settings['found_on'] : '' let circulation = (settings['circulation'] == 'Auflage') ? 0 : settings['circulation']; + + // TODO it would be nicer if #circulation, #found_by and #found_on would have no value while #exists is checked. then this would also not be neccessary + if (settings['exists'] === false) { + circulation = 0; + } let data = { csrfmiddlewaretoken: csrf_token, value: value, @@ -170,16 +208,18 @@ $(document).ready(function() { ec: settings['ec'], exists: settings['exists'] } + $.ajax({ type: 'POST', url: 'add/coin', data: data, + dataType: 'json', + td: this, success: function(response) { - if (response.status === 0) { - console.log('yarp'); + render_response(this.td, settings); } else { - console.log('nope'); + alert(response.message); } } }); diff --git a/coinmanager/coinc/static/coinc/styles.css b/coinmanager/coinc/static/coinc/styles.css index e983b3c..c6c632b 100644 --- a/coinmanager/coinc/static/coinc/styles.css +++ b/coinmanager/coinc/static/coinc/styles.css @@ -56,6 +56,7 @@ table { th { position: sticky; + z-index: 1; } tr { @@ -123,7 +124,15 @@ td > * { } -td.exists { +td.buy_only { + background-color: #dd7e6b; +} + +td.rare { + background-color: #e69138; +} + +td.noexist { background-color: #434343; } @@ -131,12 +140,8 @@ td.brass, th.brass { background-color: #ffff99 !important; } -td.rare { - background-color: #e69138; -} - -td.buy_only { - background-color: #dd7e6b; +td.found { + background-color: white; } td.year { @@ -152,7 +157,7 @@ td.spacer { background-color: white; } -td.in_collector { +td.ec { color: #ff0000; font-weight: bold; } diff --git a/coinmanager/coinc/templates/coinc/coin.html b/coinmanager/coinc/templates/coinc/coin.html index e84b8f1..5297406 100644 --- a/coinmanager/coinc/templates/coinc/coin.html +++ b/coinmanager/coinc/templates/coinc/coin.html @@ -1 +1 @@ -
{{ marker }}
+
{{ marker }}
diff --git a/coinmanager/coinc/templates/coinc/controlbar.html b/coinmanager/coinc/templates/coinc/controlbar.html index 4502c53..3c6cd38 100644 --- a/coinmanager/coinc/templates/coinc/controlbar.html +++ b/coinmanager/coinc/templates/coinc/controlbar.html @@ -1,3 +1,10 @@ + diff --git a/coinmanager/coinc/views.py b/coinmanager/coinc/views.py index de9a8f0..9bd1899 100644 --- a/coinmanager/coinc/views.py +++ b/coinmanager/coinc/views.py @@ -17,7 +17,7 @@ # along with this program. If not, see . -from datetime import datetime +from datetime import datetime, date from json import dumps from django.http import HttpResponse, Http404 @@ -153,20 +153,24 @@ def show_coin(country, year, stamp, value): } td_class = '' - if coin.buy_only: + 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 not coin.exists: - td_class = 'noexist' elif coin.value in [10, 20, 50]: td_class = 'brass' + elif coin.found_by: + td_class = 'found' if coin.in_collector: - td_class += ' in_collector' + td_class += ' ec' elif coin.checked: - td_class += ' coin_checked' + td_class += ' checked' + div_class = '' + marker = '' if coin.found_by: div_class = f"found {coin.found_by}" marker = 'x' @@ -201,63 +205,150 @@ def add_user(request, username, color): return HttpResponse(dumps({ 'status': status, 'message': message })) +def response(status=0, message=''): + ''' return generic json-formatted status output with http-headers ''' + return HttpResponse(dumps({ 'status': status, 'message': message })) + + def add_coin(request): - country = Country.objects.get(name_iso=request.POST['country']) + + status = 0 + message = '' try: - stamp = Stamp.objects.get(name_short=request.POST['stamp']) + value = int(request.POST['value']) + except ValueError: + status = 1 + message = f"Der Münzwert '{value}' ist keine gültige Zahl." + return response(status, message) + if value not in [1,2,5,10,20,50,100,200,201,202,203]: + status = 1 + message = f"Der Münzwert '{value}' muss eine Zahl aus der Menge [1, 2, 5, 10, 20, 50, 100, 200, 201, 202, 203] sein." + return response(status, message) + + try: + year = int(request.POST['year']) + except ValueError: + status = 1 + message = f"Das Jahr '{year}' ist keine gültige Zahl." + return response(status, message) + if year < 1999: + status = 1 + message = "Das Jahr '{year}' ist kleiner als 1999." + return response(status, message) + if year > 2098: + status = 1 + message = f"Bitte den 2100-Jahrhundert-Datumsbug fixen. :-)" + return response(status, messae) + + try: + country = Country.objects.get(name_iso=request.POST['country']) + except Country.DoesNotExist: + status = 1 + message = f"Das Land mit ISO-Kürzel '{name_iso}' existiert nicht." + return response(status, message) + + stamp = request.POST['stamp'] + try: + stamp = Stamp.objects.get(name_short=stamp) except Stamp.DoesNotExist: + if stamp: + status = 1 + message = f"Die Prägerei '{stamp}' existiert nicht." + return response(status, message) stamp = None + try: + name = str(request.POST['name']) + except Exception as e: + status = 1 + message = f"Der Münzenname '{name}' ist kein gültiger Name. {e}" + return response(status, message) + + found_by = request.POST['found_by'] if request.POST['found_by'] else None + if found_by: + try: + found_by = User.objects.get(name=found_by) + except User.DoesNotExist: + status = 1 + message = f"Der Nutzer '{found_by}' existiert nicht." + return response(status, message) + + found_on = request.POST['found_on'] if request.POST['found_on'] else None + if found_on: + try: + print(f"found_on before: {found_on}") + found_on = datetime.strptime(found_on, '%d.%m.%Y') + found_on = found_on.strftime('%Y-%m-%d') + print(f"found_on after: {found_on}") + except ValueError: + status = 1 + message = f"Das Datum '{found_on}' entspricht nicht dem Format DD.MM.YYYY" + return response(status, message) + else: + found_on = date.today().strftime('%Y-%m-%d') try: - found_by = User.objects.get(name=request.POST['found_by']) - except User.DoesNotExist: - if not request.POST['exists']: - print('errorrr') - exit(0) - found_by = None + circulation = int(request.POST['circulation']) + except ValueError: + circulation = 0 + if circulation != 0: + if circulation < 0: + status = 1 + message = f"Die Münzauflage '{circulation}' muss 0 oder positiv sein." + return response(status, message) + elif circulation > 1000000000: + status = 1 + message = f"Die Münzauflage '{circulation}' ist unrealistisch." + return response(status, message) buy_only = True if request.POST['buy_only'] == 'true' else False - checked = True if request.POST['checked'] == 'true' else False - ec = True if request.POST['ec'] == 'true' else False - exists = True if request.POST['exists'] == 'true' else False + checked = True if request.POST['checked'] == 'true' else False + + ec = True if request.POST['ec'] == 'true' else False + + exists = True if request.POST['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 try: - print('update') - Coin.objects.update( - value=int(request.POST['value']), - year=int(request.POST['year']), + 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() + except Coin.DoesNotExist: + Coin.objects.create( + value=value, + year=year, country=country, stamp=stamp, - name=request.POST['name'], + name=name, found_by=found_by, - found_on=request.POST['found_on'], - circulation=request.POST['circulation'], + found_on=found_on, + circulation=circulation, buy_only=buy_only, checked=checked, in_collector=ec, exists=exists) - except Coin.DoesNotExist: - print('new') - Coin.objects.create( - value=int(request.POST['value']), - year=int(request.POST['year']), - country=country, - stamp=stamp, - name=request.POST['name'], - found_by=found_by, - found_on=request.POST['found_on'], - circulation=request.POST['circulation'], - buy_only=buy_only, - checked=checked, - in_collector=ec, - exists=exists - ) - - return HttpResponse(dumps({'status': 'ok'})) + return response() # TODO diff --git a/coinmanager/db.sqlite3 b/coinmanager/db.sqlite3 index 4051a58..3e8245c 100644 Binary files a/coinmanager/db.sqlite3 and b/coinmanager/db.sqlite3 differ