Implement getting bank account details
This commit is contained in:
parent
144e048d5f
commit
c0dc41a63a
|
@ -87,4 +87,10 @@ urlpatterns = [
|
||||||
aggregators.ReqDelete.as_view(),
|
aggregators.ReqDelete.as_view(),
|
||||||
name="req_delete",
|
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)
|
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
|
|
@ -104,3 +104,78 @@ class NordigenClient(BaseClient):
|
||||||
path, schema="RequisitionDelete", http_method="delete"
|
path, schema="RequisitionDelete", http_method="delete"
|
||||||
)
|
)
|
||||||
return response
|
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
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
{% if type == 'page' %}
|
{% 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">
|
class="button">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<button
|
<button
|
||||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
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-trigger="click"
|
||||||
hx-target="#{{ type }}s-here"
|
hx-target="#{{ type }}s-here"
|
||||||
hx-swap="innerHTML"
|
hx-swap="innerHTML"
|
||||||
|
|
|
@ -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 %}
|
|
@ -3,7 +3,13 @@ import asyncio
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.views import View
|
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 two_factor.views.mixins import OTPRequiredMixin
|
||||||
|
|
||||||
from core.clients.aggregators.nordigen import NordigenClient
|
from core.clients.aggregators.nordigen import NordigenClient
|
||||||
|
@ -175,12 +181,9 @@ class AggregatorLinkBank(LoginRequiredMixin, OTPRequiredMixin, View):
|
||||||
run = synchronize_async_helper(NordigenClient(aggregator))
|
run = synchronize_async_helper(NordigenClient(aggregator))
|
||||||
auth_url = synchronize_async_helper(run.build_link(bank))
|
auth_url = synchronize_async_helper(run.build_link(bank))
|
||||||
|
|
||||||
# Redirect to auth url
|
|
||||||
print("AUTH URL", auth_url)
|
|
||||||
# Create a blank response
|
# Create a blank response
|
||||||
response = HttpResponse()
|
response = HttpResponse()
|
||||||
response["HX-Redirect"] = auth_url
|
response["HX-Redirect"] = auth_url
|
||||||
# return redirect(auth_url)
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@ -207,6 +210,33 @@ class ReqDelete(LoginRequiredMixin, OTPRequiredMixin, View):
|
||||||
return response
|
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):
|
class AggregatorList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
|
||||||
list_template = "partials/aggregator-list.html"
|
list_template = "partials/aggregator-list.html"
|
||||||
model = Aggregator
|
model = Aggregator
|
||||||
|
|
Loading…
Reference in New Issue