From a036333e370ac26c43b3171880d8f96cc088caaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gregor=20D=C3=BCster?= Date: Fri, 20 Oct 2023 14:21:59 +0200 Subject: [PATCH] Enable submission of repayment requests --- pycroft/lib/finance/__init__.py | 3 +++ pycroft/lib/finance/repayment/fields.py | 14 ++++++++++++++ requirements.txt | 1 + web/api/v0/__init__.py | 24 +++++++++++++++++++++++- 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 pycroft/lib/finance/repayment/fields.py diff --git a/pycroft/lib/finance/__init__.py b/pycroft/lib/finance/__init__.py index 7549aec15..1e1dc0112 100644 --- a/pycroft/lib/finance/__init__.py +++ b/pycroft/lib/finance/__init__.py @@ -51,6 +51,9 @@ process_transactions, ImportedTransactions, ) +from .repayment.fields import ( + IBANField, +) def user_has_paid(user: User) -> bool: diff --git a/pycroft/lib/finance/repayment/fields.py b/pycroft/lib/finance/repayment/fields.py new file mode 100644 index 000000000..5b5eb15d9 --- /dev/null +++ b/pycroft/lib/finance/repayment/fields.py @@ -0,0 +1,14 @@ +from marshmallow import fields, ValidationError +from schwifty import IBAN + + +class IBANField(fields.Field): + """Field that serializes to a IBAN and deserializes + to a string. + """ + + def _deserialize(self, value, attr, data, **kwargs) -> IBAN: + try: + return IBAN(value) + except ValueError as error: + raise ValidationError("Pin codes must contain only digits.") from error diff --git a/requirements.txt b/requirements.txt index 63a27162e..0b6b026c1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -40,3 +40,4 @@ sentry-sdk[Flask]~=1.29.2 -e ./deps/wtforms-widgets/ python-dotenv~=0.21.0 pydantic~=2.0.0 +schwifty~=2023.9.0 diff --git a/web/api/v0/__init__.py b/web/api/v0/__init__.py index 70b036c07..d6e0e9679 100644 --- a/web/api/v0/__init__.py +++ b/web/api/v0/__init__.py @@ -7,6 +7,7 @@ from flask import jsonify, current_app, Response from flask.typing import ResponseReturnValue from flask_restful import Api, Resource as FlaskRestfulResource, abort +from schwifty import IBAN from sqlalchemy.exc import IntegrityError from sqlalchemy import select from sqlalchemy.orm import joinedload, selectinload, undefer, with_polymorphic @@ -16,7 +17,7 @@ from pycroft.helpers import utc from pycroft.helpers.i18n import Message -from pycroft.lib.finance import estimate_balance, get_last_import_date +from pycroft.lib.finance import estimate_balance, get_last_import_date, IBANField from pycroft.lib.host import change_mac, host_create, interface_create, host_edit from pycroft.lib.net import SubnetFullException from pycroft.lib.swdd import get_swdd_person_id, get_relevant_tenancies, \ @@ -796,3 +797,24 @@ def patch(self, token: str, password: str) -> ResponseReturnValue: api.add_resource(ResetPasswordResource, '/user/reset-password') + + +class RequestRepaymentResource(Resource): + def get(self, user_id: int): + current_app.logger.warning("RECEIVED GET FOR REQUEST_REPAYMENT.") + return jsonify(False) + + @use_kwargs( + { + "beneficiary": fields.Str(required=True), + "iban": IBANField(required=True), + "amount": fields.Decimal(required=True), + }, + location="form", + ) + def post(self, user_id: int, beneficiary: str, iban: str, amount: Decimal): + current_app.logger.warning({beneficiary, iban, amount}) + return jsonify({"success": True}) + + +api.add_resource(RequestRepaymentResource, "/user//request-repayment")