Transactions funtzen, kaufen fast
This commit is contained in:
parent
4615033732
commit
9450f3326b
|
@ -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)
|
||||
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
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block "content" %}
|
||||
{% if item %}
|
||||
You got the item {{ item }}
|
||||
{% else %}
|
||||
No item found :(
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -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 %}
|
|
@ -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'),
|
||||
)
|
|
@ -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))
|
BIN
k4ever/k4ever.db
BIN
k4ever/k4ever.db
Binary file not shown.
|
@ -0,0 +1,5 @@
|
|||
from models import UserProfile
|
||||
from django.contrib import admin
|
||||
|
||||
admin.site.register(UserProfile)
|
||||
|
|
@ -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)
|
|
@ -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)
|
||||
return "%s (Kontostand: %s)" % (self.user ,self.balance)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<b>Main</b><br />
|
||||
<a href="/buy/">Buy</a><br />
|
||||
<a href="/store/">Buy</a><br />
|
||||
<a href="/transaction/">Konto</a><br />
|
||||
<a href="/">History</a><br />
|
||||
{% if user.is_staff %}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -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 = '/'
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -1,14 +1,31 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% 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 %}
|
||||
{{ 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 %}
|
||||
ist eingegangen
|
||||
{% else %}
|
||||
noch nicht da
|
||||
{% endif %}
|
||||
{% if forloop.first and transacted %}
|
||||
</b>
|
||||
{% endif %}
|
||||
<br />
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block "content" %}
|
||||
No content here.
|
||||
{% endblock %}
|
|
@ -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'),
|
||||
)
|
||||
|
|
|
@ -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))
|
|
@ -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<path>.*)$', 'django.views.static.serve', {'document_root': 'media'}),
|
||||
|
||||
# Uncomment the next line to enable the admin:
|
||||
(r'^admin/', include(admin.site.urls)),
|
||||
|
|
Loading…
Reference in New Issue