diff --git a/k4ever/buyable/models.py b/k4ever/buyable/models.py index 6f2f05e..13da811 100644 --- a/k4ever/buyable/models.py +++ b/k4ever/buyable/models.py @@ -28,4 +28,8 @@ class Purchase(models.Model): buyable = models.ForeignKey(Buyable) def __unicode__(self): - return "%s%s, %s by %s" % (self.buyable.name, self.isDeposit and " (deposit)" or "", self.price, self.user) \ No newline at end of file + return "%s%s, %s by %s" % (self.buyable.name, self.isDeposit and " (deposit)" or "", self.price, self.user) + + def create(self, buyable): + self.dateTime = datetime.datetime.now() + self.buyable = buyable \ No newline at end of file diff --git a/k4ever/buyable/templates/buyables/showItem.html b/k4ever/buyable/templates/buyables/showItem.html new file mode 100644 index 0000000..02a16c0 --- /dev/null +++ b/k4ever/buyable/templates/buyables/showItem.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} + +{% block "content" %} + {% if item %} + You got the item {{ item }} + {% else %} + No item found :( + {% endif %} +{% endblock %} diff --git a/k4ever/buyable/templates/buyables/showItems.html b/k4ever/buyable/templates/buyables/showItems.html new file mode 100644 index 0000000..65b0510 --- /dev/null +++ b/k4ever/buyable/templates/buyables/showItems.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block "content" %} +{% for item in items %} +{{ item }} {{ item.name }} +{% endfor %} +{% endblock %} \ No newline at end of file diff --git a/k4ever/buyable/urls.py b/k4ever/buyable/urls.py new file mode 100644 index 0000000..beb4562 --- /dev/null +++ b/k4ever/buyable/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls.defaults import * + + +urlpatterns = patterns('', + (r'^$', 'buyable.views.showItems'), + (r'^show/(\d+)/$', 'buyable.views.showItem'), + (r'^buy/(\d+)/$', 'buyable.views.buyItem'), +) \ No newline at end of file diff --git a/k4ever/buyable/views.py b/k4ever/buyable/views.py index 60f00ef..a0206a1 100644 --- a/k4ever/buyable/views.py +++ b/k4ever/buyable/views.py @@ -1 +1,33 @@ # Create your views here. +from django.shortcuts import render_to_response +from django.template import RequestContext +from django.contrib.auth.decorators import login_required +from django.http import HttpResponseRedirect +from models import Buyable + +@login_required +def showItems(request): + # FIXME: Implement pagination here + items = Buyable.objects.all() + return render_to_response("buyables/showItems.html", {'items': items}, RequestContext(request)) + +@login_required +def showItem(request, itemid): + try: + item = Buyable.objects.get(id=itemid) + except Buyable.DoesNotExist: + # baww, kein item mit der id :( (oder mutax trollt rum) + return HttpResponseRedirect("/buy/") + return render_to_response("buyables/showItem.html", {'item': item}, RequestContext(request)) + +@login_required +def buyItem(request, itemid): + try: + item = Buyable.objects.get(id=itemid) + except Buyable.DoesNotExist: + # oh no! kein item mit der id :( mutax trollt rum) + return HttpResponseRedirect("/buy/") + purchase = Purchase(user=request.user, price=item.price, isDeposit=false ) + purchase.create(item) + purchase.save() + return render_to_response("buyables/itemBought.html", {'item': item}, RequestContext(request)) \ No newline at end of file diff --git a/k4ever/k4ever.db b/k4ever/k4ever.db index e8eefa0..c6beae2 100644 Binary files a/k4ever/k4ever.db and b/k4ever/k4ever.db differ diff --git a/k4ever/main/admin.py b/k4ever/main/admin.py new file mode 100644 index 0000000..4477270 --- /dev/null +++ b/k4ever/main/admin.py @@ -0,0 +1,5 @@ +from models import UserProfile +from django.contrib import admin + +admin.site.register(UserProfile) + diff --git a/k4ever/main/fields.py b/k4ever/main/fields.py new file mode 100644 index 0000000..fa4ad0b --- /dev/null +++ b/k4ever/main/fields.py @@ -0,0 +1,71 @@ +from django import forms +from django.core.exceptions import ValidationError +import re + +#class CurrencyField(forms.IntegerField): +# default_error_message = { +# 'invalid': _(u'Enter a number.'), +# } +# def __init__(self, positive=True, *args, **kwargs): +# super(IntegerField, self).__init__(*args, **kwargs) +# self.positive = positive +# def to_python(self, value): +# value = super(IntegerField, self).to_python(value) +# if value in validators.EMPTY_VALUES: +# return None +# try: +# value = float(value.replace(",", ".")) +# except: +# pass + +class CurrencyInput (forms.TextInput): + def render(self, name, value, attrs=None): + if value != '': + try: + value = u"%.2f" % value + except TypeError: + pass + return super(CurrencyInput, self).render(name, value, attrs) + + +class CurrencyField (forms.RegexField): + widget = CurrencyInput + currencyRe = re.compile(r'^[0-9]{1,5}([,\.][0-9][0-9]?)?$') + + #currencyRe = re.compile(r'^[0-9]{1,5}(.[0-9][0-9]?)?$') +# currencyRe = re.compile(r"^[0-9]") + def __init__(self, *args, **kwargs): + super(CurrencyField, self).__init__( + self.currencyRe, None, None, *args, **kwargs) + +#class CurrencyField(forms.FloatField): +# widget = CurrencyInput +# moneyre = re.compile(r"^[0-9]{1,5}([\.][0-9][0-9])?$") +# def __init__(self, positive=False, allowPerCent=False, *args, **kwargs): +# super(forms.FloatField, self).__init__(*args, **kwargs) +# self.positive = positive +# self.allowPerCent = allowPerCent + def to_python(self, value): + #return super(forms.FloatField, self).to_python(value) + #raise ValidationError("WTF WTF WTF %s " % value) + #value = value.replace(",", ".") + #try: + # value = super(forms.FloatField, self).to_python(value) + #except ValidationError, e: + # raise NotImplementedError("%s %s" % (e, value)) + #return value + value = value.replace(",", ".") + try: + value = float(value) + except (ValueError, TypeError): + raise ValidationError("Bitte gib eine Zahl ein") +# if not self.allowPerCent: +# tmpval = 100.0*value +# if tmpval == int(tmpval): +# raise ValidationError("Deine Zahl sollte nicht mehr als zwei Nachkommastellen haben. %s %s %s" % (tmpval, int(tmpval), tmpval-int(tmpval))) +# if self.positive and self.value < 0.0: +# raise ValidationError("Bitte gib eine positive Zahl an.") + return value + def clean(self, value): + value = super(CurrencyField, self).clean(value) + return float(value) diff --git a/k4ever/main/models.py b/k4ever/main/models.py index f9fd3c9..33eb976 100644 --- a/k4ever/main/models.py +++ b/k4ever/main/models.py @@ -3,7 +3,7 @@ from django.contrib.auth.models import User class UserProfile(models.Model): user = models.ForeignKey(User, unique=True) - balance = models.FloatField() + balance = models.FloatField(default=0.0) def __unicode__(self): - return "%s (Kontostand: %s)" % (self.user ,self.balance) \ No newline at end of file + return "%s (Kontostand: %s)" % (self.user ,self.balance) diff --git a/k4ever/main/templates/main/navigation-login.html b/k4ever/main/templates/main/navigation-login.html index f1b53f9..56f82f0 100644 --- a/k4ever/main/templates/main/navigation-login.html +++ b/k4ever/main/templates/main/navigation-login.html @@ -1,5 +1,5 @@ Main
-Buy
+Buy
Konto
History
{% if user.is_staff %} diff --git a/k4ever/media/img/buyable/484488a54d079e9f5714c16f6d848eab.gif b/k4ever/media/img/buyable/484488a54d079e9f5714c16f6d848eab.gif new file mode 100755 index 0000000..6cd7395 Binary files /dev/null and b/k4ever/media/img/buyable/484488a54d079e9f5714c16f6d848eab.gif differ diff --git a/k4ever/media/img/buyable/bier.jpg b/k4ever/media/img/buyable/bier.jpg new file mode 100755 index 0000000..b7b6469 Binary files /dev/null and b/k4ever/media/img/buyable/bier.jpg differ diff --git a/k4ever/settings.py b/k4ever/settings.py index 945b41a..9067c4e 100644 --- a/k4ever/settings.py +++ b/k4ever/settings.py @@ -50,7 +50,7 @@ MEDIA_ROOT = 'media/' # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash if there is a path component (optional in other cases). # Examples: "http://media.lawrence.com", "http://example.com/media/" -MEDIA_URL = 'media/' +MEDIA_URL = '/media/' # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. @@ -61,7 +61,7 @@ ADMIN_MEDIA_PREFIX = '/media/admin/' SECRET_KEY = 'l(f*a$l)_n_n_5#lh@rvhv(na^!lj1u#bow=c!*90(1w$5%b^j' # User Profile / Login stuff -AUTH_PROFILE_MODULE = 'main.models.UserProfile' +AUTH_PROFILE_MODULE = 'main.UserProfile' LOGIN_URL = '/user/login/' LOGIN_REDIRECT_URL = '/' diff --git a/k4ever/transaction/admin.py b/k4ever/transaction/admin.py index cb836ff..9c3f5ee 100644 --- a/k4ever/transaction/admin.py +++ b/k4ever/transaction/admin.py @@ -1,5 +1,24 @@ +# -*- coding: utf-8 -*- from models import Transaction, TransactionType from django.contrib import admin -admin.site.register(Transaction) +class TransactionAdmin(admin.ModelAdmin): + actions = ['really_delete_selected'] + + def get_actions(self, request): + actions = super(TransactionAdmin, self).get_actions(request) + del actions['delete_selected'] + return actions + # FIXME: Can we instead of replacing the whole page just + # hook the release process? Also - make this nicer + # in terms of localization/naming foo + def really_delete_selected(self, request, queryset): + for obj in queryset: + obj.delete() + num = queryset.count() + message = "%s transaction%s" % (num, (num != 1 and "s" or "")) + self.message_user(request, u"Erfolgreich %s gelöscht." % message) + really_delete_selected.short_description = u"Ausgewählte transactions löschen" + +admin.site.register(Transaction, TransactionAdmin) admin.site.register(TransactionType) diff --git a/k4ever/transaction/forms.py b/k4ever/transaction/forms.py new file mode 100644 index 0000000..3423a01 --- /dev/null +++ b/k4ever/transaction/forms.py @@ -0,0 +1,12 @@ +from django import forms +from models import Transaction +from main.fields import CurrencyField + +class TransactionForm(forms.ModelForm): + amount = CurrencyField() + class Meta: + model = Transaction + exclude = ('user', 'dateTime', 'checked') + def clean_amount(self): + data = self.cleaned_data['amount'] + return data \ No newline at end of file diff --git a/k4ever/transaction/models.py b/k4ever/transaction/models.py index 23ee89d..5bf9849 100644 --- a/k4ever/transaction/models.py +++ b/k4ever/transaction/models.py @@ -1,13 +1,12 @@ from django.db import models from django.contrib.auth.models import User - class TransactionType(models.Model): name = models.CharField(max_length=100) needsCheck = models.BooleanField(default=True) def __unicode__(self): - return unicode(self.name + (self.needsCheck and " (needs Check)" or "")) + return unicode(self.name) class Transaction(models.Model): user = models.ForeignKey(User) @@ -17,7 +16,23 @@ class Transaction(models.Model): checked = models.BooleanField(default=False) def __unicode__(self): - return u"%s for user %s (%s), %schecked" % (self.amount, self.user, self.transactionType, (self.checked and "" or "not ")) - + return u"%s for user %s (%s),%schecked" % (self.amount, self.user, self.transactionType, (self.checked and " " or " not ")) + # TODO: Find out what would happen if parent save/delete does not like us + def save(self, *args, **kwargs): + profile = self.user.get_profile() + if self.id == None: + # insert + profile.balance += self.amount + else: + # update + oldobj = Transaction.objects.get(id=self.id) + profile.balance += (self.amount-oldobj.amount) + profile.save() + super(Transaction, self).save(*args, **kwargs) + def delete(self, *args, **kwargs): + profile = self.user.get_profile() + profile.balance -= self.amount + profile.save() + super(Transaction, self).delete(*args, **kwargs) diff --git a/k4ever/transaction/templates/transaction/overview.html b/k4ever/transaction/templates/transaction/overview.html index 2f07ffe..b304eb5 100644 --- a/k4ever/transaction/templates/transaction/overview.html +++ b/k4ever/transaction/templates/transaction/overview.html @@ -1,14 +1,31 @@ {% extends "base.html" %} {% block "content" %} - + {% if transacted %} + YOU DID IT!. You transacted money! + {% endif %} +
+ {% csrf_token %} + + {{ form.as_table }} +
+ +
+ + {% for transaction in history %} - {{ transaction.amount }}, got that by {{ transaction.type }} + {% if forloop.first and transacted %} + + {% endif %} + [ {{ transaction.dateTime }} ] {{ transaction.amount|floatformat:2 }} Euronen, got that by {{ transaction.transactionType }} {% if transaction.checked %} ist eingegangen {% else %} noch nicht da {% endif %} + {% if forloop.first and transacted %} + + {% endif %}
{% endfor %} {% endblock %} diff --git a/k4ever/transaction/templates/transaction/transfer.html b/k4ever/transaction/templates/transaction/transfer.html new file mode 100644 index 0000000..c2888ce --- /dev/null +++ b/k4ever/transaction/templates/transaction/transfer.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} + +{% block "content" %} + No content here. +{% endblock %} diff --git a/k4ever/transaction/urls.py b/k4ever/transaction/urls.py index 60c9fc1..a689cdf 100644 --- a/k4ever/transaction/urls.py +++ b/k4ever/transaction/urls.py @@ -3,6 +3,7 @@ from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^$', 'transaction.views.overview'), + #(r'^transact/$', 'transaction.views.transact'), #(r'^transfer/$', 'transaction.views.transfer'), #(r'^checkTransfers/$', 'transaction.views.checkTransfers'), ) diff --git a/k4ever/transaction/views.py b/k4ever/transaction/views.py index 8d7115e..8b04ddd 100644 --- a/k4ever/transaction/views.py +++ b/k4ever/transaction/views.py @@ -1,20 +1,36 @@ from django.shortcuts import render_to_response from django.template import RequestContext from django.contrib.auth.decorators import login_required +from django.http import HttpResponseRedirect from models import Transaction, TransactionType +from forms import TransactionForm +import datetime @login_required def overview(request): - history = Transaction.objects.filter(user=request.user).order_by("dateTime") - return render_to_response("transaction/overview.html", {'history': history}, RequestContext(request)) + history = Transaction.objects.filter(user=request.user).order_by("-dateTime") + transacted = False + if request.method == 'POST': + transaction = Transaction(user=request.user, dateTime=datetime.datetime.now()) + form = TransactionForm(request.POST, instance=transaction) + if form.is_valid(): + form.save() + form = TransactionForm() + transacted = True + else: + pass + else: + form = TransactionForm() + return render_to_response("transaction/overview.html", {'history': history, 'form': form, 'transacted': transacted}, RequestContext(request)) -#@login_required -#def transfer(request): -# if request.method == 'POST': -# -# return render_to_response("transaction/transfered.html", RequestContext(request)) +@login_required +def transact(request): + if request.method == 'POST': + return render_to_response("transaction/transfered.html", RequestContext(request)) + else: + return HttpResponseRedirect("/transaction/") #@kassenwart_required #def checkTransfers(request): -# transfers = Transaction.objects.filter(checked=False).sort("dateTime") +# transfers = Transaction.objects.filter(checked=False).order_by("dateTime") # return render_to_response("transaction/uncheckedTransfers.html", {'transfers' : tranfers}, RequestContext(request)) \ No newline at end of file diff --git a/k4ever/urls.py b/k4ever/urls.py index 434639b..a5469ca 100644 --- a/k4ever/urls.py +++ b/k4ever/urls.py @@ -15,7 +15,8 @@ urlpatterns = patterns('', (r'^$', 'main.views.startpage'), (r'^user/', include('main.urls')), (r'^transaction/', include('transaction.urls')), - #(r'^buy/', include('buyable.urls')), + (r'^store/', include('buyable.urls')), + (r'^media/(?P.*)$', 'django.views.static.serve', {'document_root': 'media'}), # Uncomment the next line to enable the admin: (r'^admin/', include(admin.site.urls)),