[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [taler-bank] branch master updated (a7ec665 -> 2cf4730)
From: |
gnunet |
Subject: |
[GNUnet-SVN] [taler-bank] branch master updated (a7ec665 -> 2cf4730) |
Date: |
Wed, 13 Dec 2017 13:29:18 +0100 |
This is an automated email from the git hooks/post-receive script.
marcello pushed a change to branch master
in repository bank.
from a7ec665 tolerating fraction-less amount strings
new 7795cbb add fields to indicate whether a transaction is cancelled,
and if it reimburses another one.
new 2cf4730 Done with /reject logic.
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
talerbank/app/models.py | 5 +++
talerbank/app/tests.py | 112 +++++++++++++++++++++++++++++++++---------------
talerbank/app/views.py | 33 ++++++++++----
3 files changed, 107 insertions(+), 43 deletions(-)
diff --git a/talerbank/app/models.py b/talerbank/app/models.py
index f8c5c47..4abfcda 100644
--- a/talerbank/app/models.py
+++ b/talerbank/app/models.py
@@ -80,3 +80,8 @@ class BankTransaction(models.Model):
subject = models.CharField(default="(no subject given)", max_length=200)
date = models.DateTimeField(auto_now=True, db_index=True)
cancelled = models.BooleanField(default=False)
+ reimburses = models.ForeignKey("BankTransaction",
+ on_delete=models.CASCADE,
+ related_name="reimburser",
+ default=None,
+ null=True)
diff --git a/talerbank/app/tests.py b/talerbank/app/tests.py
index 5f9e67b..2c8729a 100644
--- a/talerbank/app/tests.py
+++ b/talerbank/app/tests.py
@@ -17,11 +17,13 @@
import json
import timeit
import logging
+from django.db import connection
from django.test import TestCase, Client
from django.urls import reverse
from django.conf import settings
from django.contrib.auth.models import User
from mock import patch, MagicMock
+from urllib.parse import unquote
from .models import BankAccount, BankTransaction
from . import urls
from .views import wire_transfer
@@ -31,12 +33,12 @@ LOGGER = logging.getLogger()
LOGGER.setLevel(logging.WARNING)
def clear_db():
- # FIXME: this way we do not reset autoincrement
- # fields.
User.objects.all().delete()
BankAccount.objects.all().delete()
BankTransaction.objects.all().delete()
-
+ with connection.cursor() as cursor:
+ cursor.execute("ALTER SEQUENCE app_bankaccount_account_no_seq RESTART")
+ cursor.execute("ALTER SEQUENCE app_banktransaction_id_seq RESTART")
class WithdrawTestCase(TestCase):
def setUp(self):
BankAccount(
@@ -138,8 +140,8 @@ class RegisterTestCase(TestCase):
def setUp(self):
BankAccount(
- user=User.objects.create_user(username='Bank'),
- account_no=1).save()
+ user=User.objects.create_user(
+ username='Bank')).save()
def tearDown(self):
clear_db()
@@ -162,8 +164,8 @@ class RegisterWrongCurrencyTestCase(TestCase):
# Note, config has KUDOS as currency.
BankAccount(
user=User.objects.create_user(username='Bank'),
- amount=Amount('WRONGCURRENCY'),
- account_no=1).save()
+ amount=Amount('WRONGCURRENCY')).save()
+ # Takes account_no = 1, as the first one.
def tearDown(self):
clear_db()
@@ -342,54 +344,96 @@ class HistoryTestCase(TestCase):
user=User.objects.create_user(
username='User',
password="Password"),
- amount=Amount(settings.TALER_CURRENCY, 100),
- account_no=1)
+ amount=Amount(settings.TALER_CURRENCY, 100))
debit_account.save()
credit_account = BankAccount(
user=User.objects.create_user(
username='User0',
- password="Password0"),
- account_no=2)
+ password="Password0"))
credit_account.save()
- for subject in ("a", "b", "c", "d", "e", "f", "g", "h"):
+ for subject in ("a", "b", "c", "d", "e", "f", "g", "h", "i"):
wire_transfer(Amount(settings.TALER_CURRENCY, 1),
debit_account,
credit_account, subject)
+ # reject transaction 'i'.
+ trans_i = BankTransaction.objects.get(subject="i")
+ self.client = Client()
+ self.client.post(
+ reverse("reject", urlconf=urls),
+ data='{"auth": {"type": "basic"}, \
+ "row_id": %d, \
+ "account_number": 44}' % trans_i.id, # Ignored
+ content_type="application/json",
+ follow=True,
+ **{"HTTP_X_TALER_BANK_USERNAME": "User0",
+ "HTTP_X_TALER_BANK_PASSWORD": "Password0"})
+
def tearDown(self):
clear_db()
def test_history(self):
- client = Client()
- for ctx in (HistoryContext(expected_resp={"status": 200},
- delta="4", direction="both"),
- HistoryContext(expected_resp={
- "field": "row_id", "value": 6,
- "status": 200}, delta="+1", start="5",
direction="both"),
- HistoryContext(expected_resp={
- "field": "wt_subject", "value": "h",
- "status": 200}, delta="-1", direction="both"),
- HistoryContext(expected_resp={"status": 204},
- delta="1", start="11", direction="both"),
- HistoryContext(expected_resp={"status": 204},
- delta="+1", direction="cancel+"),
- HistoryContext(expected_resp={"status": 204},
- delta="+1", direction="credit"),
+ for ctx in (HistoryContext(
+ expected_resp={"status": 200},
+ delta="4", direction="both"),
+ HistoryContext(
+ expected_resp={
+ "fields": [("row_id", 6)],
+ "status": 200},
+ delta="+1", start="5", direction="both"),
+ HistoryContext(
+ expected_resp={
+ "fields": [("wt_subject", "h")],
+ "status": 200},
+ delta="-1", start=9, direction="both"),
+ HistoryContext(
+ expected_resp={"status": 204},
+ delta="1", start="11", direction="both"),
+ HistoryContext(
+ expected_resp={
+ "status": 200,
+ "fields": [("wt_subject", "i"), ("sign",
"cancel-")]},
+ start=8, delta="+1", direction="cancel-"),
+ HistoryContext(
+ expected_resp={"status": 204},
+ start=8, delta="-1", direction="cancel-"),
+ HistoryContext(
+ expected_resp={"status": 204},
+ delta="+1", direction="cancel+"),
+ HistoryContext(
+ expected_resp={
+ "status": 200,
+ "fields":
+ [("wt_subject",
+ "/reject: reimbursement")]},
+ delta="+1", direction="credit"),
HistoryContext(expected_resp={"status": 200},
delta="+1", direction="debit")):
- response = client.get(reverse("history", urlconf=urls),
ctx.urlargs,
- **{"HTTP_X_TALER_BANK_USERNAME": "User",
- "HTTP_X_TALER_BANK_PASSWORD": "Password"})
+ response = self.client.get(
+ reverse("history", urlconf=urls), ctx.urlargs,
+ **{"HTTP_X_TALER_BANK_USERNAME": "User",
+ "HTTP_X_TALER_BANK_PASSWORD": "Password"})
data = response.content.decode("utf-8")
try:
data = json.loads(data)["data"][0]
except (json.JSONDecodeError, KeyError):
data = {}
+ self.assertEqual(
+ ctx.expected_resp.get("status"),
+ response.status_code,
+ "Failing request: %s?%s" % \
+ (response.request["PATH_INFO"],
+ unquote(response.request["QUERY_STRING"])))
+
+ # extract expected data from response
+ expected_data = {}
+ response_data = {}
+ for k, v in ctx.expected_resp.get("fields", []):
+ response_data.update({k: data.get(k)})
+ expected_data.update({k: v})
+
+ self.assertEqual(expected_data, response_data)
- self.assertEqual(data.get(ctx.expected_resp.get("field")),
- ctx.expected_resp.get("value"))
- self.assertEqual(ctx.expected_resp.get("status"),
- response.status_code)
class DBAmountSubtraction(TestCase):
def setUp(self):
diff --git a/talerbank/app/views.py b/talerbank/app/views.py
index 39d35cf..ed89f6d 100644
--- a/talerbank/app/views.py
+++ b/talerbank/app/views.py
@@ -388,12 +388,11 @@ def serve_history(request, user_account):
# delta
parsed_delta = re.search(r"([\+-])?([0-9]+)",
request.GET.get("delta"))
+ sign = parsed_delta.group(1)
# start
start = int(request.GET.get("start", -1))
- sign = parsed_delta.group(1)
-
- # Assuming Q() means 'true'
+ # translating delta's sign into query object
sign_filter = Q()
if start >= 0:
sign_filter = Q(id__gt=start)
@@ -426,6 +425,8 @@ def serve_history(request, user_account):
if entry.credit_account.account_no ==
user_account.bankaccount.account_no:
counterpart = entry.debit_account.account_no
sign_ = "+"
+ cancel = "cancel" if entry.cancelled else ""
+ sign_ = cancel + sign_
history.append(dict(counterpart=counterpart,
amount=entry.amount.dump(),
sign=sign_,
@@ -458,6 +459,7 @@ def auth_and_login(request):
return django.contrib.auth.authenticate(username=username,
password=password)
address@hidden
@csrf_exempt
@require_http_methods(["PUT", "POST"])
@login_via_headers
@@ -472,15 +474,16 @@ def reject(request, user_account):
trans = BankTransaction.objects.get(id=data["row_id"])
except BankTransaction.DoesNotExist:
return JsonResponse({"error": "unknown transaction"}, status=404)
-
if trans.credit_account.account_no != user_account.bankaccount.account_no:
LOGGER.error("you can only reject a transaction where you _got_ money")
return JsonResponse({"error": "you can only reject a transaction where
you _got_ money"},
status=401) # Unauthorized
+ trans.cancelled = True
+ trans.save()
try:
wire_transfer(trans.amount, user_account.bankaccount,
trans.debit_account, "/reject: reimbursement",
- cancelled=True)
+ reimburses=trans)
except WireTransferException as exc:
# Logging the error is taken care of wire_transfer()
return exc.response
@@ -557,13 +560,21 @@ class WireTransferException(Exception):
self.response = response
super().__init__()
-def wire_transfer(amount, debit_account, credit_account, subject, **kwargs):
+def wire_transfer(amount,
+ debit_account,
+ credit_account,
+ subject,
+ **kwargs):
def err_cb(exc, resp):
LOGGER.error(str(exc))
raise WireTransferException(exc, resp)
- def wire_transfer_internal(amount, debit_account, credit_account, subject):
+ def wire_transfer_internal(amount,
+ debit_account,
+ credit_account,
+ subject,
+ reimburses=None):
LOGGER.info("%s => %s, %s, %s" %
(debit_account.account_no,
credit_account.account_no,
@@ -577,7 +588,7 @@ def wire_transfer(amount, debit_account, credit_account,
subject, **kwargs):
credit_account=credit_account,
debit_account=debit_account,
subject=subject,
- cancelled=kwargs.get("cancelled",
False))
+ reimburses=reimburses)
if debit_account.debit:
debit_account.amount.add(amount)
@@ -622,7 +633,11 @@ def wire_transfer(amount, debit_account, credit_account,
subject, **kwargs):
return transaction_item
try:
- return wire_transfer_internal(amount, debit_account, credit_account,
subject)
+ return wire_transfer_internal(amount,
+ debit_account,
+ credit_account,
+ subject,
+ kwargs.get("reimburses", None))
except (CurrencyMismatch, BadFormatAmount) as exc:
err_cb(exc, JsonResponse({"error": "internal server error"},
status=500))
--
To stop receiving notification emails like this one, please contact
address@hidden
- [GNUnet-SVN] [taler-bank] branch master updated (a7ec665 -> 2cf4730),
gnunet <=