Implement getting bank account details

This commit is contained in:
Mark Veidemanis 2023-03-08 17:04:47 +00:00
parent 144e048d5f
commit c0dc41a63a
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
5 changed files with 145 additions and 6 deletions

View File

@ -87,4 +87,10 @@ urlpatterns = [
aggregators.ReqDelete.as_view(),
name="req_delete",
),
# Requisition info
path(
"aggs/<str:type>/info/<str:pk>/<str:req_id>/",
aggregators.ReqInfo.as_view(),
name="req_info",
),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

View File

@ -104,3 +104,78 @@ class NordigenClient(BaseClient):
path, schema="RequisitionDelete", http_method="delete"
)
return response
async def get_requisition(self, requisition):
"""
Get a list of accounts for a requisition.
:param requisition: requisition ID"""
path = f"requisitions/{requisition}"
response = await self.call(path, schema="Requisition")
return response
# def get_ownernames(self):
# """
# Get list of supplementary owner names.
# """
# ownernames = loads(settings.Nordigen.OwnerNames)
# return ownernames
async def get_account(self, account_id):
"""
Get details of an account.
:param requisition: requisition ID"""
path = f"accounts/{account_id}/details"
response = await self.call(path, schema="AccountDetails")
if "account" not in response:
return False
parsed = response["account"]
if "bban" in parsed and parsed["currency"] == "GBP":
sort_code = parsed["bban"][0:6]
account_number = parsed["bban"][6:]
# if "ownerName" not in parsed:
# ownernames = self.get_ownernames()
# if account_id in ownernames:
# parsed["ownerName"] = ownernames[account_id]
# else:
# return False
# recipient = parsed["ownerName"]
del parsed["bban"]
if "iban" in parsed:
del parsed["iban"]
sort_code = "-".join(list(map("".join, zip(*[iter(sort_code)] * 2))))
parsed["sort_code"] = sort_code
parsed["number"] = account_number
parsed["recipient"] = "TODO"
# Let's add the account ID so we can reference it later
parsed["account_id"] = account_id
print("PARSED", parsed)
return parsed
async def get_all_account_info(self, requisition=None):
print("GET ALL ACCOU T INFO", requisition)
to_return = {}
if not requisition:
raise NotImplementedError
# requisitions = await self.get_requisitions()
else:
requisitions = [await self.get_requisition(requisition)]
print("REQUISITIONS", requisitions)
print("REQUISITIONS", requisitions)
for req in requisitions:
print("REQ ITER", req)
accounts = req["accounts"]
print("ACCOUNTS", accounts)
for account_id in accounts:
account_info = await self.get_account(account_id)
if not account_info:
continue
if req["institution_id"] in to_return:
to_return[req["institution_id"]].append(account_info)
else:
to_return[req["institution_id"]] = [account_info]
return to_return

View File

@ -43,7 +43,7 @@
</span>
</button>
{% if type == 'page' %}
<a href="{# url 'aggregator_read' type=type pk=item.id #}"><button
<a href="{% url 'req_info' type=type pk=pk req_id=item.id %}"><button
class="button">
<span class="icon-text">
<span class="icon">
@ -55,7 +55,7 @@
{% else %}
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-get="{# url 'aggregator_info' type=type pk=item.id #}"
hx-get="{% url 'req_info' type=type pk=pk req_id=item.id %}"
hx-trigger="click"
hx-target="#{{ type }}s-here"
hx-swap="innerHTML"

View File

@ -0,0 +1,28 @@
{% include 'mixins/partials/notify.html' %}
<h1 class="title">{{ title_singular }} info</h1>
{% for key, item in object.items %}
<h1 class="title is-4">Bank: {{ key }}</h1>
{% for account in item %}
<table class="table is-fullwidth is-hoverable box">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% for key_i, item_i in account.items %}
<tr>
<th>{{ key_i }}</th>
<td>
{% if item_i is not None %}
{{ item_i }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
<hr/>
{% endfor %}

View File

@ -3,7 +3,13 @@ import asyncio
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django.views import View
from mixins.views import ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate
from mixins.views import (
ObjectCreate,
ObjectDelete,
ObjectList,
ObjectRead,
ObjectUpdate,
)
from two_factor.views.mixins import OTPRequiredMixin
from core.clients.aggregators.nordigen import NordigenClient
@ -175,12 +181,9 @@ class AggregatorLinkBank(LoginRequiredMixin, OTPRequiredMixin, View):
run = synchronize_async_helper(NordigenClient(aggregator))
auth_url = synchronize_async_helper(run.build_link(bank))
# Redirect to auth url
print("AUTH URL", auth_url)
# Create a blank response
response = HttpResponse()
response["HX-Redirect"] = auth_url
# return redirect(auth_url)
return response
@ -207,6 +210,33 @@ class ReqDelete(LoginRequiredMixin, OTPRequiredMixin, View):
return response
class ReqInfo(LoginRequiredMixin, OTPRequiredMixin, ObjectRead):
context_object_name_singular = "requisition"
context_object_name = "requisitions"
detail_template = "partials/aggregator-req-info.html"
def get_object(self, **kwargs):
pk = kwargs.get("pk")
req_id = kwargs.get("req_id")
try:
aggregator = Aggregator.get_by_id(pk, self.request.user)
except Aggregator.DoesNotExist:
message = "Aggregator does not exist"
message_class = "danger"
context = {
"message": message,
"message_class": message_class,
"window_content": self.window_content,
}
return self.render_to_response(context)
run = synchronize_async_helper(NordigenClient(aggregator))
req = synchronize_async_helper(run.get_all_account_info(req_id))
print("REQ KEYS", req.keys())
self.extra_context = {"pretty": list(req.keys())}
return req
class AggregatorList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
list_template = "partials/aggregator-list.html"
model = Aggregator