From f9e5f0d7e41ff1acf5279cd58e54e8b3bd890158 Mon Sep 17 00:00:00 2001 From: Lucas Mathews Date: Thu, 23 May 2024 18:21:13 +0200 Subject: [PATCH] minor updates --- api.yml | 294 ++++++++++++++++++++++++++++++----------------- bank.db | Bin 28672 -> 28672 bytes bank.ini | 2 +- manager.py | 100 ++++++++++------ test_database.db | Bin 741376 -> 741376 bytes 5 files changed, 256 insertions(+), 140 deletions(-) diff --git a/api.yml b/api.yml index 82aa54b..957d966 100644 --- a/api.yml +++ b/api.yml @@ -105,63 +105,7 @@ paths: description: Old password incorrect '404': description: client_id not found - /Client: - post: - tags: - - client - summary: Add a new client - description: Add a new client to the system - operationId: manager.add_client - parameters: - - name: name - in: query - description: Client Name - required: true - schema: - type: string - - name: birthdate - in: query - description: Client Birthdate (dd-mm-yyyy) - required: true - schema: - type: string - - name: address - in: query - description: Client Address - required: false - schema: - type: string - - name: phone_number - in: query - description: Client Phone Number - required: true - schema: - type: string - - name: email - in: query - description: Client Email Address - required: true - schema: - type: string - - name: password - in: query - description: Client Password - required: true - schema: - type: string - - name: notes - in: query - description: Notes about client - required: false - schema: - type: string - responses: - '200': - description: "Client created" - '400': - description: Invalid input - '422': - description: Validation exception + /Client/Client: put: tags: - client @@ -240,27 +184,6 @@ paths: description: Invalid Client ID supplied '404': description: Client not found - delete: - tags: - - client - summary: Delete a client by ID - description: Delete a client by ID - operationId: manager.delete_client - parameters: - - name: client_id - in: query - description: ID of client to delete - required: true - schema: - type: string - format: int32 - responses: - '200': - description: Successful operation - '400': - description: Invalid Client ID supplied - '404': - description: Client not found /Account: post: tags: @@ -361,27 +284,6 @@ paths: description: Invalid Account ID supplied '404': description: Account not found - delete: - tags: - - account - summary: Delete an account by ID - description: Delete an account by ID - operationId: manager.delete_account - parameters: - - name: account_id - in: query - description: ID of account to delete - required: true - schema: - type: string - format: int32 - responses: - '200': - description: Successful operation - '400': - description: Invalid account_id supplied - '404': - description: Account not found /Transaction: get: tags: @@ -473,7 +375,7 @@ paths: description: Invalid input '404': description: No transactions found - /Manager/Interest: + /Admin/Interest: post: tags: - admin @@ -522,7 +424,7 @@ paths: description: Invalid input '422': description: Validation exception - /Manager/Clients: + /Admin/Clients: get: tags: - admin @@ -540,7 +442,7 @@ paths: description: Invalid input '404': description: No clients found - /Manager/Accounts: + /Admin/Accounts: get: tags: - admin @@ -558,7 +460,7 @@ paths: description: Invalid input '404': description: No accounts found - /Manager/Transactions: + /Admin/Transactions: get: tags: - admin @@ -576,7 +478,7 @@ paths: description: Invalid input '404': description: No transactions found - /Manager/Hash: + /System/Hash: get: tags: - system @@ -600,8 +502,8 @@ paths: '400': description: Invalid input '401': - description: Unauthorized - /Manager/Timestamp: + description: Unauthorised + /System/Timestamp: get: tags: - system @@ -618,7 +520,185 @@ paths: '400': description: Invalid input '401': - description: Unauthorized + description: Unauthorised + /Admin/Balance: + get: + tags: + - admin + summary: Test the balance of all accounts + description: Tests the balance of all accounts and alerts of any discrepancies + operationId: manager.test_account_balances + responses: + '200': + description: Successful operation + content: + application/json: + schema: + type: string + '401': + description: Unauthorised + /System/Initialise: + get: + tags: + - system + summary: Initialise the system + description: Initialises the system with test data + operationId: manager.initialise_database + parameters: + - name: password + in: query + description: Password to initialise the system + required: true + schema: + type: string + responses: + '200': + description: Successful operation + '400': + description: Database not empty, this function cannot be used + /Admin/Promote: + put: + tags: + - admin + summary: Promote a client to administrator + description: Promote a client to administrator + operationId: manager.promote_to_admin + parameters: + - name: client_id + in: query + description: ID of client to promote + required: true + schema: + type: string + responses: + '200': + description: Successful operation + '401': + description: Unauthorised + '404': + description: Client not found + /Admin/Demote: + put: + tags: + - admin + summary: Demote a client from administrator + description: Demote a client from administrator + operationId: manager.demote_from_admin + parameters: + - name: client_id + in: query + description: ID of client to demote + required: true + schema: + type: string + responses: + '200': + description: Successful operation + '401': + description: Unauthorised + '404': + description: Client not found + /Admin/Client: + post: + tags: + - admin + summary: Add a new client + description: Add a new client to the system + operationId: manager.add_client + parameters: + - name: name + in: query + description: Client Name + required: true + schema: + type: string + - name: birthdate + in: query + description: Client Birthdate (dd-mm-yyyy) + required: true + schema: + type: string + - name: address + in: query + description: Client Address + required: false + schema: + type: string + - name: phone_number + in: query + description: Client Phone Number + required: true + schema: + type: string + - name: email + in: query + description: Client Email Address + required: true + schema: + type: string + - name: password + in: query + description: Client Password + required: true + schema: + type: string + - name: notes + in: query + description: Notes about client + required: false + schema: + type: string + responses: + '200': + description: "Client created" + '400': + description: Invalid input + '422': + description: Validation exception + /Delete/Client: + delete: + tags: + - admin + summary: Delete a client by ID + description: Delete a client by ID + operationId: manager.delete_client + parameters: + - name: client_id + in: query + description: ID of client to delete + required: true + schema: + type: string + format: int32 + responses: + '200': + description: Successful operation + '400': + description: Invalid Client ID supplied + '404': + description: Client not found + /Delete/Account: + delete: + tags: + - admin + summary: Delete an account by ID + description: Delete an account by ID + operationId: manager.delete_account + parameters: + - name: account_id + in: query + description: ID of account to delete + required: true + schema: + type: string + format: int32 + responses: + '200': + description: Successful operation + '400': + description: Invalid account_id supplied + '404': + description: Account not found components: schemas: Client: diff --git a/bank.db b/bank.db index 1456f1cae6d350a1d01e58db4f5e3ba1e5b2cd48..60ab951ce9cae164bc62a7e1ba0adaf46ca4e8f0 100644 GIT binary patch delta 374 zcmaKnKS~2Z6vk(f6*jW0ku;)#SZx(~@6F84Y^nrpQm7Dff%ywwz&6p&E;)dQkUfE= zx5y!K05>Vb6#7-~$Bzf!x7;MlO|rU3()Hy{nzHNXw-5hbWQ?(-=&_>LbO)Vc@$!`9 z{j%g`S-$2h%QT<^)NXQnH@%-e&S#VP!|VVENDM&^i4RbXK#o8h_`gAEE}^2}con>) zItE&ha}~EH^59T=E|fRU61uuA;*GWjw9u|~A^M0xqC(}pv`7M?lCm<+@LDKiKoJQ^ zT520A0CMO>Wig`Th!#Tab!R_*%ZhD#?9-f&Ka2J1>g?pG|Fb>csne!A{%RE-@4kNF GzxEqwWnCNq literal 28672 zcmeI)-*4MQ8~|`T?%F16W)PYp)I~B6(^iQv`|kX!5)xUJj%i&xvJSDAg*)HfYN>Hb z>;il27*9N*@i*|lAfAx+fc6jU8EFzca+k%O)3pO3rft$UY2>@J&v*CvI+lEPbMv!} zv=ELQjfb>wumQo-U&j3DE#u6O z_AgE6%$KLPmY$qc0m?xD1V8`;KmY_l00cnbEfV!-Q4b7>GdaDr$dn!bhuaDjEg)Or+d0@)nb|?x_YHyy@#<#(!Eru^5fUv z=wH3w?ca8;^=>;CXZydR>#uM1dsnY)>h%|&?_tI1_tty;-sW2GrZX+ho$3Zh>mJvS zf8I-DC7hpcT{~|YX~xC3`B%H@nrA@wi_s)MsB}0Vc-7p({g17MR=aIJxIPJJ*~xM_ zHxtORR0naIt~kyFFxj1GJ`b-R=?Nhj?TKtq92di~k)wwIqq{UqMD-XDnLZ%7b9rlP zqu1Tk&1IuP{Z!WZ! zm(2&=3HWrU(?xBD`>?@A{jkY$I5XH89nO41SUN6tI91oZ)9;qn(8_6c_XKFp$0DD> z+S?grVvy|*nHX31BZf5HtrqOie5aa!f&G}!P(DnvRG%}7(YPA3nGhY0dZn?_sm-^# z%O^oksRrIOp|9l^^?9{vUovXVhsGJ%e7N*z>Cszsu7$3G00@8p2!H?xfB*=900@A9 zaj-tuY_~qZXIt;zZyNQ*h*anw)mvU`Yh+^FNlafDo*_B&qaAa|9xt6q!|K?oD1 zmRK!`#8KkL5%yh%1ag^(^_vEvp9m@a05Ks05`+iD1p6|KU5O$VMM;ndp9msc%0n58&|{dPgPYdD4XfF{pt`?2>3*FAUMNE%Hue*m zJJ)HkBfiOBG7M4}=9027LP(WLhB%J}js^2+L}Da^$n_E=ypU0ncmazfOStF9iHid%P{^n|4|<)lkZ zjbh0SIkK!~y{R&meaEnWweQ$Jz2W17?tuUZfB*=900@8p2!H?xfB*=9z$+Kf zJ$$xSHT(~yg&d1KmY_l00ck) z1V8`;KmY_l00dsEz!&D?t+t7cc3b_dLZW`u!R<(2CLI#`aVJ*4Q_&H^Ls5c5pSyDM z1C~;Zts_qu;8h=&lK|z+fWH54+P@p>4_+Vu0w4eaAOHd&00JNY0w4eaAOHeynZO0> KR{h`175oj=PrPpc diff --git a/bank.ini b/bank.ini index ebe7c20..adecc92 100644 --- a/bank.ini +++ b/bank.ini @@ -1,5 +1,5 @@ [database] -name=test_database.db +name=bank.db [api_file] name=api.yml diff --git a/manager.py b/manager.py index 75a90a0..443d4db 100644 --- a/manager.py +++ b/manager.py @@ -91,15 +91,6 @@ def get_client(client_id:str): # Returns a specific client in the database return jsonify({"name": client.name, "birthdate": client.birthdate, "opening_timestamp": client.opening_timestamp, "address": client.address, "phone_number": client.phone_number, "email": client.email}), 200 return jsonify({"error": "Client not found"}), 404 -@login_required -def add_client(name:str, birthdate:str, address:str, phone_number:str, email:str, password:str, **kwargs): # Adds a new client to the database - client_id = generate_uuid_short() - notes = kwargs.get("notes", None) - new_client = Client(client_id, name, birthdate, timestamp(), address, phone_number, email, hash_password(password), notes, 1, 0, None) - session.add(new_client) - session.commit() - return f"New client has been added: name: {name}, uuid: {client_id} ", 200 - @login_required def update_client(client_id:str, **kwargs): # Updates a client in the database current_client_id, is_admin = get_current_client() @@ -331,33 +322,78 @@ def apply_fee(account_id:int, fee:float): @admin_required def delete_transaction(transaction_id:int): DELETE_TRANSACTION = "DELETE FROM transaction WHERE transaction_id=?" - from api import session, Transaction - for transaction in session.query(Transaction).all(): - if transaction.transaction_id == transaction_id: - input(f"Are you sure you would like permanenty delete transaction ID: {transaction_id}? WARNING: This action can not be reversed. (Y/N) ") - if input == "Y"or input == "y": - session.execute(DELETE_TRANSACTION, (transaction_id)) - print(f"Transaction ID: {transaction_id} has been removed.") - else: - return f"Transaction ID: {transaction_id} has NOT been removed." - return - return f"Transaction ID: {transaction_id} is not found." + return @admin_required def test_account_balances(): - # Get all accounts - all_accounts = get_all_accounts() + # Get all transactions from the database + all_transactions = session.query(Transaction).all() + + # Initialize a dictionary to store the calculated balance for each account + calculated_balances = {} + + # Go through each transaction + for transaction in all_transactions: + # If the account ID of the transaction is not in the dictionary, add it with a balance of 0 + if transaction.account_id not in calculated_balances: + calculated_balances[transaction.account_id] = 0 + + # Update the calculated balance for the account + if transaction.transaction_type == 'Deposit': + calculated_balances[transaction.account_id] += transaction.amount + elif transaction.transaction_type == 'Withdrawal': + calculated_balances[transaction.account_id] -= transaction.amount + + # Get all accounts from the database + all_accounts = session.query(Account).all() + + # Initialize a list to store the discrepancies + discrepancies = [] # Go through each account for account in all_accounts: - # Calculate the balance based on the transactions - calculated_balance = 0 - for transaction in account.get_transactions(): - if transaction.transaction_type == 'Deposit': - calculated_balance += transaction.amount - elif transaction.transaction_type == 'Withdrawal': - calculated_balance -= transaction.amount + # If the calculated balance doesn't match the stored balance, add the discrepancy to the list + if calculated_balances.get(account.account_id, 0) != account.balance: + discrepancies.append({"error": f"Alert: Account {account.account_id} has a balance discrepancy. Stored balance is {account.balance}, but calculated balance is {calculated_balances.get(account.account_id, 0)}."}) - # Check if the calculated balance matches the stored balance - if calculated_balance != account.balance: - print(f"Alert: Account {account.account_id} has a balance discrepancy. Stored balance is {account.balance}, but calculated balance is {calculated_balance}.") + # Return the list of discrepancies + return jsonify(discrepancies), 200 + + +@admin_required +def add_client(name:str, birthdate:str, address:str, phone_number:str, email:str, password:str, **kwargs): # Adds a new client to the database + client_id = generate_uuid_short() + notes = kwargs.get("notes", None) + new_client = Client(client_id, name, birthdate, timestamp(), address, phone_number, email, hash_password(password), notes, 1, 0, None) + session.add(new_client) + session.commit() + return client_id, 200 + +def initialise_database(password:str): + existing_clients = session.query(Client).all() # Check if any clients exist in the database + if not existing_clients: # If no clients exist, create an administrator client + add_client('ADMINISTRATOR', 'ADMINISTRATOR', 'ADMINISTRATOR', 'ADMINISTRATOR', 'ADMINISTRATOR', password) # Add the administrator client + session.commit() + admin_client = session.query(Client).filter_by(name='ADMINISTRATOR').one() # Retrieve the administrator client + admin_client.administrator = 1 # Set the new client as an administrator + session.commit() + return jsonify(f"Database initialised with administrator account with client_id {admin_client.client_id}"), 200 + return jsonify("Database not empty, this function cannot be used."), 400 + +@admin_required +def promote_to_admin(client_id:str): + for client in session.query(Client).all(): + if client.client_id == client_id: + client.administrator = 1 + session.commit() + return f"client_id: {client_id} has been promoted to administrator.", 200 + return f"client_id: {client_id} is not found.", 404 + +@admin_required +def demote_from_admin(client_id:str): + for client in session.query(Client).all(): + if client.client_id == client_id: + client.administrator = 0 + session.commit() + return f"client_id: {client_id} has been demoted from administrator.", 200 + return f"client_id: {client_id} is not found.", 404 \ No newline at end of file diff --git a/test_database.db b/test_database.db index db817c9c4e3c9840e3db36232179b4e9eade933b..fa575054fd1c9a86c01a93edc9d9c9c8970880c5 100644 GIT binary patch delta 179 zcmZozpxdxOcY-t{=R_H2R!#=JvhIy3i`O$UZsyqVkB_UIkxN##DP2*Tak7B@1$lAD z(vpn)B89a4(jtX|qWqN7EM%~G$-WoLje7pVUTSgBNM&0dBOib??8Fku?SeSsA8Hibcm=%cGfS4VK RIe?fGh`F{Kv2dUB1_0aGJ5K-r delta 140 zcmZozpxdxOcY-t{%S0JxRu%@mvd)bui`O$UZ06YTk8d)Y{lm%6_DgO$aF&mWSz`0~ za~6UisRvJaxVX)^WM!Mu6=j(we}8k4iFMoLlWz^0f4$xQ>n)?Z2&2VzCnl!%jEn*8 iMl4J~%nZaVK+FonY(UHo#2i4(3B+96jaazPc>@3y!!G9l