from pathlib import Path import sys sys.path.append(str(Path(__file__).parent.parent.parent)) from flask import request from flask_restx import Namespace, Resource, fields, reqparse from database.finance_database import FinanceDatabase from database.database_classes import Transaction from helpers.helper_functions import ( json_success_response, json_error_response, get_string_from_date, get_date_from_string ) namespace = Namespace( 'transaction', description='API endpoints related to Transaction resource' ) transaction_payload = namespace.model("Payload", { "user_id": fields.Integer(required=True, description='id of the user'), "transactions": fields.List(fields.Nested(namespace.model("data", { "amount":fields.Integer(required=True, description='amount of the transaction'), "business_id":fields.Integer(required=True, description='id of business'), "is_expense":fields.Boolean(required=True, description='if its an expense'), "created_date":fields.DateTime(required=True, description='date of transaction', dt_format='iso8601' ) })), required=True, description="list of transactions to insert") }) get_transaction_parser = reqparse.RequestParser() get_transaction_parser.add_argument('user_id', required=True, type=int, help='id of the user') get_transaction_parser.add_argument('page', required=False, type=int, help='page number') get_transaction_parser.add_argument('business_type_id', required=False, type=int, help='id of business type') get_transaction_parser.add_argument('start_date', required=False, type=str, help='start date of target period') get_transaction_parser.add_argument('end_date', required=False, type=str, help='end date of target period') @namespace.route('') class TransactionAPI(Resource): """ API for the Transaction resource. """ @namespace.expect(get_transaction_parser) def get(self): """ Gets a list of transactions. :param user_id: id of the user :param page: page number (default: 1) :param business_type_id: id of the business type :param start_date: start date interval :param end_date: end date interval """ args = get_transaction_parser.parse_args() user_id = args['user_id'] page = args.get('page') business_type_id = args.get('business_type_id') start_date = args.get('start_date') end_date = args.get('end_date') if start_date: start_date = get_date_from_string(start_date) if end_date: end_date = get_date_from_string(end_date) if (start_date is None) ^ (end_date is None): return json_error_response( 'ERROR: One of the dates provided is invalid' ) if (start_date and end_date) and (start_date > end_date): return json_error_response( 'ERROR: End date is earlier than start date.' ) finance_db = FinanceDatabase() transactions = finance_db.get_transactions( user_id=user_id, page=page if page else 1, business_type_id=business_type_id, start_date=start_date, end_date=end_date ) if transactions is None: return json_error_response("ERROR: Failed to get transactions.") return json_success_response([ { 'amount': transaction.amount, 'business_id': transaction.business_id, 'is_expense': 'True' if transaction.is_expense else 'False', 'created_date': get_string_from_date(transaction.created_date), } for transaction in transactions ]) @namespace.expect(transaction_payload) def post(self): """ Inserts multiple transactions into the database. Expected payload: { user_id: int, transactions: [ amount: int, business_id: int, is_expense: bool, created_date: datetime ] } """ payload = request.json finance_db = FinanceDatabase() transactions_to_insert = [] for values in payload['transactions']: transactions_to_insert.append( Transaction( id=0, dashboard_user_id=payload['user_id'], amount=values['amount'], business_id=values['business_id'], is_expense=True, created_date=values['created_date'], ) ) is_insert_successful = finance_db.insert_transactions( transactions_to_insert ) if is_insert_successful is False: return json_error_response( 'ERROR: Failed to insert transactions.' ) return json_success_response()