Browse Source

Merge branch 'morejson'

Sebastian Lohff 9 years ago
parent
commit
551c8641d3

+ 5
- 0
client-barcode/freitagskasse.conf.sample View File

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

+ 5
- 0
client-barcode/freitagskasse.py View File

@@ -8,6 +8,7 @@ from __future__ import print_function
8 8
 import freitagslib.network as net
9 9
 from freitagslib.commands import BuyCommand, DepositCommand
10 10
 from freitagslib.encoding import asciify
11
+from freitagslib.settings import settings, Settings
11 12
 
12 13
 import colorama
13 14
 from colorama import Fore, Style
@@ -519,6 +520,10 @@ def read_line(f, timeout, timeout_func):
519 520
 
520 521
 def main():
521 522
 	colorama.init()
523
+
524
+	if not settings.load("freitagskasse.conf"):
525
+		sys.exit(1)
526
+
522 527
 	status = Status()
523 528
 	global scroll_line1,scroll_line2
524 529
 	global myDisplay

+ 1
- 1
client-barcode/freitagslib/commands.py View File

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

+ 25
- 28
client-barcode/freitagslib/network.py View File

@@ -18,39 +18,43 @@ if __name__ == '__main__':
18 18
 	sys.path.append('.')
19 19
 from freitagslib.item import Item
20 20
 from freitagslib.tools import require_type
21
+from freitagslib.settings import settings, Settings
21 22
 
22 23
 
23 24
 DEPOSIT_CASH = 1
24 25
 DEPOSIT_BANK = 2
25 26
 
26 27
 
27
-_BASE_URL = 'https://k4ever.freitagsrunde.org:443/api2/'
28
+ITEM_ONLY, DEPOSIT_ONLY, ITEM_AND_DEPOSIT = range(3)
28 29
 
29
-_auth = base64.encodestring('%s:%s' % (os.environ['BARCODE_PLUGIN_USER'], os.environ['BARCODE_PLUGIN_PASS'])).rstrip()
30
-_headers = {'Authorization':'Basic %s' % _auth}
31 30
 
32
-ITEM_ONLY, DEPOSIT_ONLY, ITEM_AND_DEPOSIT = range(3)
31
+def _urlopen(*args):
32
+	if settings.CLIENT_DEBUG:
33
+		_h = urllib2.HTTPHandler(debuglevel=1)
34
+		_opener = urllib2.build_opener(_h)
35
+		_func = _opener.open
36
+	else:
37
+		_func = urllib2.urlopen
38
+	return _func(*args)
33 39
 
34 40
 
35
-if bool(os.environ.get('BARCODE_PLUGIN_DEBUG', False)):
36
-	_h = urllib2.HTTPHandler(debuglevel=1)
37
-	_opener = urllib2.build_opener(_h)
38
-	_urlopen = _opener.open
39
-else:
40
-	_urlopen = urllib2.urlopen
41
+def _get_default_headers():
42
+	_auth = base64.encodestring('%s:%s' % (settings.SERVER_USER, settings.SERVER_PASSWORD)).rstrip()
43
+	_headers = {'Authorization':'Basic %s' % _auth}
44
+	return _headers
41 45
 
42 46
 
43 47
 def _request(api_rel_url, data, method, headers=None):
44
-	url = _BASE_URL + api_rel_url
48
+	url = settings.SERVER_URL + api_rel_url
45 49
 
46 50
 	if isinstance(data, dict):
47 51
 		data = urllib.urlencode(data)
48 52
 
49 53
 	# Add default headers
50 54
 	if headers is None:
51
-		final_headers = _headers
55
+		final_headers = _get_default_headers()
52 56
 	else:
53
-		final_headers = copy.copy(_headers)
57
+		final_headers = copy.copy(_get_default_headers())
54 58
 		final_headers.update(headers)
55 59
 
56 60
 	if method == 'GET':
@@ -71,16 +75,6 @@ def get_user_name_from_auth_blob(authblob):
71 75
 	return d['username']
72 76
 
73 77
 
74
-def buy_item(item_id, what_about_it, user_name):
75
-	require_type(int, item_id)
76
-	assert(what_about_it in (ITEM_ONLY, DEPOSIT_ONLY, ITEM_AND_DEPOSIT))
77
-
78
-	content = _request('buyable/item/' + urllib.quote(str(item_id)),
79
-			{'user':user_name, 'deposit':what_about_it, 'amount':1}, method='POST')
80
-	if content != 'Created':
81
-		raise ValueError('Server says "%s"' % content)
82
-
83
-
84 78
 def bulk_buy(buycommands, user_name):
85 79
 	item_ids = tuple(e.item_id() for e in buycommands if e.includes_commodity())
86 80
 	deposit_ids = tuple(e.item_id() for e in buycommands if e.includes_deposit())
@@ -99,7 +93,8 @@ def bulk_buy(buycommands, user_name):
99 93
 		'Content-Length':len(data)
100 94
 	}
101 95
 	content = _request('buyable/item/bulkbuy/', data, 'POST', headers=headers)
102
-	if content != 'Created':
96
+	d = json.loads(content)
97
+	if not d['success']:
103 98
 		raise ValueError('Server says "%s"' % content)
104 99
 
105 100
 
@@ -123,15 +118,17 @@ def deposit(amount, transaction_type, user_name):
123 118
 
124 119
 	content = _request('account/transactions/transact/',
125 120
 			{'user':user_name, 'amount':amount, 'type':transaction_type}, method='POST')
126
-	if content != 'OK':
121
+	d = json.loads(content)
122
+	if not d['success']:
127 123
 		raise ValueError('Server says "%s"' % content)
128 124
 
129 125
 
130 126
 if __name__ == '__main__':
131
-	user_name = get_user_name_from_auth_blob(os.environ['BARCODE_PLUGIN_TEST_AUTH_BLOB'])
132
-	print('User name: ' + user_name)
127
+	if not settings.load('freitagskasse.conf', (('TEST_AUTH_BLOB', str, None), )):
128
+		sys.exit(1)
133 129
 
134
-	buy_item(1, True, user_name)
130
+	user_name = get_user_name_from_auth_blob(settings.TEST_AUTH_BLOB)
131
+	print('User name: ' + user_name)
135 132
 
136 133
 	balance = get_balance(user_name)
137 134
 	print('Balance is %f, type is "%s"' % (balance, type(balance).__name__))

+ 63
- 0
client-barcode/freitagslib/settings.py View File

@@ -0,0 +1,63 @@
1
+#! /usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+#
4
+# Copyright (C) 2011 Sebastian Pipping <sebastian@pipping.org>
5
+# Licensed under GPL v3 or later
6
+
7
+from __future__ import print_function
8
+import sys
9
+import ConfigParser
10
+
11
+
12
+_SECTION = 'client-barcode'
13
+
14
+_KEYS = (
15
+	# Key, type, default
16
+	('CLIENT_DEBUG', bool, False),  # Should go first to enable debugging as early as possible
17
+	('SERVER_URL', str, None),
18
+	('SERVER_USER', str, None),
19
+	('SERVER_PASSWORD', str, None),
20
+)
21
+
22
+_DEFAULTS = dict([(key, str(default))
23
+	for (key, _type, default)
24
+	in _KEYS
25
+	if default is not None])
26
+
27
+
28
+class Settings:
29
+	def __init__(self):
30
+		pass
31
+
32
+	def load(self, filename, _additional_keys=None):
33
+		additional_keys = () if _additional_keys is None else _additional_keys
34
+
35
+		cp = ConfigParser.ConfigParser(_DEFAULTS)
36
+		if not cp.read(filename):
37
+			print('FATAL: Config file "%s" could not be parsed.' % (filename), file=sys.stderr)
38
+			return False
39
+
40
+		valid = True
41
+		for key, _type, dummy in _KEYS + additional_keys:
42
+			try:
43
+				if _type is bool:
44
+					value = cp.getboolean(_SECTION, key)
45
+				else:
46
+					value = cp.get(_SECTION, key)
47
+			except ValueError:
48
+				print('ERROR: Key "%s" in config file "%s" must be of type "%s".' \
49
+						% (key, filename, _type.__name__), file=sys.stderr)
50
+				valid = False
51
+			except ConfigParser.NoOptionError:
52
+				print('ERROR: Config file "%s" misses required key "%s.%s".' \
53
+						% (filename, _SECTION, key), file=sys.stderr)
54
+				valid = False
55
+			else:
56
+				setattr(self, key, value)
57
+				if self.CLIENT_DEBUG:
58
+					print('DEBUG: CONFIG: %s.%s=%s("%s")' % (_SECTION, key, type(value).__name__, value))
59
+
60
+		return valid
61
+
62
+
63
+settings = Settings()

+ 4
- 4
k4ever/api2/handlers.py View File

@@ -116,7 +116,7 @@ class BuyableItemHandler(BaseHandler):
116 116
 				p.save(saveOrder=False)
117 117
 		order.save()
118 118
 		
119
-		return {'success': True, 'balance': request.user.getProfile().balance}
119
+		return {'success': True, 'balance': request.user.get_profile().balance}
120 120
 		
121 121
 	def bulkBuy(self, request):
122 122
 		"""Buy a :class:`Buyable <buyable.models.Buyable>` item.
@@ -179,7 +179,7 @@ class BuyableItemHandler(BaseHandler):
179 179
 			p.save(saveOrder=False)
180 180
 		order.save()
181 181
 		
182
-		return {'success': True, 'balance': request.user.getProfile().balance}
182
+		return {'success': True, 'balance': request.user.get_profile().balance}
183 183
 
184 184
 
185 185
 class BuyableTypeHandler(BaseHandler):
@@ -290,7 +290,7 @@ class TransactionTransactHandler(BaseHandler):
290 290
 			return getError(rc.BAD_REQUEST, "Your TransactionType could not be found")
291 291
 		trans = Transaction(user=request.user, transactionType=tType, amount=amount, checked=not tType.needsCheck)
292 292
 		trans.save()
293
-		return {'success': True, 'balance': request.user.getProfile().balance}
293
+		return {'success': True, 'balance': request.user.get_profile().balance}
294 294
 
295 295
 class TransactionTypeHandler(BaseHandler):
296 296
 	"""Handler for :class:`Transaction Types <transaction.models.TransactionType>`
@@ -348,7 +348,7 @@ class TransactionVirtualHandler(BaseHandler):
348 348
 			return getError(rc.BAD_REQUEST, "The recipient user does not exist.")
349 349
 		trans = VirtualTransaction(user=request.user, recipient=recipient, amount=amount, comment=comment)
350 350
 		trans.save()
351
-		return {'success': True, 'balance': request.user.getProfile().balance}
351
+		return {'success': True, 'balance': request.user.get_profile().balance}
352 352
 
353 353
 class AccountBalanceHandler(BaseHandler):
354 354
 	"""Handler for the user's account balance"""

+ 15
- 0
k4ever/main/templates/403.html View File

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

+ 17
- 0
k4ever/main/templates/404.html View File

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

+ 31
- 0
k4ever/main/templates/500.html View File

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

+ 3
- 1
k4ever/main/templates/base.html View File

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

+ 0
- 5
k4ever/main/templates/registration/loginForm.html View File

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

+ 9
- 1
k4ever/media/js/k4ever.js View File

@@ -25,6 +25,13 @@ jQuery(document).ready(function($) {
25 25
 		}, options), callback);
26 26
 	};
27 27
 
28
+	var updateBalance = function(newBalance) {
29
+		var balanceString = $("span.balance").text().split(": ");
30
+		balanceString[1] = parseFloat(newBalance).toFixed(2).replace(".", ",") + " €";
31
+
32
+		$("span.balance").text(balanceString.join(": "));
33
+	}
34
+
28 35
 	$.extend($.gritter.options, {
29 36
 		position: "bottom-right",
30 37
 		fade_in_speed: 250,
@@ -61,6 +68,7 @@ jQuery(document).ready(function($) {
61 68
 			});
62 69
 
63 70
 			dataContainer.children().removeClass("locked");
71
+			updateBalance(data.balance);
64 72
 		}, options);
65 73
 	});
66 74
 
@@ -121,7 +129,7 @@ jQuery(document).ready(function($) {
121 129
 
122 130
 						if(status === "success") {
123 131
 							selected_item.addClass("success");
124
-							//TODO neuer kontostand wär schnaffte
132
+							updateBalance(data.balance);
125 133
 						} else {
126 134
 							selected_item.addClass("failure");
127 135
 						}

+ 4
- 0
preislister/main.py View File

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

Loading…
Cancel
Save