gnunet-svn
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]