Skip to content

Commit

Permalink
Fix landing page styling
Browse files Browse the repository at this point in the history
  • Loading branch information
open-risk committed Sep 13, 2024
1 parent b045832 commit e577a73
Show file tree
Hide file tree
Showing 7 changed files with 388 additions and 110 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ ChangeLog
===========================
PLEASE NOTE THIS IS ONLY A BETA RELEASE. THE OPENNPL API IS STILL UNSTABLE

v0.6.3 (17-05-2025)
v0.6.4 (20-06-2024)
-------------------
* Bugs: REST API for both NPL and SFLP templates

v0.6.3 (17-05-2024)
-------------------
* Functionality: Update to 2023 SFLP Template

Expand Down
5 changes: 5 additions & 0 deletions npl_portfolio/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
ChangeLog
===========================

v0.6.1
------------------
* Redesign REST API


v0.6.0 (Starting App ChangeLog)
------------------
* First commit of changelog / readme
36 changes: 18 additions & 18 deletions npl_portfolio/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,30 @@

from django.urls import re_path

from openNPL import npl_views as views
from . import views as api_views

app_name = 'npl_portfolio'

urlpatterns = [
# re_path(r'^$', views.npl_api_root, name='npl_api_root'),
re_path(r'^counterparty_groups$', views.npl_counterparty_group_api, name='npl_counterparty_group_api'),
re_path(r'^counterparty_groups/(?P<pk>[0-9]+)/$', views.npl_counterparty_group_detail,
re_path(r'^', api_views.npl_api_root, name='npl_api_root'),
re_path(r'^counterparty_groups$', api_views.npl_counterparty_group_api, name='npl_counterparty_group_api'),
re_path(r'^counterparty_groups/(?P<pk>[0-9]+)/$', api_views.npl_counterparty_group_detail,
name='npl_counterparty_group_detail'),
re_path(r'^counterparties$', views.npl_counterparty_api, name='npl_counterparty_api'),
re_path(r'^counterparties/(?P<pk>[0-9]+)/$', views.npl_counterparty_detail, name='npl_counterparty_detail'),
re_path(r'^property_collateral$', views.npl_property_collateral_api, name='npl_property_collateral_api'),
re_path(r'^property_collateral/(?P<pk>[0-9]+)/$', views.npl_property_collateral_detail,
re_path(r'^counterparties$', api_views.npl_counterparty_api, name='npl_counterparty_api'),
re_path(r'^counterparties/(?P<pk>[0-9]+)/$', api_views.npl_counterparty_detail, name='npl_counterparty_detail'),
re_path(r'^property_collateral$', api_views.npl_property_collateral_api, name='npl_property_collateral_api'),
re_path(r'^property_collateral/(?P<pk>[0-9]+)/$', api_views.npl_property_collateral_detail,
name='npl_property_collateral_detail'),
re_path(r'^loans$', views.npl_loan_api, name='npl_loan_api'),
re_path(r'^loans/(?P<pk>[0-9]+)/$', views.npl_loan_detail, name='npl_loan_detail'),
re_path(r'^enforcement$', views.npl_enforcement_api, name='npl_enforcement_api'),
re_path(r'^enforcement/(?P<pk>[0-9]+)/$', views.npl_enforcement_detail, name='npl_enforcement_detail'),
re_path(r'^forbearance$', views.npl_forbearance_api, name='npl_forbearance_api'),
re_path(r'^forbearance/(?P<pk>[0-9]+)/$', views.npl_forbearance_detail, name='npl_forbearance_detail'),
re_path(r'^nonproperty_collateral$', views.npl_nonproperty_collateral_api, name='npl_nonproperty_collateral_api'),
re_path(r'^nonproperty_collateral/(?P<pk>[0-9]+)/$', views.npl_nonproperty_collateral_detail,
re_path(r'^loans$', api_views.npl_loan_api, name='npl_loan_api'),
re_path(r'^loans/(?P<pk>[0-9]+)/$', api_views.npl_loan_detail, name='npl_loan_detail'),
re_path(r'^enforcement$', api_views.npl_enforcement_api, name='npl_enforcement_api'),
re_path(r'^enforcement/(?P<pk>[0-9]+)/$', api_views.npl_enforcement_detail, name='npl_enforcement_detail'),
re_path(r'^forbearance$', api_views.npl_forbearance_api, name='npl_forbearance_api'),
re_path(r'^forbearance/(?P<pk>[0-9]+)/$', api_views.npl_forbearance_detail, name='npl_forbearance_detail'),
re_path(r'^nonproperty_collateral$', api_views.npl_nonproperty_collateral_api, name='npl_nonproperty_collateral_api'),
re_path(r'^nonproperty_collateral/(?P<pk>[0-9]+)/$', api_views.npl_nonproperty_collateral_detail,
name='npl_nonproperty_collateral_detail'),
re_path(r'^external_collection$', views.npl_external_collection_api, name='npl_external_collection_api'),
re_path(r'^external_collection/(?P<pk>[0-9]+)/$', views.npl_external_collection_detail,
re_path(r'^external_collection$', api_views.npl_external_collection_api, name='npl_external_collection_api'),
re_path(r'^external_collection/(?P<pk>[0-9]+)/$', api_views.npl_external_collection_detail,
name='npl_external_collection_detail'),
]
4 changes: 4 additions & 0 deletions sflp_portfolio/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
ChangeLog
===========================

v0.6.4
------------------
* Redesign REST API

v0.6.3
------------------
* Added two new attributes as per 2023 SFLP template update
Expand Down
3 changes: 2 additions & 1 deletion sflp_portfolio/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@

from django.urls import re_path

from openNPL import sflp_views as api_views
from . import views as api_views

app_name = 'sflp_portfolio'

urlpatterns = [
re_path(r'^', api_views.sflp_api_root, name='sflp_api_root'),
re_path(r'^counterparties$',
api_views.sflp_counterparty_api,
name='sflp_counterparty_api'),
Expand Down
247 changes: 247 additions & 0 deletions sflp_portfolio/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
# Copyright (c) 2020 - 2024 Open Risk (https://www.openriskmanagement.com)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.


from rest_framework import permissions
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from rest_framework.reverse import reverse

from openNPL.sflp_serializers import SFLP_CounterpartySerializer, SFLP_CounterpartyDetailSerializer
from openNPL.sflp_serializers import SFLP_EnforcementSerializer, SFLP_EnforcementDetailSerializer
from openNPL.sflp_serializers import SFLP_ForbearanceSerializer, SFLP_ForbearanceDetailSerializer
from openNPL.sflp_serializers import SFLP_LoanSerializer, SFLP_LoanDetailSerializer
from openNPL.sflp_serializers import SFLP_PropertyCollateralSerializer, SFLP_PropertyCollateralDetailSerializer
from sflp_portfolio.models.counterparty import Counterparty
from sflp_portfolio.models.loan import Loan
from sflp_portfolio.models.enforcement import Enforcement
from sflp_portfolio.models.forbearance import Forbearance
from sflp_portfolio.models.property_collateral import PropertyCollateral




#
# API ENDPOINTS
#

@api_view(['GET'])
def sflp_api_root(request, format=None):
"""
Returns a list of all active API endpoints for SFLP Template Data
"""

data = [
{'SFLP Template Endpoints':
[
{'sflp_counterparty': reverse('sflp_portfolio:sflp_counterparty_api', request=request, format=format)},
{'sflp_loan': reverse('sflp_portfolio:sflp_loan_api', request=request, format=format)},
{'sflp_enforcement': reverse('sflp_portfolio:sflp_enforcement_api', request=request, format=format)},
{'sflp_forbearance': reverse('sflp_portfolio:sflp_forbearance_api', request=request, format=format)},
{'sflp_property_collateral': reverse('sflp_portfolio:sflp_property_collateral_api', request=request, format=format)},
# {'sflp_repayment_schedule': reverse('sflp_portfolio:sflp_repayment_schedule_api', request=request, format=format)},
]}
]
return Response(data)


@api_view(['GET', 'POST'])
@permission_classes((permissions.AllowAny,))
def sflp_counterparty_api(request):
"""
List Counterparties (EBA Template)
"""
if request.method == 'GET':
counterparty = Counterparty.objects.all()
serializer = SFLP_CounterpartySerializer(counterparty, many=True, context={'request': request})
return Response(serializer.data)
elif request.method == 'POST':
"""
Create a new Counterparty
"""
data = JSONParser().parse(request)
serializer = SFLP_CounterpartyDetailSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET'])
def sflp_counterparty_detail(request, pk):
if request.method == 'GET':
"""
List the data a specific Counterparty
"""
try:
counterparty = Counterparty.objects.get(pk=pk)
except Counterparty.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

serializer = SFLP_CounterpartyDetailSerializer(counterparty)
return Response(serializer.data)


@api_view(['GET', 'POST'])
@permission_classes((permissions.AllowAny,))
def sflp_loan_api(request):
"""
List Loans (EBA Template)
"""
if request.method == 'GET':
loan = Loan.objects.all()
serializer = SFLP_LoanSerializer(loan, many=True, context={'request': request})
return Response(serializer.data)
elif request.method == 'POST':
"""
Create a new Loan
"""
data = JSONParser().parse(request)
serializer = SFLP_LoanDetailSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET'])
def sflp_loan_detail(request, pk):
"""
List the data a specific EBA Loan
"""
try:
loan = Loan.objects.get(pk=pk)
except Loan.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

serializer = SFLP_LoanDetailSerializer(loan)
return Response(serializer.data)


@api_view(['GET', 'POST'])
@permission_classes((permissions.AllowAny,))
def sflp_property_collateral_api(request):
"""
List Property Collateral (EBA Template)
"""
if request.method == 'GET':
property_collateral = PropertyCollateral.objects.all()
serializer = SFLP_PropertyCollateralSerializer(property_collateral, many=True,
context={'request': request})
return Response(serializer.data)
elif request.method == 'POST':
"""
Create new property collateral
"""
data = JSONParser().parse(request)
serializer = SFLP_PropertyCollateralDetailSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET'])
def sflp_property_collateral_detail(request, pk):
"""
List the data a specific EBA Property Collateral
"""
try:
property_collateral = PropertyCollateral.objects.get(pk=pk)
except PropertyCollateral.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

serializer = SFLP_PropertyCollateralDetailSerializer(property_collateral)
return Response(serializer.data)


@api_view(['GET', 'POST'])
@permission_classes((permissions.AllowAny,))
def sflp_enforcement_api(request):
"""
List Enforcements (EBA Template)
"""
if request.method == 'GET':
enforcement = Enforcement.objects.all()
serializer = SFLP_EnforcementSerializer(enforcement, many=True, context={'request': request})
return Response(serializer.data)
elif request.method == 'POST':
"""
Create new Enforcement entry
"""
data = JSONParser().parse(request)
serializer = SFLP_EnforcementDetailSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET'])
def sflp_enforcement_detail(request, pk):
"""
List the data a specific EBA Enforcement entry
"""
try:
enforcement = Enforcement.objects.get(pk=pk)
except Enforcement.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

serializer = SFLP_EnforcementDetailSerializer(enforcement)
return Response(serializer.data)


@api_view(['GET', 'POST'])
@permission_classes((permissions.AllowAny,))
def sflp_forbearance_api(request):
"""
List Forbearance (EBA Template)
"""
if request.method == 'GET':
forbearance = Forbearance.objects.all()
serializer = SFLP_ForbearanceSerializer(forbearance, many=True, context={'request': request})
return Response(serializer.data)
elif request.method == 'POST':
"""
Create new Forbearance entry
"""
data = JSONParser().parse(request)
serializer = SFLP_ForbearanceDetailSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET'])
def sflp_forbearance_detail(request, pk):
"""
List the data a specific EBA Forbearance entry
"""
try:
forbearance = Forbearance.objects.get(pk=pk)
except Forbearance.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)

serializer = SFLP_ForbearanceDetailSerializer(forbearance)
return Response(serializer.data)
Loading

0 comments on commit e577a73

Please sign in to comment.