Transactions funtzen, kaufen fast

This commit is contained in:
seba 2010-10-16 17:33:18 +02:00
parent 4615033732
commit 9450f3326b
21 changed files with 244 additions and 22 deletions

View File

@ -29,3 +29,7 @@ class Purchase(models.Model):
def __unicode__(self): def __unicode__(self):
return "%s%s, %s by %s" % (self.buyable.name, self.isDeposit and " (deposit)" or "", self.price, self.user) 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

View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block "content" %}
{% if item %}
You got the item {{ item }}
{% else %}
No item found :(
{% endif %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block "content" %}
{% for item in items %}
<img src="{{ MEDIA_URL }}{{ item.image }}">{{ item }} <a href="/store/show/{{ item.id }}">{{ item.name }}</a>
{% endfor %}
{% endblock %}

8
k4ever/buyable/urls.py Normal file
View File

@ -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'),
)

View File

@ -1 +1,33 @@
# Create your views here. # 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))

Binary file not shown.

5
k4ever/main/admin.py Normal file
View File

@ -0,0 +1,5 @@
from models import UserProfile
from django.contrib import admin
admin.site.register(UserProfile)

71
k4ever/main/fields.py Normal file
View File

@ -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)

View File

@ -3,7 +3,7 @@ from django.contrib.auth.models import User
class UserProfile(models.Model): class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True) user = models.ForeignKey(User, unique=True)
balance = models.FloatField() balance = models.FloatField(default=0.0)
def __unicode__(self): def __unicode__(self):
return "%s (Kontostand: %s)" % (self.user ,self.balance) return "%s (Kontostand: %s)" % (self.user ,self.balance)

View File

@ -1,5 +1,5 @@
<b>Main</b><br /> <b>Main</b><br />
<a href="/buy/">Buy</a><br /> <a href="/store/">Buy</a><br />
<a href="/transaction/">Konto</a><br /> <a href="/transaction/">Konto</a><br />
<a href="/">History</a><br /> <a href="/">History</a><br />
{% if user.is_staff %} {% if user.is_staff %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
k4ever/media/img/buyable/bier.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -50,7 +50,7 @@ MEDIA_ROOT = 'media/'
# URL that handles the media served from MEDIA_ROOT. Make sure to use a # 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). # trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/" # 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 # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash. # 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' SECRET_KEY = 'l(f*a$l)_n_n_5#lh@rvhv(na^!lj1u#bow=c!*90(1w$5%b^j'
# User Profile / Login stuff # User Profile / Login stuff
AUTH_PROFILE_MODULE = 'main.models.UserProfile' AUTH_PROFILE_MODULE = 'main.UserProfile'
LOGIN_URL = '/user/login/' LOGIN_URL = '/user/login/'
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = '/'

View File

@ -1,5 +1,24 @@
# -*- coding: utf-8 -*-
from models import Transaction, TransactionType from models import Transaction, TransactionType
from django.contrib import admin 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) admin.site.register(TransactionType)

View File

@ -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

View File

@ -1,13 +1,12 @@
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
class TransactionType(models.Model): class TransactionType(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
needsCheck = models.BooleanField(default=True) needsCheck = models.BooleanField(default=True)
def __unicode__(self): def __unicode__(self):
return unicode(self.name + (self.needsCheck and " (needs Check)" or "")) return unicode(self.name)
class Transaction(models.Model): class Transaction(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
@ -17,7 +16,23 @@ class Transaction(models.Model):
checked = models.BooleanField(default=False) checked = models.BooleanField(default=False)
def __unicode__(self): 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)

View File

@ -1,14 +1,31 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block "content" %} {% block "content" %}
{% if transacted %}
<font color="green"><b>YOU DID IT!</b></font>. You transacted money!
{% endif %}
<form method="POST" action="/transaction/">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Senden">
</form>
{% for transaction in history %} {% for transaction in history %}
{{ transaction.amount }}, got that by {{ transaction.type }} {% if forloop.first and transacted %}
<b>
{% endif %}
[ {{ transaction.dateTime }} ] {{ transaction.amount|floatformat:2 }} Euronen, got that by {{ transaction.transactionType }}
{% if transaction.checked %} {% if transaction.checked %}
ist eingegangen ist eingegangen
{% else %} {% else %}
noch nicht da noch nicht da
{% endif %} {% endif %}
{% if forloop.first and transacted %}
</b>
{% endif %}
<br /> <br />
{% endfor %} {% endfor %}
{% endblock %} {% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "base.html" %}
{% block "content" %}
No content here.
{% endblock %}

View File

@ -3,6 +3,7 @@ from django.conf.urls.defaults import *
urlpatterns = patterns('', urlpatterns = patterns('',
(r'^$', 'transaction.views.overview'), (r'^$', 'transaction.views.overview'),
#(r'^transact/$', 'transaction.views.transact'),
#(r'^transfer/$', 'transaction.views.transfer'), #(r'^transfer/$', 'transaction.views.transfer'),
#(r'^checkTransfers/$', 'transaction.views.checkTransfers'), #(r'^checkTransfers/$', 'transaction.views.checkTransfers'),
) )

View File

@ -1,20 +1,36 @@
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template import RequestContext from django.template import RequestContext
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from models import Transaction, TransactionType from models import Transaction, TransactionType
from forms import TransactionForm
import datetime
@login_required @login_required
def overview(request): def overview(request):
history = Transaction.objects.filter(user=request.user).order_by("dateTime") history = Transaction.objects.filter(user=request.user).order_by("-dateTime")
return render_to_response("transaction/overview.html", {'history': history}, RequestContext(request)) 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 @login_required
#def transfer(request): def transact(request):
# if request.method == 'POST': if request.method == 'POST':
# return render_to_response("transaction/transfered.html", RequestContext(request))
# return render_to_response("transaction/transfered.html", RequestContext(request)) else:
return HttpResponseRedirect("/transaction/")
#@kassenwart_required #@kassenwart_required
#def checkTransfers(request): #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)) # return render_to_response("transaction/uncheckedTransfers.html", {'transfers' : tranfers}, RequestContext(request))

View File

@ -15,7 +15,8 @@ urlpatterns = patterns('',
(r'^$', 'main.views.startpage'), (r'^$', 'main.views.startpage'),
(r'^user/', include('main.urls')), (r'^user/', include('main.urls')),
(r'^transaction/', include('transaction.urls')), (r'^transaction/', include('transaction.urls')),
#(r'^buy/', include('buyable.urls')), (r'^store/', include('buyable.urls')),
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': 'media'}),
# Uncomment the next line to enable the admin: # Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)), (r'^admin/', include(admin.site.urls)),