Merge branch 'morejson'

This commit is contained in:
Sebastian Lohff 2012-02-01 23:01:20 +01:00
commit 551c8641d3
13 changed files with 183 additions and 41 deletions

View File

@ -0,0 +1,5 @@
[client-barcode]
SERVER_URL = https://example.org:443/api2/
SERVER_USER = user
SERVER_PASSWORD = password
#CLIENT_DEBUG = 1

View File

@ -8,6 +8,7 @@ from __future__ import print_function
import freitagslib.network as net import freitagslib.network as net
from freitagslib.commands import BuyCommand, DepositCommand from freitagslib.commands import BuyCommand, DepositCommand
from freitagslib.encoding import asciify from freitagslib.encoding import asciify
from freitagslib.settings import settings, Settings
import colorama import colorama
from colorama import Fore, Style from colorama import Fore, Style
@ -519,6 +520,10 @@ def read_line(f, timeout, timeout_func):
def main(): def main():
colorama.init() colorama.init()
if not settings.load("freitagskasse.conf"):
sys.exit(1)
status = Status() status = Status()
global scroll_line1,scroll_line2 global scroll_line1,scroll_line2
global myDisplay global myDisplay

View File

@ -53,7 +53,7 @@ class BuyCommand(object):
raise ValueError("BuyCommand in illegal state") raise ValueError("BuyCommand in illegal state")
def run(self, user_name): def run(self, user_name):
net.buy_item(self._item.id, what_about_it=self._what_to_buy(), user_name=user_name) raise NotImplementedError('BuyCommand.run(user_name)')
def item_name(self): def item_name(self):
return self._item.name return self._item.name

View File

@ -18,39 +18,43 @@ if __name__ == '__main__':
sys.path.append('.') sys.path.append('.')
from freitagslib.item import Item from freitagslib.item import Item
from freitagslib.tools import require_type from freitagslib.tools import require_type
from freitagslib.settings import settings, Settings
DEPOSIT_CASH = 1 DEPOSIT_CASH = 1
DEPOSIT_BANK = 2 DEPOSIT_BANK = 2
_BASE_URL = 'https://k4ever.freitagsrunde.org:443/api2/'
_auth = base64.encodestring('%s:%s' % (os.environ['BARCODE_PLUGIN_USER'], os.environ['BARCODE_PLUGIN_PASS'])).rstrip()
_headers = {'Authorization':'Basic %s' % _auth}
ITEM_ONLY, DEPOSIT_ONLY, ITEM_AND_DEPOSIT = range(3) ITEM_ONLY, DEPOSIT_ONLY, ITEM_AND_DEPOSIT = range(3)
if bool(os.environ.get('BARCODE_PLUGIN_DEBUG', False)): def _urlopen(*args):
_h = urllib2.HTTPHandler(debuglevel=1) if settings.CLIENT_DEBUG:
_opener = urllib2.build_opener(_h) _h = urllib2.HTTPHandler(debuglevel=1)
_urlopen = _opener.open _opener = urllib2.build_opener(_h)
else: _func = _opener.open
_urlopen = urllib2.urlopen else:
_func = urllib2.urlopen
return _func(*args)
def _get_default_headers():
_auth = base64.encodestring('%s:%s' % (settings.SERVER_USER, settings.SERVER_PASSWORD)).rstrip()
_headers = {'Authorization':'Basic %s' % _auth}
return _headers
def _request(api_rel_url, data, method, headers=None): def _request(api_rel_url, data, method, headers=None):
url = _BASE_URL + api_rel_url url = settings.SERVER_URL + api_rel_url
if isinstance(data, dict): if isinstance(data, dict):
data = urllib.urlencode(data) data = urllib.urlencode(data)
# Add default headers # Add default headers
if headers is None: if headers is None:
final_headers = _headers final_headers = _get_default_headers()
else: else:
final_headers = copy.copy(_headers) final_headers = copy.copy(_get_default_headers())
final_headers.update(headers) final_headers.update(headers)
if method == 'GET': if method == 'GET':
@ -71,16 +75,6 @@ def get_user_name_from_auth_blob(authblob):
return d['username'] return d['username']
def buy_item(item_id, what_about_it, user_name):
require_type(int, item_id)
assert(what_about_it in (ITEM_ONLY, DEPOSIT_ONLY, ITEM_AND_DEPOSIT))
content = _request('buyable/item/' + urllib.quote(str(item_id)),
{'user':user_name, 'deposit':what_about_it, 'amount':1}, method='POST')
if content != 'Created':
raise ValueError('Server says "%s"' % content)
def bulk_buy(buycommands, user_name): def bulk_buy(buycommands, user_name):
item_ids = tuple(e.item_id() for e in buycommands if e.includes_commodity()) item_ids = tuple(e.item_id() for e in buycommands if e.includes_commodity())
deposit_ids = tuple(e.item_id() for e in buycommands if e.includes_deposit()) deposit_ids = tuple(e.item_id() for e in buycommands if e.includes_deposit())
@ -99,7 +93,8 @@ def bulk_buy(buycommands, user_name):
'Content-Length':len(data) 'Content-Length':len(data)
} }
content = _request('buyable/item/bulkbuy/', data, 'POST', headers=headers) content = _request('buyable/item/bulkbuy/', data, 'POST', headers=headers)
if content != 'Created': d = json.loads(content)
if not d['success']:
raise ValueError('Server says "%s"' % content) raise ValueError('Server says "%s"' % content)
@ -123,15 +118,17 @@ def deposit(amount, transaction_type, user_name):
content = _request('account/transactions/transact/', content = _request('account/transactions/transact/',
{'user':user_name, 'amount':amount, 'type':transaction_type}, method='POST') {'user':user_name, 'amount':amount, 'type':transaction_type}, method='POST')
if content != 'OK': d = json.loads(content)
if not d['success']:
raise ValueError('Server says "%s"' % content) raise ValueError('Server says "%s"' % content)
if __name__ == '__main__': if __name__ == '__main__':
user_name = get_user_name_from_auth_blob(os.environ['BARCODE_PLUGIN_TEST_AUTH_BLOB']) if not settings.load('freitagskasse.conf', (('TEST_AUTH_BLOB', str, None), )):
print('User name: ' + user_name) sys.exit(1)
buy_item(1, True, user_name) user_name = get_user_name_from_auth_blob(settings.TEST_AUTH_BLOB)
print('User name: ' + user_name)
balance = get_balance(user_name) balance = get_balance(user_name)
print('Balance is %f, type is "%s"' % (balance, type(balance).__name__)) print('Balance is %f, type is "%s"' % (balance, type(balance).__name__))

View File

@ -0,0 +1,63 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
# Licensed under GPL v3 or later
from __future__ import print_function
import sys
import ConfigParser
_SECTION = 'client-barcode'
_KEYS = (
# Key, type, default
('CLIENT_DEBUG', bool, False), # Should go first to enable debugging as early as possible
('SERVER_URL', str, None),
('SERVER_USER', str, None),
('SERVER_PASSWORD', str, None),
)
_DEFAULTS = dict([(key, str(default))
for (key, _type, default)
in _KEYS
if default is not None])
class Settings:
def __init__(self):
pass
def load(self, filename, _additional_keys=None):
additional_keys = () if _additional_keys is None else _additional_keys
cp = ConfigParser.ConfigParser(_DEFAULTS)
if not cp.read(filename):
print('FATAL: Config file "%s" could not be parsed.' % (filename), file=sys.stderr)
return False
valid = True
for key, _type, dummy in _KEYS + additional_keys:
try:
if _type is bool:
value = cp.getboolean(_SECTION, key)
else:
value = cp.get(_SECTION, key)
except ValueError:
print('ERROR: Key "%s" in config file "%s" must be of type "%s".' \
% (key, filename, _type.__name__), file=sys.stderr)
valid = False
except ConfigParser.NoOptionError:
print('ERROR: Config file "%s" misses required key "%s.%s".' \
% (filename, _SECTION, key), file=sys.stderr)
valid = False
else:
setattr(self, key, value)
if self.CLIENT_DEBUG:
print('DEBUG: CONFIG: %s.%s=%s("%s")' % (_SECTION, key, type(value).__name__, value))
return valid
settings = Settings()

View File

@ -116,7 +116,7 @@ class BuyableItemHandler(BaseHandler):
p.save(saveOrder=False) p.save(saveOrder=False)
order.save() order.save()
return {'success': True, 'balance': request.user.getProfile().balance} return {'success': True, 'balance': request.user.get_profile().balance}
def bulkBuy(self, request): def bulkBuy(self, request):
"""Buy a :class:`Buyable <buyable.models.Buyable>` item. """Buy a :class:`Buyable <buyable.models.Buyable>` item.
@ -179,7 +179,7 @@ class BuyableItemHandler(BaseHandler):
p.save(saveOrder=False) p.save(saveOrder=False)
order.save() order.save()
return {'success': True, 'balance': request.user.getProfile().balance} return {'success': True, 'balance': request.user.get_profile().balance}
class BuyableTypeHandler(BaseHandler): class BuyableTypeHandler(BaseHandler):
@ -290,7 +290,7 @@ class TransactionTransactHandler(BaseHandler):
return getError(rc.BAD_REQUEST, "Your TransactionType could not be found") return getError(rc.BAD_REQUEST, "Your TransactionType could not be found")
trans = Transaction(user=request.user, transactionType=tType, amount=amount, checked=not tType.needsCheck) trans = Transaction(user=request.user, transactionType=tType, amount=amount, checked=not tType.needsCheck)
trans.save() trans.save()
return {'success': True, 'balance': request.user.getProfile().balance} return {'success': True, 'balance': request.user.get_profile().balance}
class TransactionTypeHandler(BaseHandler): class TransactionTypeHandler(BaseHandler):
"""Handler for :class:`Transaction Types <transaction.models.TransactionType>` """Handler for :class:`Transaction Types <transaction.models.TransactionType>`
@ -348,7 +348,7 @@ class TransactionVirtualHandler(BaseHandler):
return getError(rc.BAD_REQUEST, "The recipient user does not exist.") return getError(rc.BAD_REQUEST, "The recipient user does not exist.")
trans = VirtualTransaction(user=request.user, recipient=recipient, amount=amount, comment=comment) trans = VirtualTransaction(user=request.user, recipient=recipient, amount=amount, comment=comment)
trans.save() trans.save()
return {'success': True, 'balance': request.user.getProfile().balance} return {'success': True, 'balance': request.user.get_profile().balance}
class AccountBalanceHandler(BaseHandler): class AccountBalanceHandler(BaseHandler):
"""Handler for the user's account balance""" """Handler for the user's account balance"""

View File

@ -0,0 +1,15 @@
{% extends "base.html" %}
{% comment %}
# This file is part of k4ever, a point-of-sale system
# Contact............ <k4ever@lists.someserver.de>
# Website............ http://k4ever.someserver.de/
# Bug tracker........ http://k4ever.someserver.de/report
#
# Licensed under GNU Affero General Public License v3 or later
{% endcomment %}
{% block "content" %}
<h2>Whoops! Wir glauben du gehörst hier nicht hin...</h2>
<p>...zumindest sagt uns das dein Ausweis. Wie dem auch sei: Bis hierhin und nicht weiter</p>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "base.html" %}
{% comment %}
# This file is part of k4ever, a point-of-sale system
# Contact............ <k4ever@lists.someserver.de>
# Website............ http://k4ever.someserver.de/
# Bug tracker........ http://k4ever.someserver.de/report
#
# Licensed under GNU Affero General Public License v3 or later
{% endcomment %}
{% block "content" %}
<h2>Whoops! Da ist was schiefgegangen</h2>
<p>Die Seite, die du angefordert hast, konnte nicht gefunden werden.</p>
<p>Zahllose Ponies sind bereits auf der Suche nach ihr.</p>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends "base.html" %}
{% comment %}
# This file is part of k4ever, a point-of-sale system
# Contact............ <k4ever@lists.someserver.de>
# Website............ http://k4ever.someserver.de/
# Bug tracker........ http://k4ever.someserver.de/report
#
# Licensed under GNU Affero General Public License v3 or later
{% endcomment %}
{% block head %}
<link rel="stylesheet" media="screen" type="text/css"
href="/media/css/style.css" />
{% block extrastyle %}{% endblock %}
<script type="text/javascript">
var MEDIA_URL = "/media/";
</script>
<script type='text/javascript' src="/media/js/jquery-1.5.1.js"></script>
<script type='text/javascript' src="/media/js/jquery-ui-1.8.10.custom.min.js"></script>
<script type='text/javascript' src="/media/js/jquery.ui.autocomplete.html.js"></script>
<script type='text/javascript' src="/media/js/jquery.gritter.min.js"></script>
<script type='text/javascript' src="/media/js/k4ever.js"></script>
{% endblock head %}
{% block "content" %}
<h2>Whoops! Da ist was schiefgegangen</h2>
<p>Bei der Bearbeitung deiner Anfrage ist ein Fehler aufgetreten für den du nichts kannst. Sorry!</p>
<p>Bitte nutze den Zurück-Button deines Browsers um zurückzufahren.</p>
{% endblock %}

View File

@ -11,11 +11,12 @@
<html {% if user.is_authenticated %}class="loggedIn"{% endif %}> <html {% if user.is_authenticated %}class="loggedIn"{% endif %}>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
{% block head %}
<link rel="stylesheet" media="screen" type="text/css" <link rel="stylesheet" media="screen" type="text/css"
href="{{ MEDIA_URL }}css/style.css" /> href="{{ MEDIA_URL }}css/style.css" />
{% block extrastyle %}{% endblock %} {% block extrastyle %}{% endblock %}
<script type="text/javascript"> <script type="text/javascript">
var MEDIA_URL = "{{MEDIA_URL}}"; var MEDIA_URL = "{{ MEDIA_URL }}";
</script> </script>
<script type='text/javascript' src="{{ MEDIA_URL }}js/jquery-1.5.1.js"></script> <script type='text/javascript' src="{{ MEDIA_URL }}js/jquery-1.5.1.js"></script>
<script type='text/javascript' src="{{ MEDIA_URL }}js/jquery-ui-1.8.10.custom.min.js"></script> <script type='text/javascript' src="{{ MEDIA_URL }}js/jquery-ui-1.8.10.custom.min.js"></script>
@ -23,6 +24,7 @@
<script type='text/javascript' src="{{ MEDIA_URL }}js/jquery.gritter.min.js"></script> <script type='text/javascript' src="{{ MEDIA_URL }}js/jquery.gritter.min.js"></script>
<script type='text/javascript' src="{{ MEDIA_URL }}js/k4ever.js"></script> <script type='text/javascript' src="{{ MEDIA_URL }}js/k4ever.js"></script>
{% block extrahead %}{% endblock %} {% block extrahead %}{% endblock %}
{% endblock head %}
<title>Freitagsrundenkasse{% block "title" %}{% endblock %}</title> <title>Freitagsrundenkasse{% block "title" %}{% endblock %}</title>
</head> </head>
<body{%block bodyargs %}{%endblock%}> <body{%block bodyargs %}{%endblock%}>

View File

@ -29,8 +29,3 @@
<input type="hidden" name="next" value="{{ next }}" /> <input type="hidden" name="next" value="{{ next }}" />
</form> </form>
<div class="notice">
<h2>Das Kassensystem ist 'Aktiv' - nutzt euren Frunden-Account</h2>
</div>

View File

@ -25,6 +25,13 @@ jQuery(document).ready(function($) {
}, options), callback); }, options), callback);
}; };
var updateBalance = function(newBalance) {
var balanceString = $("span.balance").text().split(": ");
balanceString[1] = parseFloat(newBalance).toFixed(2).replace(".", ",") + " €";
$("span.balance").text(balanceString.join(": "));
}
$.extend($.gritter.options, { $.extend($.gritter.options, {
position: "bottom-right", position: "bottom-right",
fade_in_speed: 250, fade_in_speed: 250,
@ -61,6 +68,7 @@ jQuery(document).ready(function($) {
}); });
dataContainer.children().removeClass("locked"); dataContainer.children().removeClass("locked");
updateBalance(data.balance);
}, options); }, options);
}); });
@ -121,7 +129,7 @@ jQuery(document).ready(function($) {
if(status === "success") { if(status === "success") {
selected_item.addClass("success"); selected_item.addClass("success");
//TODO neuer kontostand wär schnaffte updateBalance(data.balance);
} else { } else {
selected_item.addClass("failure"); selected_item.addClass("failure");
} }

View File

@ -15,6 +15,7 @@ import shutil
sys.path.insert(0, '../client-barcode') # TODO sys.path.insert(0, '../client-barcode') # TODO
from freitagslib.network import _request from freitagslib.network import _request
from freitagslib.item import Item from freitagslib.item import Item
from freitagslib.settings import settings, Settings
_NAME_BLACKLIST = ('foo', ) _NAME_BLACKLIST = ('foo', )
@ -38,6 +39,9 @@ if __name__ == '__main__':
sys.exit(1) sys.exit(1)
output_filename = sys.argv[1] output_filename = sys.argv[1]
if not settings.load('../client-barcode/freitagskasse.conf'):
sys.exit(1)
content = _request('buyable/item/', None, method='GET') content = _request('buyable/item/', None, method='GET')
doc = json.loads(content) doc = json.loads(content)
items = [Item(e) for e in doc] items = [Item(e) for e in doc]