First Code Commit
This commit is contained in:
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System DockerFile
|
||||||
|
|
||||||
|
FROM python:3.12.3
|
||||||
|
|
||||||
|
LABEL maintainer="522499@student.fontys.nl"
|
||||||
|
|
||||||
|
WORKDIR /bank
|
||||||
|
|
||||||
|
COPY / /bank/
|
||||||
|
|
||||||
|
EXPOSE 81
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir --upgrade -r /bank/requirements.txt
|
||||||
|
|
||||||
|
ENTRYPOINT [ "python", "./api.py", "--host", "0.0.0.0", "--port", "81"]
|
||||||
8
Flask App/ARG/agent.py
Normal file
8
Flask App/ARG/agent.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--x', type=int, required=True)
|
||||||
|
parser.add_argument('--y', type=int, required=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
product = args.x * args.y
|
||||||
|
print(f"{args.x} * {args.y} = {product}")
|
||||||
19
Flask App/app.py
Normal file
19
Flask App/app.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from flask import Flask, render_template, request
|
||||||
|
import requests
|
||||||
|
|
||||||
|
SERVER_URL = "http://127.0.0.1:8000"
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/", methods=["GET"])
|
||||||
|
def loginGET():
|
||||||
|
return render_template("login.html")
|
||||||
|
|
||||||
|
@app.route("/", methods=["POST"])
|
||||||
|
def loginPOST():
|
||||||
|
username = request.form["username"]
|
||||||
|
password = request.form["password"]
|
||||||
|
response = requests.get( f"{SERVER_URL}/login?username={username}&password={password}")
|
||||||
|
return render_template("succes.html", data = response.content)
|
||||||
|
|
||||||
|
app.run()
|
||||||
0
Flask App/main.py
Normal file
0
Flask App/main.py
Normal file
17
Flask App/templates/login.html
Normal file
17
Flask App/templates/login.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Login</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form method="post">
|
||||||
|
<label>Username:</label>
|
||||||
|
<input type="text" name="username">
|
||||||
|
<label>Password:</label>
|
||||||
|
<input type="password" name="password">
|
||||||
|
<input type="submit" value="Login">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
11
Flask App/templates/succes.html
Normal file
11
Flask App/templates/succes.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>{{data}}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
686
Old/api.yml
Normal file
686
Old/api.yml
Normal file
@@ -0,0 +1,686 @@
|
|||||||
|
openapi: 3.0.3
|
||||||
|
info:
|
||||||
|
title: Banking System - OpenAPI 3.0
|
||||||
|
description: |-
|
||||||
|
This is the banking system API for the programming project.
|
||||||
|
contact:
|
||||||
|
email: 522499@student.fontys.nl
|
||||||
|
version: 1.0.11
|
||||||
|
servers:
|
||||||
|
- url: /
|
||||||
|
tags:
|
||||||
|
- name: accounts
|
||||||
|
description: Everything about your Accounts
|
||||||
|
- name: user
|
||||||
|
description: Operations about user
|
||||||
|
paths:
|
||||||
|
/Accounts:
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: Update an existing account
|
||||||
|
description: Update an existing account by Id
|
||||||
|
operationId: updateAccount
|
||||||
|
requestBody:
|
||||||
|
description: Update an existing bank account
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
text/html:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid ID supplied
|
||||||
|
'404':
|
||||||
|
description: Pet not found
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: Add a new pet to the store
|
||||||
|
description: Add a new pet to the store
|
||||||
|
operationId: addPet
|
||||||
|
requestBody:
|
||||||
|
description: Create a new pet in the store
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
/pet/findByStatus:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: Finds Pets by status
|
||||||
|
description: Multiple status values can be provided with comma separated strings
|
||||||
|
operationId: findPetsByStatus
|
||||||
|
parameters:
|
||||||
|
- name: status
|
||||||
|
in: query
|
||||||
|
description: Status values that need to be considered for filter
|
||||||
|
required: false
|
||||||
|
explode: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
default: available
|
||||||
|
enum:
|
||||||
|
- available
|
||||||
|
- pending
|
||||||
|
- sold
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid status value
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
/pet/findByTags:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: Finds Pets by tags
|
||||||
|
description: Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
|
||||||
|
operationId: findPetsByTags
|
||||||
|
parameters:
|
||||||
|
- name: tags
|
||||||
|
in: query
|
||||||
|
description: Tags to filter by
|
||||||
|
required: false
|
||||||
|
explode: true
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid tag value
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
/pet/{petId}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: Find pet by ID
|
||||||
|
description: Returns a single pet
|
||||||
|
operationId: getPetById
|
||||||
|
parameters:
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
description: ID of pet to return
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid ID supplied
|
||||||
|
'404':
|
||||||
|
description: Pet not found
|
||||||
|
security:
|
||||||
|
- api_key: []
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: Updates a pet in the store with form data
|
||||||
|
description: ''
|
||||||
|
operationId: updatePetWithForm
|
||||||
|
parameters:
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
description: ID of pet that needs to be updated
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
- name: name
|
||||||
|
in: query
|
||||||
|
description: Name of pet that needs to be updated
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: status
|
||||||
|
in: query
|
||||||
|
description: Status of pet that needs to be updated
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: Deletes a pet
|
||||||
|
description: delete a pet
|
||||||
|
operationId: deletePet
|
||||||
|
parameters:
|
||||||
|
- name: api_key
|
||||||
|
in: header
|
||||||
|
description: ''
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
description: Pet id to delete
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
responses:
|
||||||
|
'400':
|
||||||
|
description: Invalid pet value
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
/pet/{petId}/uploadImage:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- accounts
|
||||||
|
summary: uploads an image
|
||||||
|
description: ''
|
||||||
|
operationId: uploadFile
|
||||||
|
parameters:
|
||||||
|
- name: petId
|
||||||
|
in: path
|
||||||
|
description: ID of pet to update
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
- name: additionalMetadata
|
||||||
|
in: query
|
||||||
|
description: Additional Metadata
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/octet-stream:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: binary
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
security:
|
||||||
|
- petstore_auth:
|
||||||
|
- write:pets
|
||||||
|
- read:pets
|
||||||
|
/user:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Create user
|
||||||
|
description: This can only be done by the logged in user.
|
||||||
|
operationId: createUser
|
||||||
|
requestBody:
|
||||||
|
description: Created user object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
responses:
|
||||||
|
default:
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
/user/createWithList:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Creates list of users with given input array
|
||||||
|
description: Creates list of users with given input array
|
||||||
|
operationId: createUsersWithListInput
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
default:
|
||||||
|
description: successful operation
|
||||||
|
/user/login:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Logs user into the system
|
||||||
|
description: ''
|
||||||
|
operationId: loginUser
|
||||||
|
parameters:
|
||||||
|
- name: username
|
||||||
|
in: query
|
||||||
|
description: The user name for login
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: password
|
||||||
|
in: query
|
||||||
|
description: The password for login in clear text
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
headers:
|
||||||
|
X-Rate-Limit:
|
||||||
|
description: calls per hour allowed by the user
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
X-Expires-After:
|
||||||
|
description: date in UTC when token expires
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
content:
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Invalid username/password supplied
|
||||||
|
/user/logout:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Logs out current logged in user session
|
||||||
|
description: ''
|
||||||
|
operationId: logoutUser
|
||||||
|
parameters: []
|
||||||
|
responses:
|
||||||
|
default:
|
||||||
|
description: successful operation
|
||||||
|
/user/{username}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Get user by user name
|
||||||
|
description: ''
|
||||||
|
operationId: getUserByName
|
||||||
|
parameters:
|
||||||
|
- name: username
|
||||||
|
in: path
|
||||||
|
description: 'The name that needs to be fetched. Use user1 for testing. '
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
'400':
|
||||||
|
description: Invalid username supplied
|
||||||
|
'404':
|
||||||
|
description: User not found
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Update user
|
||||||
|
description: This can only be done by the logged in user.
|
||||||
|
operationId: updateUser
|
||||||
|
parameters:
|
||||||
|
- name: username
|
||||||
|
in: path
|
||||||
|
description: name that need to be deleted
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
description: Update an existent user in the store
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
application/x-www-form-urlencoded:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
responses:
|
||||||
|
default:
|
||||||
|
description: successful operation
|
||||||
|
delete:
|
||||||
|
tags:
|
||||||
|
- user
|
||||||
|
summary: Delete user
|
||||||
|
description: This can only be done by the logged in user.
|
||||||
|
operationId: deleteUser
|
||||||
|
parameters:
|
||||||
|
- name: username
|
||||||
|
in: path
|
||||||
|
description: The name that needs to be deleted
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'400':
|
||||||
|
description: Invalid username supplied
|
||||||
|
'404':
|
||||||
|
description: User not found
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Order:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
example: 10
|
||||||
|
petId:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
example: 198772
|
||||||
|
quantity:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
example: 7
|
||||||
|
shipDate:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
description: Order Status
|
||||||
|
example: approved
|
||||||
|
enum:
|
||||||
|
- placed
|
||||||
|
- approved
|
||||||
|
- delivered
|
||||||
|
complete:
|
||||||
|
type: boolean
|
||||||
|
xml:
|
||||||
|
name: order
|
||||||
|
Customer:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
example: 100000
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
example: fehguy
|
||||||
|
address:
|
||||||
|
type: array
|
||||||
|
xml:
|
||||||
|
name: addresses
|
||||||
|
wrapped: true
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Address'
|
||||||
|
xml:
|
||||||
|
name: customer
|
||||||
|
Address:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
street:
|
||||||
|
type: string
|
||||||
|
example: 437 Lytton
|
||||||
|
city:
|
||||||
|
type: string
|
||||||
|
example: Palo Alto
|
||||||
|
state:
|
||||||
|
type: string
|
||||||
|
example: CA
|
||||||
|
zip:
|
||||||
|
type: string
|
||||||
|
example: '94301'
|
||||||
|
xml:
|
||||||
|
name: address
|
||||||
|
Category:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
example: 1
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
example: Dogs
|
||||||
|
xml:
|
||||||
|
name: category
|
||||||
|
User:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
example: 10
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
example: theUser
|
||||||
|
firstName:
|
||||||
|
type: string
|
||||||
|
example: John
|
||||||
|
lastName:
|
||||||
|
type: string
|
||||||
|
example: James
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
example: john@email.com
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
example: '12345'
|
||||||
|
phone:
|
||||||
|
type: string
|
||||||
|
example: '12345'
|
||||||
|
userStatus:
|
||||||
|
type: integer
|
||||||
|
description: User Status
|
||||||
|
format: int32
|
||||||
|
example: 1
|
||||||
|
xml:
|
||||||
|
name: user
|
||||||
|
Tag:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
xml:
|
||||||
|
name: tag
|
||||||
|
Account:
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- photoUrls
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
example: 10
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
example: doggie
|
||||||
|
category:
|
||||||
|
$ref: '#/components/schemas/Category'
|
||||||
|
photoUrls:
|
||||||
|
type: array
|
||||||
|
xml:
|
||||||
|
wrapped: true
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
xml:
|
||||||
|
name: photoUrl
|
||||||
|
tags:
|
||||||
|
type: array
|
||||||
|
xml:
|
||||||
|
wrapped: true
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/Tag'
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
description: pet status in the store
|
||||||
|
enum:
|
||||||
|
- available
|
||||||
|
- pending
|
||||||
|
- sold
|
||||||
|
xml:
|
||||||
|
name: pet
|
||||||
|
ApiResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
code:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
xml:
|
||||||
|
name: '##default'
|
||||||
|
requestBodies:
|
||||||
|
Pet:
|
||||||
|
description: Pet object that needs to be added to the store
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
application/xml:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
UserArray:
|
||||||
|
description: List of user object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/User'
|
||||||
|
securitySchemes:
|
||||||
|
petstore_auth:
|
||||||
|
type: oauth2
|
||||||
|
flows:
|
||||||
|
implicit:
|
||||||
|
authorizationUrl: https://petstore3.swagger.io/oauth/authorize
|
||||||
|
scopes:
|
||||||
|
write:pets: modify pets in your account
|
||||||
|
read:pets: read your pets
|
||||||
|
api_key:
|
||||||
|
type: apiKey
|
||||||
|
name: api_key
|
||||||
|
in: header
|
||||||
59
Old/class.py
Normal file
59
Old/class.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Transaction:
|
||||||
|
def __init__(self, trans_id, from_id, to_id, amount, time, date, description, t_type):
|
||||||
|
self.trans_id = trans_id
|
||||||
|
self.from_id = from_id
|
||||||
|
self.to_id = to_id
|
||||||
|
self.amount = amount
|
||||||
|
self.time = time
|
||||||
|
self.date = date
|
||||||
|
self.description = description
|
||||||
|
self.t_type = t_type
|
||||||
|
|
||||||
|
|
||||||
|
class Account:
|
||||||
|
def __init__(self, account_id, name, balance, created_t, created_d, last_modified, closed, closure_t, closure_d,
|
||||||
|
notes, transactions=None):
|
||||||
|
if transactions is None:
|
||||||
|
transactions = []
|
||||||
|
self.account_id = account_id
|
||||||
|
self.name = name
|
||||||
|
self.balance = balance
|
||||||
|
self.created_t = created_t
|
||||||
|
self.created_d = created_d
|
||||||
|
self.last_modified = last_modified
|
||||||
|
self.closed = closed
|
||||||
|
self.closure_t = closure_t
|
||||||
|
self.closure_d = closure_d
|
||||||
|
self.notes = notes
|
||||||
|
self.transactions = transactions
|
||||||
|
|
||||||
|
|
||||||
|
class Customer:
|
||||||
|
def __init__(self, customer_id, f_name, l_name, phone, email, birthday, address, signup_d, signup_t, notes,
|
||||||
|
accounts=None):
|
||||||
|
if accounts is None:
|
||||||
|
accounts = []
|
||||||
|
self.customer_id = customer_id
|
||||||
|
self.f_name = f_name
|
||||||
|
self.l_name = l_name
|
||||||
|
self.phone = phone
|
||||||
|
self.email = email
|
||||||
|
self.birthday = birthday
|
||||||
|
self.address = address
|
||||||
|
self.signup_d = signup_d
|
||||||
|
self.signup_t = signup_t
|
||||||
|
self.notes = notes
|
||||||
|
self.accounts = accounts
|
||||||
|
|
||||||
|
#calculate the balance of an account
|
||||||
|
def calc_balance(account):
|
||||||
|
balance = 0
|
||||||
|
for transaction in account.transactions:
|
||||||
|
if transaction.from_id == account.account_id:
|
||||||
|
balance -= transaction.amount
|
||||||
|
elif transaction.to_id == account.account_id:
|
||||||
|
balance += transaction.amount
|
||||||
|
return balance
|
||||||
4
Old/manager_account.py
Normal file
4
Old/manager_account.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Manager for Account Class - Version 1
|
||||||
|
|
||||||
|
|
||||||
24
Old/manager_transaction.py
Normal file
24
Old/manager_transaction.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Manager for Transaction Class - Version 1
|
||||||
|
|
||||||
|
|
||||||
|
def add_transaction(transaction_id, transaction_type, amount, timestamp, description, account_number, recipient_account_number):
|
||||||
|
from api import session, Transaction
|
||||||
|
new_transaction = Transaction(transaction_id, transaction_type, amount, timestamp, description, account_number, recipient_account_number)
|
||||||
|
session.add(new_transaction)
|
||||||
|
session.commit()
|
||||||
|
return new_transaction
|
||||||
|
|
||||||
|
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."
|
||||||
196
Old/server.py
Normal file
196
Old/server.py
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Classes - Version 2
|
||||||
|
|
||||||
|
###############
|
||||||
|
### Modules ###
|
||||||
|
###############
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
import os.path
|
||||||
|
import datetime
|
||||||
|
import connexion
|
||||||
|
from config import CONFIG
|
||||||
|
|
||||||
|
#################
|
||||||
|
### Functions ###
|
||||||
|
#################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###############
|
||||||
|
### Classes ###
|
||||||
|
###############
|
||||||
|
|
||||||
|
class Manager:
|
||||||
|
def __init__():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
def __init__(self, client_id, name, opening_timestamp, birthdate, address, phone_number, email:str, password, accounts, notes):
|
||||||
|
self.client_id = client_id
|
||||||
|
self.name = name
|
||||||
|
self.birthdate = birthdate
|
||||||
|
self.opening_timestamp = opening_timestamp
|
||||||
|
self.address = address
|
||||||
|
self.phone_number = phone_number
|
||||||
|
self.email = email
|
||||||
|
self.password = password
|
||||||
|
self.accounts = accounts
|
||||||
|
self.notes = notes
|
||||||
|
|
||||||
|
#If you call a print function on the object, it will return the following string (does not include password for security reasons)
|
||||||
|
def __str__(self):
|
||||||
|
return f"Client ID: {self.client_id}, Name: {self.name}, Birthdate: {self.birthdate}, Address: {self.address}, Phone Number: {self.phone_number}, Email: {self.email}"
|
||||||
|
|
||||||
|
#This function will return the account list
|
||||||
|
def get_accounts(self)->str:
|
||||||
|
return f"Accounts: {self.accounts}"
|
||||||
|
|
||||||
|
#Change details (name, birthdate, address, phone number, email, password)
|
||||||
|
#Change password
|
||||||
|
|
||||||
|
class Account:
|
||||||
|
def __init__(self, account_id, description, open_timestamp, account_type, balance, enabled, notes, transactions):
|
||||||
|
self.account_id = account_id
|
||||||
|
self.description = description
|
||||||
|
self.open_timestamp = open_timestamp
|
||||||
|
self.account_type = account_type
|
||||||
|
self.balance = balance
|
||||||
|
self.enabled = enabled
|
||||||
|
self.notes = notes
|
||||||
|
self.transactions = transactions
|
||||||
|
|
||||||
|
#If you call a print function on the object, it will return the following string
|
||||||
|
def __str__(self):
|
||||||
|
return f"Account ID: {self.account_id}, Description: {self.description}, Open Timestamp: {self.open_timestamp}, Account Type: {self.account_type}, Balance: {self.balance}, Enabled: {self.enabled}, Notes: {self.notes}, Transactions: {self.transactions}"
|
||||||
|
|
||||||
|
# This function will return the transaction history of an account
|
||||||
|
def transaction_history(self, account_id:int):
|
||||||
|
return self.transactions
|
||||||
|
|
||||||
|
#This function will remove the account
|
||||||
|
def remove_account(self, account_id:int):
|
||||||
|
REMOVE_ACCOUNT = "DELETE FROM account WHERE account_id=?"
|
||||||
|
for account in self.accounts:
|
||||||
|
if account.balance != 0: #If the account has a balance, it can not be removed
|
||||||
|
return f"Account ID: {account_id} has a balance of {account.balance} and can not be removed."
|
||||||
|
if account.account_id == account_id: #Check if account exists
|
||||||
|
input(f"Are you sure you would like permanenty delete account ID: {account_id}? WARNING: This action can not be reversed. (Y/N) ")
|
||||||
|
if input == "Y"or input == "y": #If the user inputs Y or y, the account will be removed
|
||||||
|
db_conn = get_db_connection()
|
||||||
|
cursor = db_conn.cursor()
|
||||||
|
cursor.execute(REMOVE_ACCOUNT, (account_id, ) )
|
||||||
|
db_conn.commit()
|
||||||
|
print(f"Account ID: {account_id} has been removed.")
|
||||||
|
else:
|
||||||
|
return f"Account ID: {account_id} has NOT been removed."
|
||||||
|
return
|
||||||
|
return f"Account ID: {account_id} is not found."
|
||||||
|
|
||||||
|
#This function will return the account balance
|
||||||
|
def account_balance(account_id:int):
|
||||||
|
GET_ACCOUNT = "SELECT balance FROM account WHERE account_id = ?"
|
||||||
|
|
||||||
|
db_conn = get_db_connection()
|
||||||
|
cursor = db_conn.cursor()
|
||||||
|
cursor.execute(GET_ACCOUNT, (account_id) )
|
||||||
|
resultset = cursor.fetchall()
|
||||||
|
db_conn.close()
|
||||||
|
|
||||||
|
if len(resultset) < 1:
|
||||||
|
return "Not found", 404
|
||||||
|
elif len(resultset) > 2:
|
||||||
|
return "Too many results found.", 500
|
||||||
|
|
||||||
|
class Transaction:
|
||||||
|
def __init__(self, transaction_id, transaction_type, amount, timestamp, description, account_number, recipient_account_number = None):
|
||||||
|
self.transaction_id = transaction_id
|
||||||
|
self.transaction_type = transaction_type
|
||||||
|
self.amount = amount
|
||||||
|
self.timestamp = timestamp
|
||||||
|
self.description = description
|
||||||
|
self.account_number = account_number
|
||||||
|
self.recipient_account_number = recipient_account_number
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Transaction ID: {self.transaction_id}, Transaction Type: {self.transaction_type}, Amount: {self.amount}, Timestamp: {self.timestamp}, Description: {self.description} From Account Number: {self.account_number}, Recipient Account Number: {self.recipient_account_number}"
|
||||||
|
|
||||||
|
################
|
||||||
|
### Database ###
|
||||||
|
################
|
||||||
|
|
||||||
|
def Database():
|
||||||
|
CLIENT_TABLE_CREATION_QUERY = """
|
||||||
|
CREATE TABLE IF NOT EXISTS client (
|
||||||
|
client_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
birthdate DATE NOT NULL,
|
||||||
|
opening_timestamp TIMESTAMP NOT NULL,
|
||||||
|
address TEXT NOT NULL,
|
||||||
|
phone_number TEXT NOT NULL,
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
password TEXT NOT NULL,
|
||||||
|
notes TEXT NOT NULL
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
ACCOUNT_TABLE_CREATION_QUERY = """
|
||||||
|
CREATE TABLE IF NOT EXISTS account (
|
||||||
|
account_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
description TEXT NOT NULL,
|
||||||
|
open_timestamp TIMESTAMP NOT NULL,
|
||||||
|
account_type TEXT NOT NULL,
|
||||||
|
balance REAL NOT NULL,
|
||||||
|
enabled BOOLEAN NOT NULL,
|
||||||
|
notes TEXT NOT NULL,
|
||||||
|
client_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (client_id) REFERENCES client(client_id)
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
TRANSACT_TABLE_CREATION_QUERY = """
|
||||||
|
CREATE TABLE IF NOT EXISTS transact (
|
||||||
|
transaction_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
transaction_type TEXT NOT NULL,
|
||||||
|
amount REAL NOT NULL,
|
||||||
|
timestamp TIMESTAMP NOT NULL,
|
||||||
|
description TEXT NOT NULL,
|
||||||
|
account_id INTEGER NOT NULL,
|
||||||
|
recipient_account_id INTEGER,
|
||||||
|
FOREIGN KEY (account_id) REFERENCES account(account_id)
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
# Check if the database exists
|
||||||
|
if os.path.exists('bank.db'):
|
||||||
|
print("Database already exists.")
|
||||||
|
else:
|
||||||
|
print("Database does not exist. Creating database.")
|
||||||
|
|
||||||
|
# Create the database and the tables if they do not exist, or connect to the database if it does exist
|
||||||
|
db_connection = sqlite3.connect('bank.db')
|
||||||
|
db_cursor = db_connection.cursor()
|
||||||
|
db_cursor.execute(CLIENT_TABLE_CREATION_QUERY)
|
||||||
|
db_cursor.execute(ACCOUNT_TABLE_CREATION_QUERY)
|
||||||
|
db_cursor.execute(TRANSACT_TABLE_CREATION_QUERY)
|
||||||
|
db_connection.commit()
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
### Connexion ###
|
||||||
|
#################
|
||||||
|
|
||||||
|
def API():
|
||||||
|
app = connexion.App(__name__)
|
||||||
|
app.add_api('api.yml')
|
||||||
|
app.run(host=CONFIG["server"]["listen_address"], port=CONFIG["server"]["port"], debug=CONFIG["server"]["debug"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
################
|
||||||
|
### Run Code ###
|
||||||
|
################
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
Database()
|
||||||
|
API()
|
||||||
BIN
__pycache__/class_account.cpython-312.pyc
Normal file
BIN
__pycache__/class_account.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/class_base.cpython-312.pyc
Normal file
BIN
__pycache__/class_base.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/class_client.cpython-312.pyc
Normal file
BIN
__pycache__/class_client.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/class_transaction.cpython-312.pyc
Normal file
BIN
__pycache__/class_transaction.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/config.cpython-312.pyc
Normal file
BIN
__pycache__/config.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/database.cpython-312.pyc
Normal file
BIN
__pycache__/database.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/manager.cpython-312.pyc
Normal file
BIN
__pycache__/manager.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/manager_account.cpython-312.pyc
Normal file
BIN
__pycache__/manager_account.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/manager_client.cpython-312.pyc
Normal file
BIN
__pycache__/manager_client.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/manager_transaction.cpython-312.pyc
Normal file
BIN
__pycache__/manager_transaction.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/operator_account.cpython-312.pyc
Normal file
BIN
__pycache__/operator_account.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/operator_client.cpython-312.pyc
Normal file
BIN
__pycache__/operator_client.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/operator_transaction.cpython-312.pyc
Normal file
BIN
__pycache__/operator_transaction.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/password.cpython-312.pyc
Normal file
BIN
__pycache__/password.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/server.cpython-312.pyc
Normal file
BIN
__pycache__/server.cpython-312.pyc
Normal file
Binary file not shown.
26
api.py
Normal file
26
api.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System API
|
||||||
|
|
||||||
|
###############
|
||||||
|
### Modules ###
|
||||||
|
###############
|
||||||
|
|
||||||
|
import connexion # Imports connexion module
|
||||||
|
from config import CONFIG # Imports the configuration file
|
||||||
|
from manager import * # Imports the Manager file that contains the functions for the API
|
||||||
|
|
||||||
|
#################
|
||||||
|
### Connexion ###
|
||||||
|
#################
|
||||||
|
|
||||||
|
def API():
|
||||||
|
app = connexion.FlaskApp(__name__)
|
||||||
|
app.add_api(CONFIG["api_file"]["name"])
|
||||||
|
app.run(host=CONFIG["server"]["listen_ip"], port=CONFIG["server"]["port"], debug=CONFIG["server"]["debug"]) # Runs the API using the configuration file
|
||||||
|
|
||||||
|
################
|
||||||
|
### Run Code ###
|
||||||
|
################
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
API()
|
||||||
701
api.yml
Normal file
701
api.yml
Normal file
@@ -0,0 +1,701 @@
|
|||||||
|
openapi: 3.0.3
|
||||||
|
info:
|
||||||
|
title: Banking API
|
||||||
|
description: |-
|
||||||
|
Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
contact:
|
||||||
|
email: 522499@student.fontys.nl
|
||||||
|
version: 2.0.0
|
||||||
|
servers:
|
||||||
|
- url: http://127.0.0.1:81
|
||||||
|
tags:
|
||||||
|
- name: client
|
||||||
|
description: Operations for Client Accounts
|
||||||
|
- name: account
|
||||||
|
description: Operations for Bank Accounts
|
||||||
|
- name: transaction
|
||||||
|
description: Operations for Transactions
|
||||||
|
- name: manager
|
||||||
|
description: Operations for Bank Managers
|
||||||
|
paths:
|
||||||
|
/Client/Login:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- client
|
||||||
|
summary: Log in to the system
|
||||||
|
description: Log in to the system
|
||||||
|
operationId: manager.login_user
|
||||||
|
requestBody:
|
||||||
|
description: Credentials for logging in
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Client'
|
||||||
|
'400':
|
||||||
|
description: Invalid username/password supplied
|
||||||
|
'401':
|
||||||
|
description: Unauthorized
|
||||||
|
/Client/Logout:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- client
|
||||||
|
summary: Log out from the system
|
||||||
|
description: Log out from the system
|
||||||
|
operationId: manager.logout_user
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
'401':
|
||||||
|
description: Unauthorized
|
||||||
|
/Client/Password:
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- client
|
||||||
|
summary: Change password
|
||||||
|
description: Change password
|
||||||
|
operationId: manager.change_password
|
||||||
|
parameters:
|
||||||
|
- name: client_id
|
||||||
|
in: query
|
||||||
|
description: ID of client to change password
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
- name: password
|
||||||
|
in: query
|
||||||
|
description: New password
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: new_password
|
||||||
|
in: query
|
||||||
|
description: New password
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Password changed successfully
|
||||||
|
'400':
|
||||||
|
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 Email Address
|
||||||
|
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
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- client
|
||||||
|
summary: Update an existing client
|
||||||
|
description: Update an existing client Id
|
||||||
|
operationId: manager.update_client
|
||||||
|
requestBody:
|
||||||
|
description: Update an existing client's details
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Client'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Client'
|
||||||
|
'400':
|
||||||
|
description: Invalid Client ID supplied
|
||||||
|
'404':
|
||||||
|
description: Client not found
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- client
|
||||||
|
summary: Get a client by ID
|
||||||
|
description: Get a client by ID
|
||||||
|
operationId: manager.get_client
|
||||||
|
parameters:
|
||||||
|
- name: client_id
|
||||||
|
in: query
|
||||||
|
description: ID of client to return
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Client'
|
||||||
|
'400':
|
||||||
|
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:
|
||||||
|
- account
|
||||||
|
summary: Add a new account
|
||||||
|
description: Add a new account to the system
|
||||||
|
operationId: manager.add_account
|
||||||
|
parameters:
|
||||||
|
- name: description
|
||||||
|
in: query
|
||||||
|
description: Account description
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: account_type
|
||||||
|
in: query
|
||||||
|
description: Type of account
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: notes
|
||||||
|
in: query
|
||||||
|
description: Notes about account
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- account
|
||||||
|
summary: Update an existing account
|
||||||
|
description: Update an existing account
|
||||||
|
operationId: manager.update_account
|
||||||
|
parameters:
|
||||||
|
- name: account_id
|
||||||
|
in: query
|
||||||
|
description: ID of account to update
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
requestBody:
|
||||||
|
description: Update an existing account
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid Account ID supplied
|
||||||
|
'404':
|
||||||
|
description: Account not found
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- account
|
||||||
|
summary: Get an account by ID
|
||||||
|
description: Get an account by ID
|
||||||
|
operationId: manager.get_account
|
||||||
|
parameters:
|
||||||
|
- name: account_id
|
||||||
|
in: query
|
||||||
|
description: ID of account to return
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
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:
|
||||||
|
- transaction
|
||||||
|
summary: Get a transaction by ID
|
||||||
|
description: Get a transaction by ID
|
||||||
|
operationId: manager.get_transaction
|
||||||
|
parameters:
|
||||||
|
- name: transaction_id
|
||||||
|
in: query
|
||||||
|
description: ID of transaction to return
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Transaction'
|
||||||
|
'400':
|
||||||
|
description: Invalid Transaction ID supplied
|
||||||
|
'404':
|
||||||
|
description: Transaction not found
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- transaction
|
||||||
|
summary: Add a new transaction
|
||||||
|
description: Add a new transaction to the system
|
||||||
|
operationId: manager.add_transaction
|
||||||
|
parameters:
|
||||||
|
- name: amount
|
||||||
|
in: query
|
||||||
|
description: Amount of transaction
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
- name: account_from
|
||||||
|
in: query
|
||||||
|
description: Account number the money paid from
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: account_to
|
||||||
|
in: query
|
||||||
|
description: Recipient account number
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: description
|
||||||
|
in: query
|
||||||
|
description: Description of transaction
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
/Transaction/History:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- transaction
|
||||||
|
summary: Get transaction history
|
||||||
|
description: Get transaction history
|
||||||
|
operationId: manager.transaction_history
|
||||||
|
parameters:
|
||||||
|
- name: account_id
|
||||||
|
in: query
|
||||||
|
description: ID of account to return
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Transaction'
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'404':
|
||||||
|
description: No transactions found
|
||||||
|
/Manager/Interest:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Apply interest
|
||||||
|
description: Apply interest to account
|
||||||
|
operationId: manager.apply_interest
|
||||||
|
requestBody:
|
||||||
|
description: Apply interest to account
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Apply fee
|
||||||
|
description: Apply fee to account
|
||||||
|
operationId: manager.apply_fee
|
||||||
|
requestBody:
|
||||||
|
description: Apply fee to account
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
/Manager/Clients:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Get all clients
|
||||||
|
description: Get all clients
|
||||||
|
operationId: manager.get_all_clients
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Client'
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'404':
|
||||||
|
description: No clients found
|
||||||
|
/Manager/Accounts:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Get all accounts
|
||||||
|
description: Get all accounts
|
||||||
|
operationId: manager.get_all_accounts
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Account'
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'404':
|
||||||
|
description: No accounts found
|
||||||
|
/Manager/Transactions:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Get all transactions
|
||||||
|
description: Get all transactions
|
||||||
|
operationId: manager.get_all_transactions
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Transaction'
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'404':
|
||||||
|
description: No transactions found
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Update an existing transaction
|
||||||
|
description: Update an existing transaction
|
||||||
|
operationId: manager.update_transaction
|
||||||
|
requestBody:
|
||||||
|
description: Update an existing transaction
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Transaction'
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/Transaction'
|
||||||
|
'400':
|
||||||
|
description: Invalid Transaction ID supplied
|
||||||
|
'404':
|
||||||
|
description: Transaction not found
|
||||||
|
'422':
|
||||||
|
description: Validation exception
|
||||||
|
/Manager/Hash:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Hash password
|
||||||
|
description: Pass a string through the hashing algorithm
|
||||||
|
operationId: manager.password_hash
|
||||||
|
parameters:
|
||||||
|
- name: password
|
||||||
|
in: query
|
||||||
|
description: Password to hash
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'401':
|
||||||
|
description: Unauthorized
|
||||||
|
/Manager/Timestamp:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- manager
|
||||||
|
summary: Get the timestamp
|
||||||
|
description: Gets the date and time in the appropriate format
|
||||||
|
operationId: manager.timestamp
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
'400':
|
||||||
|
description: Invalid input
|
||||||
|
'401':
|
||||||
|
description: Unauthorized
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Client:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
client_id:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
birthdate:
|
||||||
|
type: string
|
||||||
|
opening_timestamp:
|
||||||
|
type: string
|
||||||
|
address:
|
||||||
|
type: string
|
||||||
|
phone_number:
|
||||||
|
type: string
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
notes:
|
||||||
|
type: string
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
administator:
|
||||||
|
type: boolean
|
||||||
|
accounts:
|
||||||
|
type: array
|
||||||
|
example:
|
||||||
|
client_id: 1
|
||||||
|
name: "Lucas Mathews"
|
||||||
|
birthdate: "21-05-1980"
|
||||||
|
opening_timestamp: "17-04-2022 16:21:12"
|
||||||
|
address: "Rachelsmolen 1, 5612MA, Eindhoven"
|
||||||
|
phone_number: "0612345678"
|
||||||
|
email: "john.d@fontys.nl"
|
||||||
|
password: "password"
|
||||||
|
notes: "This is a test client"
|
||||||
|
enabled: true
|
||||||
|
administator: false
|
||||||
|
accounts: []
|
||||||
|
Account:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
account_id:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
decription:
|
||||||
|
type: string
|
||||||
|
opening_timestamp:
|
||||||
|
type: string
|
||||||
|
account_type:
|
||||||
|
type: string
|
||||||
|
balance:
|
||||||
|
type: number
|
||||||
|
enabled:
|
||||||
|
type: boolean
|
||||||
|
notes:
|
||||||
|
type: string
|
||||||
|
transactons:
|
||||||
|
type: array
|
||||||
|
example:
|
||||||
|
account_id: 1
|
||||||
|
description: "Savings Account"
|
||||||
|
opening_timestamp: "17-04-2022 16:21:12"
|
||||||
|
account_type: "Rachelsmolen 1, 5612MA, Eindhoven"
|
||||||
|
balance: 2314.23
|
||||||
|
enabled: true
|
||||||
|
notes: "This is a savings account"
|
||||||
|
transactions: []
|
||||||
|
Transaction:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
transaction_id:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
transaction_type:
|
||||||
|
type: string
|
||||||
|
amount:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
timestamp:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
account_number:
|
||||||
|
type: string
|
||||||
|
recipient_account_number:
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
transaction_id: 1
|
||||||
|
transaction_type: "Deposit"
|
||||||
|
amount: 100.00
|
||||||
|
timestamp: "17-04-2022 16:21:12"
|
||||||
|
description: "Deposit to Savings Account"
|
||||||
|
account_number: "NL12ABNA0123456789"
|
||||||
|
recipient_account_number: "NL12ABNA1234567890"
|
||||||
|
|
||||||
20
bank.ini
Normal file
20
bank.ini
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
[database]
|
||||||
|
name=bank.db
|
||||||
|
add_sample_data=True
|
||||||
|
|
||||||
|
[api_file]
|
||||||
|
name=api.yml
|
||||||
|
|
||||||
|
[server]
|
||||||
|
listen_ip=127.0.0.1
|
||||||
|
port=81
|
||||||
|
debug=True
|
||||||
|
|
||||||
|
[frontend]
|
||||||
|
listen_ip=127.0.0.1
|
||||||
|
port=80
|
||||||
|
debug=True
|
||||||
|
|
||||||
|
[api]
|
||||||
|
url=http://127.0.0.1:81/
|
||||||
|
|
||||||
31
class_account.py
Normal file
31
class_account.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Account Class
|
||||||
|
|
||||||
|
from sqlalchemy import ForeignKey, Column, String, Integer, Boolean
|
||||||
|
|
||||||
|
|
||||||
|
from class_base import Base
|
||||||
|
|
||||||
|
class Account(Base):
|
||||||
|
__tablename__ = 'accounts'
|
||||||
|
account_id = Column("account_id", String, primary_key=True)
|
||||||
|
description = Column("description", String)
|
||||||
|
open_timestamp = Column("open_timestamp", String)
|
||||||
|
account_type = Column("account_type", String)
|
||||||
|
balance = Column("balance", Integer)
|
||||||
|
enabled = Column("enabled", Boolean)
|
||||||
|
notes = Column("notes", String)
|
||||||
|
transactions = ("transactions", String, ForeignKey("transactions.transaction_id"))
|
||||||
|
|
||||||
|
def __init__(self, account_id, description, open_timestamp, account_type, balance, enabled, notes, transactions):
|
||||||
|
self.account_id = account_id
|
||||||
|
self.description = description
|
||||||
|
self.open_timestamp = open_timestamp
|
||||||
|
self.account_type = account_type
|
||||||
|
self.balance = balance
|
||||||
|
self.enabled = enabled
|
||||||
|
self.notes = notes
|
||||||
|
self.transactions = transactions
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Account ID: {self.account_id}, Description: {self.description}, Open Timestamp: {self.open_timestamp}, Account Type: {self.account_type}, Balance: {self.balance}, Enabled: {self.enabled}, Notes: {self.notes}, Transactions: {self.transactions}"
|
||||||
6
class_base.py
Normal file
6
class_base.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Base Class
|
||||||
|
|
||||||
|
from sqlalchemy.orm import declarative_base
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
38
class_client.py
Normal file
38
class_client.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Client Class
|
||||||
|
|
||||||
|
from sqlalchemy import Column, String, Boolean
|
||||||
|
|
||||||
|
from class_base import Base
|
||||||
|
|
||||||
|
class Client(Base):
|
||||||
|
__tablename__ = 'clients'
|
||||||
|
client_id = Column("client_id", String, primary_key=True)
|
||||||
|
name = Column("name", String)
|
||||||
|
birthdate = Column("birthdate", String)
|
||||||
|
opening_timestamp = Column("opening_timestamp", String)
|
||||||
|
address = Column("address", String)
|
||||||
|
phone_number = Column("phone_number", String)
|
||||||
|
email = Column("email", String)
|
||||||
|
hash = Column("hash", String)
|
||||||
|
notes = Column("notes", String)
|
||||||
|
enabled = Column("enabled", Boolean)
|
||||||
|
administrator = Column("administrator", Boolean)
|
||||||
|
accounts = Column("accounts", String)
|
||||||
|
|
||||||
|
def __init__(self, client_id, name, birthdate, opening_timestamp, address, phone_number, email, hash, notes, enabled, administrator, accounts):
|
||||||
|
self.client_id = client_id
|
||||||
|
self.name = name
|
||||||
|
self.birthdate = birthdate
|
||||||
|
self.opening_timestamp = opening_timestamp
|
||||||
|
self.address = address
|
||||||
|
self.phone_number = phone_number
|
||||||
|
self.email = email
|
||||||
|
self.hash = hash
|
||||||
|
self.notes = notes
|
||||||
|
self.enabled = enabled
|
||||||
|
self.administrator = administrator
|
||||||
|
self.accounts = accounts
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Client ID: {self.client_id}, Name: {self.name}, Birthdate: {self.birthdate}, Address: {self.address}, Phone Number: {self.phone_number}, Email: {self.email}, Enabled: {self.enabled}, Accounts: {self.accounts}"
|
||||||
28
class_transaction.py
Normal file
28
class_transaction.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Transaction Class
|
||||||
|
|
||||||
|
from sqlalchemy import Column, String, Integer
|
||||||
|
|
||||||
|
from class_base import Base
|
||||||
|
|
||||||
|
class Transaction(Base):
|
||||||
|
__tablename__ = 'transactions'
|
||||||
|
transaction_id = Column("transaction_id", String, primary_key=True)
|
||||||
|
transaction_type = Column("transaction_type", String)
|
||||||
|
amount = Column("amount", Integer)
|
||||||
|
timestamp = Column("timestamp", String)
|
||||||
|
description = Column("description", String)
|
||||||
|
account_number = Column("account_number", Integer)
|
||||||
|
recipient_account_number = Column("recipient_account_number", Integer)
|
||||||
|
|
||||||
|
def __init__(self, transaction_id, transaction_type, amount, timestamp, description, account_number, recipient_account_number = None):
|
||||||
|
self.transaction_id = transaction_id
|
||||||
|
self.transaction_type = transaction_type
|
||||||
|
self.amount = amount
|
||||||
|
self.timestamp = timestamp
|
||||||
|
self.description = description
|
||||||
|
self.account_number = account_number
|
||||||
|
self.recipient_account_number = recipient_account_number
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"Transaction ID: {self.transaction_id}, Transaction Type: {self.transaction_type}, Amount: {self.amount}, Timestamp: {self.timestamp}, Description: {self.description} From Account Number: {self.account_number}, Recipient Account Number: {self.recipient_account_number}"
|
||||||
19
cli.py
Normal file
19
cli.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System CLI Utility
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
SERVER_URL = "http://127.0.0.1:5000"
|
||||||
|
|
||||||
|
def main():
|
||||||
|
username = "john"
|
||||||
|
password = "doe"
|
||||||
|
print(f"Login with {username} and {password}:")
|
||||||
|
response = requests.get( f"{SERVER_URL}/login?username={username}&password={password}")
|
||||||
|
print(f"{response}, {response.content}")
|
||||||
|
|
||||||
|
print(f"Logout:")
|
||||||
|
response = requests.get( f"{SERVER_URL}/logout")
|
||||||
|
print(f"{response}, {response.content}")
|
||||||
|
print(f"Closing")
|
||||||
|
main()
|
||||||
7
config.py
Normal file
7
config.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Config Parser
|
||||||
|
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
CONFIG = configparser.ConfigParser()
|
||||||
|
CONFIG.read("bank.ini")
|
||||||
58
database.py
Normal file
58
database.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Manager File
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
|
#Import Config
|
||||||
|
from config import CONFIG
|
||||||
|
|
||||||
|
# Check if the database exists
|
||||||
|
if os.path.exists(CONFIG["database"]["name"]):
|
||||||
|
print(f"Database {CONFIG["database"]["name"]} already exists.")
|
||||||
|
else:
|
||||||
|
print(f"Database {CONFIG["database"]["name"]} does not exist. Creating it now.")
|
||||||
|
|
||||||
|
# Sets the database file to be used from the configuration file
|
||||||
|
db_url : str = "sqlite:///" + CONFIG["database"]["name"]
|
||||||
|
print(f"Database file set to: {db_url}")
|
||||||
|
|
||||||
|
# Creates the database engine (does not create the database file if it already exists)
|
||||||
|
engine = create_engine(db_url, echo=True)
|
||||||
|
|
||||||
|
#Import Classes
|
||||||
|
from class_base import Base # Imports the base class required by SQLAlchemy
|
||||||
|
from class_client import Client
|
||||||
|
from class_account import Account
|
||||||
|
from class_transaction import Transaction
|
||||||
|
|
||||||
|
# Create the tables in the database
|
||||||
|
Base.metadata.create_all(bind=engine) # Creates the tables in the database from the classes
|
||||||
|
|
||||||
|
# Creates a session to interact with the database
|
||||||
|
Session = sessionmaker(bind=engine) # Creates a session to interact with the database
|
||||||
|
session = Session() # Creates a session object
|
||||||
|
|
||||||
|
# Add sample data if enabled in the configuration file if the database is empty
|
||||||
|
if CONFIG["database"]["add_sample_data"] == "True": # Checks if sample data addition is enabled
|
||||||
|
if session.query(Client).count() == 0: # Checks if the database is empty
|
||||||
|
print(f"Sample data addition is disabled because the database is not empty.")
|
||||||
|
print(f"Adding sample data to new database file {CONFIG["database"]["name"]}.")
|
||||||
|
session.add(Client("f9a16945-b570-4153-ba63-413f2cc2768a", "Lucas Mathews", "24/08/1998", "17/04/2024", "Rachelsmolen 1, 5612MA, Eindhoven", "0612345678", "522499@student.fontys.nl", "7835062ec36ed529fe22cc63baf3ec18d347dacb21c9801da8ba0848cc18efdf1e51717dd5b1240f7556aca3947aa0722452858be6002c1d46b1f1c311b0e9d8", "Notes", True, True, "1, 2"))
|
||||||
|
session.add(Client("5be2a74d-d55c-4de6-85a1-2ed6a355f2cd", "Rigby", "16/03/2018", "06/05/2024", "Rachelsmolen 1, 5612MA, Eindhoven", "0612345678", "522499@cat.fontys.nl", "d3e7df3c78682fbb51e8c6110b3926349bb426bc9834c640cd666519901aef3dfab7822d66fb2dd9e39eb5a8492f6801c2e17ba4c16b8fbcd159c036fe27d8bd", "Is a cat", True, False, "3"))
|
||||||
|
session.add(Account("4c227b02-348c-4611-99a2-8967680cdee6", "Savings Account", "17/04/2024", "Savings", 3000, True, "Savings account", "1"))
|
||||||
|
session.add(Account("b9d9b801-eaab-45be-a4d1-1f7b0bbf798f", "Spending Account", "17/04/2024", "Spending", 150, True, "Spending account", "1"))
|
||||||
|
session.add(Account("f182f186-0a88-4f98-8a02-3a568c65aba7", "Cat Account", "06/05/2024", "Cat Account", 497, True, "Food savings", "2"))
|
||||||
|
session.add(Transaction("9d989788-f983-4590-8de2-9aa0c8bec7d2", "Deposit", 5000, "17/04/2024", "Initial Deposit", 1, "23542335"))
|
||||||
|
session.add(Transaction("153cee93-51c7-4114-b9ef-e307fbf0bf87", "Deposit", 100, "17/04/2024", "Initial Deposit", 2, "23542335"))
|
||||||
|
session.add(Transaction("4bec761a-0f36-452f-a48a-127dcf526e47", "Deposit", 500, "06/05/2024", "Initial Deposit", 3, "23542335"))
|
||||||
|
session.add(Transaction("227a2a9e-a13b-484b-b037-78deeeb0258c", "Withdrawal", 2000, "06/05/2024", "Uni Fees", 3, "Fontys University"))
|
||||||
|
session.add(Transaction("7248a706-29a8-478b-a674-c12ebf9a904a", "Withdrawal", 50, "06/05/2024", "Groceries", 3, "Aldi"))
|
||||||
|
session.add(Transaction("ba367c28-41e6-4f8a-9bfa-3819f7b89a58", "Withdrawal", 3, "06/05/2024", "Treats", 3, "ZooPlus"))
|
||||||
|
session.commit()
|
||||||
|
else:
|
||||||
|
print(f"The database is not empty, skipping sample data addition.")
|
||||||
|
else:
|
||||||
|
print(f"Sample data addition is disabled.")
|
||||||
249
manager.py
Normal file
249
manager.py
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
|
# Banking System Manager File
|
||||||
|
|
||||||
|
from class_client import Client
|
||||||
|
from class_account import Account
|
||||||
|
from class_transaction import Transaction
|
||||||
|
from flask import jsonify
|
||||||
|
import hashlib # hashlib for password hashing
|
||||||
|
import datetime # datetime for timestamps
|
||||||
|
import uuid # uuid for unique identifiers
|
||||||
|
|
||||||
|
|
||||||
|
from database import * # Importing the database connection
|
||||||
|
|
||||||
|
##############
|
||||||
|
### System ###
|
||||||
|
##############
|
||||||
|
|
||||||
|
def timestamp(): # Returns the current timestamp
|
||||||
|
return (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
||||||
|
|
||||||
|
def password_hash(password:str): # Converts a string to SHA512 hash
|
||||||
|
return hashlib.sha512(password.encode()).hexdigest()
|
||||||
|
|
||||||
|
def generate_uuid(): # Generates a unique identifier for transactions
|
||||||
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
|
def generate_uuid_short(): # Generates a short uuid
|
||||||
|
return str(uuid.uuid4())[:8]
|
||||||
|
|
||||||
|
##############
|
||||||
|
### Client ###
|
||||||
|
##############
|
||||||
|
|
||||||
|
def get_client(client_id:int): # Returns a specific client in the database
|
||||||
|
client = session.query(Client).filter_by(client_id=client_id).one_or_none()
|
||||||
|
if client is None:
|
||||||
|
return jsonify({"error": "Client not found"}), 404
|
||||||
|
if client is not None:
|
||||||
|
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
|
||||||
|
|
||||||
|
def change_password(client_id, password:str, new_password:str): # Changes the password of a client
|
||||||
|
old_hash = password_hash(password)
|
||||||
|
new_hash = password_hash(new_password)
|
||||||
|
for client in session.query(Client).all():
|
||||||
|
if client.client_id == client_id:
|
||||||
|
if client.hash == old_hash:
|
||||||
|
client.hash = new_hash
|
||||||
|
session.commit()
|
||||||
|
return "Password changed successfully.", 200
|
||||||
|
return "Incorrect old password.", 400
|
||||||
|
return f"client_id: {client_id} is not found.", 404
|
||||||
|
|
||||||
|
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, password_hash(password), notes, 1, 0, None)
|
||||||
|
session.add(new_client)
|
||||||
|
session.commit()
|
||||||
|
return f"New client has been added: name: {name}, uuid: {client_id} ", 200
|
||||||
|
|
||||||
|
def delete_client(client_id): # Deletes a client from the database
|
||||||
|
for client in session.query(Client).all():
|
||||||
|
if client.client_id == client_id:
|
||||||
|
if client.accounts == None:
|
||||||
|
session.delete(client)
|
||||||
|
session.commit()
|
||||||
|
return f"client_id: {client_id} has been removed.", 200
|
||||||
|
else:
|
||||||
|
return f"client_id: {client_id} has active accounts and can not be removed.", 400
|
||||||
|
return f"client_id: {client_id} is not found.", 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def login_user(email:str, password:str):
|
||||||
|
for client in session.query(Client).all():
|
||||||
|
if client.email == email and client.password == password:
|
||||||
|
return f"Welcome {client.name}."
|
||||||
|
return "Invalid email or password."
|
||||||
|
|
||||||
|
def logout_user():
|
||||||
|
return "You have been logged out."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update_client(client_id, name, birthdate, address, phone_number, email, notes):
|
||||||
|
for client in session.query(Client).all():
|
||||||
|
if client.client_id == client_id:
|
||||||
|
client.name = name
|
||||||
|
client.birthdate = birthdate
|
||||||
|
client.address = address
|
||||||
|
client.phone_number = phone_number
|
||||||
|
client.email = email
|
||||||
|
client.notes = notes
|
||||||
|
session.commit()
|
||||||
|
return f"client_id: {client_id} has been updated."
|
||||||
|
return f"Client ID: {client_id} is not found."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###############
|
||||||
|
### Account ###
|
||||||
|
###############
|
||||||
|
|
||||||
|
def get_account(account_id:int): # Returns a specific account in the database
|
||||||
|
account = session.query(Account).filter_by(account_id=account_id).one_or_none()
|
||||||
|
if account is None:
|
||||||
|
return jsonify({"error": "Account not found"}), 404
|
||||||
|
if account is not None:
|
||||||
|
for account in account:
|
||||||
|
return jsonify({"description": account.description, "account_type": account.account_type, "balance": account.balance, "enabled": account.enabled, "notes": account.notes}), 200
|
||||||
|
|
||||||
|
def add_account(description:str, account_type, **kwargs): # Adds a new account to the database
|
||||||
|
account_id = generate_uuid_short()
|
||||||
|
notes = kwargs.get("notes", None)
|
||||||
|
new_account = Account(account_id, description, timestamp(), account_type, 0, 1, notes, None)
|
||||||
|
session.add(new_account)
|
||||||
|
session.commit()
|
||||||
|
return f"New account has been added: description: {description}, uuid: {account_id} ", 200
|
||||||
|
|
||||||
|
def delete_account(account_id): # Deletes an account from the database
|
||||||
|
for account in session.query(Account).all():
|
||||||
|
if account.account_id == account_id:
|
||||||
|
if account.balance == 0:
|
||||||
|
session.delete(account)
|
||||||
|
session.commit()
|
||||||
|
return f"account_id: {account_id} has been removed.", 200
|
||||||
|
else:
|
||||||
|
return f"account_id: {account_id} has a balance and can not be removed.", 400
|
||||||
|
return f"account_id: {account_id} is not found.", 404
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update_account(account_id:int, update:dict):
|
||||||
|
for account in session.query(Account).all():
|
||||||
|
if account.account_id == account_id:
|
||||||
|
account.description = update["description"]
|
||||||
|
account.account_type = update["account_type"]
|
||||||
|
account.balance = update["balance"]
|
||||||
|
account.enabled = update["enabled"]
|
||||||
|
account.notes = update["notes"]
|
||||||
|
session.commit()
|
||||||
|
return f"account_id: {update['account_id']} has been updated."
|
||||||
|
return f"account_id: {update['account_id']} is not found."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
###################
|
||||||
|
### Transaction ###
|
||||||
|
###################
|
||||||
|
|
||||||
|
def get_transaction(transaction_id:int): # Returns a specific transaction in the database
|
||||||
|
transaction = session.query(Transaction).filter_by(transaction_id=transaction_id).one_or_none()
|
||||||
|
if transaction is None:
|
||||||
|
return jsonify({"error": "Transaction not found"}), 404
|
||||||
|
if transaction is not None:
|
||||||
|
return jsonify({"transaction_type": transaction.transaction_type, "amount": transaction.amount, "timestamp": transaction.timestamp, "description": transaction.description, "account_number": transaction.account_number, "recipient_account_number": transaction.recipient_account_number}), 200
|
||||||
|
|
||||||
|
def transaction_history(account_id:int): # Returns all transactions for a specific account
|
||||||
|
result = session.query(Transaction).filter(Transaction.account_number == account_id)
|
||||||
|
return jsonify([{"transaction_id": transaction.transaction_id, "transaction_type": transaction.transaction_type, "amount": transaction.amount, "timestamp": transaction.timestamp, "description": transaction.description, "account_number": transaction.account_number, "recipient_account_number": transaction.recipient_account_number} for transaction in result]), 200
|
||||||
|
|
||||||
|
def add_transaction(amount:int, account_from, account_to, **kwargs): # Adds a new transaction to the database
|
||||||
|
transaction_id = generate_uuid()
|
||||||
|
for account in session.query(Account).all():
|
||||||
|
if account.account_id == account_from:
|
||||||
|
if account.balance < amount:
|
||||||
|
return f"Account ID: {account_from} does not have enough funds to transfer {amount}.", 401
|
||||||
|
account.balance -= amount
|
||||||
|
transaction_type = "withdraw"
|
||||||
|
session.commit()
|
||||||
|
if account.account_id == account_to:
|
||||||
|
account.balance += amount
|
||||||
|
transaction_type = "transfer"
|
||||||
|
session.commit()
|
||||||
|
description = kwargs.get("description", None)
|
||||||
|
new_transaction = Transaction(transaction_id, transaction_type, amount, timestamp(), description, account_from, account_to)
|
||||||
|
session.add(new_transaction)
|
||||||
|
session.commit()
|
||||||
|
return f"New transaction has been added: description: {description}, uuid: {transaction_id} ", 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#####################
|
||||||
|
### Administrator ###
|
||||||
|
#####################
|
||||||
|
|
||||||
|
def get_all_clients(): # Returns all clients in the database
|
||||||
|
clients = session.query(Client).all()
|
||||||
|
return jsonify([{"client_id": client.client_id, "name": client.name, "birthdate": client.birthdate, "opening_timestamp": client.opening_timestamp, "address": client.address, "phone_number": client.phone_number, "email": client.email} for client in clients])
|
||||||
|
|
||||||
|
def get_all_accounts(): # Returns all accounts in the database
|
||||||
|
accounts = session.query(Account).all()
|
||||||
|
return jsonify([{"account_id": account.account_id, "description": account.description, "open_timestamp": account.open_timestamp, "account_type": account.account_type, "balance": account.balance, "enabled": account.enabled, "notes": account.notes} for account in accounts])
|
||||||
|
|
||||||
|
def get_all_transactions(): # Returns all transactions in the database
|
||||||
|
transactions = session.query(Transaction).all()
|
||||||
|
return jsonify([{"transaction_id": transaction.transaction_id, "transaction_type": transaction.transaction_type, "amount": transaction.amount, "timestamp": transaction.timestamp, "description": transaction.description, "account_number": transaction.account_number, "recipient_account_number": transaction.recipient_account_number} for transaction in transactions])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update_transaction(transaction_id, transaction_type, amount, description, account_number, recipient_account_number):
|
||||||
|
for transaction in session.query(Transaction).all():
|
||||||
|
if transaction.transaction_id == transaction_id:
|
||||||
|
transaction.transaction_type = transaction_type
|
||||||
|
transaction.amount = amount
|
||||||
|
transaction.description = description
|
||||||
|
transaction.account_number = account_number
|
||||||
|
transaction.recipient_account_number = recipient_account_number
|
||||||
|
session.commit()
|
||||||
|
return f"Transaction ID: {transaction_id} has been updated."
|
||||||
|
return f"Transaction ID: {transaction_id} is not found."
|
||||||
|
|
||||||
|
def apply_interest(account_id:int, interest_rate:float):
|
||||||
|
for account in session.query(Account).filter(Account.account_id == account_id):
|
||||||
|
if account.account_id == account_id:
|
||||||
|
account.balance += account.balance * interest_rate
|
||||||
|
session.commit()
|
||||||
|
return f"Interest has been applied to Account ID: {account_id}."
|
||||||
|
return f"Account ID: {account_id} is not found."
|
||||||
|
|
||||||
|
def apply_fee(account_id:int, fee:float):
|
||||||
|
for account in session.query(Account).all():
|
||||||
|
if account.account_id == account_id:
|
||||||
|
account.balance -= fee
|
||||||
|
session.commit()
|
||||||
|
return f"Fee has been applied to Account ID: {account_id}."
|
||||||
|
return f"Account ID: {account_id} is not found."
|
||||||
|
|
||||||
|
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."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
flask
|
||||||
|
connexion[swagger-ui]==2.14.2
|
||||||
|
requests
|
||||||
|
sqlalchemy
|
||||||
Reference in New Issue
Block a user