This commit is contained in:
NikolajDanger
2022-05-17 10:26:15 +02:00
commit 9fb3452341
29 changed files with 1439 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.DS_Store
__pycache__/

101
README.md Normal file
View File

@ -0,0 +1,101 @@
# April 24, 2019 - MAY 1ST, 2019 DEVELOPMENT SPRINT
Reviewing the prioritized user stories. User stories to be picked.
Our two target dates are: monday April 29th (choose not to meet if github works; stand by ) and Wednesday May 1st, when we meet for acceptance test.
We consider this a sprint started. Lets be modest and see if we can get some done. In a normal workplace situation no user story should for example not take more that 20 hours.
## Rules:
To pick: Add your name. Pick one at the time, (pick only several when you break the rule)
Update progress.
Finalize one at the time.
Commit to repository.
## User stories:
### Customer role:
CUS-1: finished (ziming, 100%); CUS1: As a customer, I can log in and log out of the system, so that my information in the bank is only accessible to me.
Suspend authentication for other parts of the application (YES / NO ) - No action - defered.
CUS7(SPLIT): As a customer, I can transfer money from one of my accounts to another, so that I can make other operations with that money.
CUS7-1 (ziming, 100%): HTML finished version one; SPLIT; update not confirmed; ;
CUS7-3 (ziming, 100%): confirm update;
CUS7-2 (ziming+anders,100%): confirm dropdown;
CUS7-4 (anders, 100%, left): ER to relational part. deposit, transfer, withdraw;
CUS7-5 (anders+, 10%): must be logged in as employee part
CUS7-6 (name, ): restrict from_accounts to employees manages accounts
CUS4(SPLIT): As a customer, I can see the consolidated summary of my investments at a given date, so that I can see how much money I have invested and the current value of these investments. SPLIT current date (CUS4-1; date part (CUS4-2)
CUS4-1(anders, 60%): investment list; list of each and a total; one line for each investment account; at a given date; accounts.html with overview just start (5%); SPLIT; consolidate up to and including dags dato-current date.; ; SPLIT model part (CUS4-4).
CUS4-4(anders, 70%); model part of CUS4-1
CUS4-2(name); date part; consolidated view at point in time.
CUS4-3(anders, 100%, left): ER to relational part. certificates_of_deposit, investmentaccounts;
### Employee role:
EUS-CUS10 ((moved,SPLIT), 0%): Move to employee as it is a employee/counter utility; Employee must chose the customer; CUS10: As a customer, I can deposit money to my checking account, so that I can have it in a safe place at the bank.-> EUS-CUS10 : As an employee, I can recieve money for deposit to a customer account, so that the customer can have it in a safe place at the bank.
EUS-CUS10-1: CUS10 moved to employee; status 0% but CUS7 can be used as start.
EUS-CUS10-2(name): Authentication part
EUS-CUS10-3(anders, 100%, left): ER to relational part.
EUS1(lasse, 100%) EUS1 is very similar to CUS1. 60% finished even though it is not started. EUS1: As a bank employee, I can log in and log out of the system, so that I can perform operations on behalf of customers securely.
EUS1-2: (anders, 100%) ER to relational part. created table manages with account_type field. Need to fix manages
EUS3 (complex, SPLIT): Complex story. SPLIT, only employees should have acces to this story). EUS3: As a bank employee, I can add or delete customers and their accounts in the system, so that I can keep track of the my customers and the bank products they are using.
EUS3-1 (ziming, 100%) register page as is implements adding a customer
EUS3-2 (name) add and remove money accounts for customers
EUS3-3 (name) un-register page implements deleting a customer along with the accounts
EUS3-4 (name) authentication against employee of EUS3.
EUS3-5 (anders, 100%) ER to relational part.
EUS6 (name): As a bank employee, I can create a new CD for one of my customers and associate it to the customer's investment account, so that I can facilitate investments and attract money to the bank.
EUS6-2 (anders, 100%) ER to relational part.
### Tasks:
MVC1-1 (ziming, 100%) Move SQL
MVC1-2 (name, ) navigation
CM-1 (name, ) adjusting technical debt
## Requirements:
Run the code below to install the necessary modules.
>$ pip install -r requirements.txt
## Database init
1. set the database in __init__.py file.
2. run schema.sql, schema_ins.sql in your database.

49
bank/Customer/routes.py Normal file
View File

@ -0,0 +1,49 @@
from flask import render_template, url_for, flash, redirect, request, Blueprint
from bank import app, conn, bcrypt
from bank.forms import DepositForm, InvestForm
from flask_login import current_user
from bank.models import CheckingAccount, InvestmentAccount, update_CheckingAccount
from bank.models import select_investments_with_certificates, select_investments, select_investments_certificates_sum
import sys, datetime
Customer = Blueprint('Customer', __name__)
@Customer.route("/invest", methods=['GET', 'POST'])
def invest():
if not current_user.is_authenticated:
flash('Please Login.','danger')
return redirect(url_for('Login.login'))
#form = InvestForm()
investments = select_investments(current_user.get_id())
investment_certificates = select_investments_with_certificates(current_user.get_id())
investment_sums = select_investments_certificates_sum(current_user.get_id())
return render_template('invest.html', title='Investments', inv=investments, inv_cd_list=investment_certificates
, inv_sums=investment_sums)
@Customer.route("/deposit", methods=['GET', 'POST'])
def deposit():
if not current_user.is_authenticated:
flash('Please Login.','danger')
return redirect(url_for('Login.login'))
form = DepositForm()
if form.validate_on_submit():
amount=form.amount.data
CPR_number = form.CPR_number.data
update_CheckingAccount(amount, CPR_number)
flash('Succeed!', 'success')
return redirect(url_for('Login.home'))
return render_template('deposit.html', title='Deposit', form=form)
@Customer.route("/summary", methods=['GET', 'POST'])
def summary():
if not current_user.is_authenticated:
flash('Please Login.','danger')
return redirect(url_for('Login.login'))
if form.validate_on_submit():
pass
flash('Succeed!', 'success')
return redirect(url_for('Login.home'))
return render_template('deposit.html', title='Deposit', form=form)

71
bank/Employee/routes.py Normal file
View File

@ -0,0 +1,71 @@
from flask import render_template, url_for, flash, redirect, request, Blueprint
from bank import app, conn, bcrypt
from bank.forms import TransferForm, DepositForm, AddCustomerForm
from flask_login import current_user
from bank.models import Transfers, CheckingAccount, InvestmentAccount, select_emp_cus_accounts, transfer_account, insert_Customers
import sys, datetime
Employee = Blueprint('Employee', __name__)
@Employee.route("/addcustomer", methods=['GET', 'POST'])
def addcustomer():
#if current_user.is_authenticated:
# return redirect(url_for('Login.home'))
form = AddCustomerForm()
if form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
name=form.username.data
CPR_number=form.CPR_number.data
password=hashed_password
insert_Customers(name, CPR_number, password)
flash('Account has been created! The customer is now able to log in', 'success')
return redirect(url_for('Login.home'))
return render_template('addcustomer.html', title='Add Customer', form=form)
@Employee.route("/manageCustomer", methods=['GET', 'POST'])
def manageCustomer():
if not current_user.is_authenticated:
flash('Please Login.','danger')
return redirect(url_for('Login.login'))
form = TransferForm()
if form.validate_on_submit():
amount=form.amount.data
cur = conn.cursor()
sql = """
UPDATE CheckingAccount
SET amount = %s
WHERE CPR_number = %s
"""
cur.execute(sql, (amount, CPR_number))
conn.commit()
cur.close()
flash('Transfer succeed!', 'success')
return redirect(url_for('Login.home'))
return render_template('transfer.html', title='Transfer', form=form)
@Employee.route("/transfer", methods=['GET', 'POST'])
def transfer():
if not current_user.is_authenticated:
flash('Please Login.','danger')
return redirect(url_for('Login.login'))
CPR_number = current_user.get_id()
print(CPR_number)
dropdown_accounts = select_emp_cus_accounts(current_user.get_id())
drp_accounts = []
for drp in dropdown_accounts:
drp_accounts.append((drp[3], drp[1]+' '+str(drp[3])))
print(drp_accounts)
form = TransferForm()
form.sourceAccount.choices = drp_accounts
form.targetAccount.choices = drp_accounts
if form.validate_on_submit():
date = datetime.date.today()
amount = form.amount.data
from_account = form.sourceAccount.data
to_account = form.targetAccount.data
transfer_account(date, amount, from_account, to_account)
flash('Transfer succeed!', 'success')
return redirect(url_for('Login.home'))
return render_template('transfer.html', title='Transfer', drop_cus_acc=dropdown_accounts, form=form)

52
bank/Login/routes.py Normal file
View File

@ -0,0 +1,52 @@
from flask import render_template, url_for, flash, redirect, request, Blueprint
from bank import app, conn, bcrypt
from bank.forms import CustomerLoginForm, EmployeeLoginForm
from flask_login import login_user, current_user, logout_user, login_required
from bank.models import Customers, select_Customers, select_Employees
Login = Blueprint('Login', __name__)
posts = [{}]
@Login.route("/")
@Login.route("/home")
def home():
return render_template('home.html', posts=posts)
@Login.route("/about")
def about():
return render_template('about.html', title='About')
@Login.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('Login.home'))
is_employee = True if request.args.get('is_employee') == 'true' else False
form = EmployeeLoginForm() if is_employee else CustomerLoginForm()
# Først bekræft, at inputtet fra formen er gyldigt... (f.eks. ikke tomt)
if form.validate_on_submit():
user = select_Employees(form.id.data) if is_employee else select_Customers(form.id.data)
# Derefter tjek om hashet af adgangskoden passer med det fra databasen...
if user != None and bcrypt.check_password_hash(user[2], form.password.data):
login_user(user, remember=form.remember.data)
flash('Login successful.','success')
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('Login.home'))
else:
flash('Login Unsuccessful. Please check identifier and password', 'danger')
return render_template('login.html', title='Login', is_employee=is_employee, form=form)
@Login.route("/logout")
def logout():
logout_user()
return redirect(url_for('Login.home'))
@Login.route("/account")
@login_required
def account():
return render_template('account.html', title='Account')

24
bank/__init__.py Normal file
View File

@ -0,0 +1,24 @@
from flask import Flask
import psycopg2
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
app = Flask(__name__)
app.config['SECRET_KEY'] = 'fc089b9218301ad987914c53481bff04'
# set your own database
db = "dbname='bank' user='postgres' host='127.0.0.1' password = 'UIS'"
conn = psycopg2.connect(db)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
from bank.Login.routes import Login
from bank.Customer.routes import Customer
from bank.Employee.routes import Employee
app.register_blueprint(Login)
app.register_blueprint(Customer)
app.register_blueprint(Employee)
#from bank import routes

39
bank/forms.py Normal file
View File

@ -0,0 +1,39 @@
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField, IntegerField, SelectField
from wtforms.validators import DataRequired, Length, EqualTo, ValidationError
class AddCustomerForm(FlaskForm):
username = StringField('Username',
validators=[DataRequired(), Length(min=2, max=20)])
CPR_number = IntegerField('CPR_number',
validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Add')
class CustomerLoginForm(FlaskForm):
id = IntegerField('CPR_number', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Remember Me')
submit = SubmitField('Login')
class EmployeeLoginForm(FlaskForm):
id = IntegerField('Id', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Remember Me')
submit = SubmitField('Login')
class TransferForm(FlaskForm):
amount = IntegerField('amount',
validators=[DataRequired()])
#sourceAccountTest = SelectField('From Account test:', choices=dropdown_choices, validators=[DataRequired()])
sourceAccount = SelectField('From Account:' , choices=[], coerce = int, validators=[DataRequired()])
targetAccount = SelectField('Target Account:', choices=[], coerce = int, validators=[DataRequired()])
submit = SubmitField('Confirm')
class DepositForm(FlaskForm):
amount = IntegerField('amount',
validators=[DataRequired()])
submit = SubmitField('Confirm')
class InvestForm(FlaskForm):
submit = SubmitField('Confirm')

193
bank/models.py Normal file
View File

@ -0,0 +1,193 @@
# write all your SQL queries in this file.
from datetime import datetime
from bank import conn, login_manager
from flask_login import UserMixin
from psycopg2 import sql
@login_manager.user_loader
def load_user(user_id):
cur = conn.cursor()
schema = 'customers'
id = 'cpr_number'
if str(user_id).startswith('60'):
schema = 'employees'
id = 'id'
user_sql = sql.SQL("""
SELECT * FROM {}
WHERE {} = %s
""").format(sql.Identifier(schema), sql.Identifier(id))
cur.execute(user_sql, (int(user_id),))
if cur.rowcount > 0:
# return-if svarer til nedenstående:
# if schema == 'employees':
# return Employees(cur.fetchone())
# else:
# return Customers(cur.fetchone())
return Employees(cur.fetchone()) if schema == 'employees' else Customers(cur.fetchone())
else:
return None
class Customers(tuple, UserMixin):
def __init__(self, user_data):
self.CPR_number = user_data[0]
self.risktype = False
self.password = user_data[2]
self.name = user_data[3]
self.address = user_data[4]
def get_id(self):
return (self.CPR_number)
class Employees(tuple, UserMixin):
def __init__(self, employee_data):
self.id = employee_data[0]
self.name = employee_data[1]
self.password = employee_data[2]
def get_id(self):
return (self.id)
class CheckingAccount(tuple):
def __init__(self, user_data):
self.id = user_data[0]
self.create_date = user_data[1]
self.CPR_number = user_data[2]
self.amount = 0
class InvestmentAccount(tuple):
def __init__(self, user_data):
self.id = user_data[0]
self.start_date = user_data[1]
self.maturity_date = user_data[2]
self.amount = 0
class Transfers(tuple):
def __init__(self, user_data):
self.id = user_data[0]
self.amount = user_data[1]
self.transfer_date = user_data[2]
def insert_Customers(name, CPR_number, password):
cur = conn.cursor()
sql = """
INSERT INTO Customers(name, CPR_number, password)
VALUES (%s, %s, %s)
"""
cur.execute(sql, (name, CPR_number, password))
# Husk commit() for INSERT og UPDATE, men ikke til SELECT!
conn.commit()
cur.close()
def select_Customers(CPR_number):
cur = conn.cursor()
sql = """
SELECT * FROM Customers
WHERE CPR_number = %s
"""
cur.execute(sql, (CPR_number,))
user = Customers(cur.fetchone()) if cur.rowcount > 0 else None;
cur.close()
return user
def select_Employees(id):
cur = conn.cursor()
sql = """
SELECT * FROM Employees
WHERE id = %s
"""
cur.execute(sql, (id,))
user = Employees(cur.fetchone()) if cur.rowcount > 0 else None;
cur.close()
return user
def update_CheckingAccount(amount, CPR_number):
cur = conn.cursor()
sql = """
UPDATE CheckingAccount
SET amount = %s
WHERE CPR_number = %s
"""
cur.execute(sql, (amount, CPR_number))
# Husk commit() for INSERT og UPDATE, men ikke til SELECT!
conn.commit()
cur.close()
def transfer_account(date, amount, from_account, to_account):
cur = conn.cursor()
sql = """
INSERT INTO Transfers(transfer_date, amount, from_account, to_account)
VALUES (%s, %s, %s, %s)
"""
cur.execute(sql, (date, amount, from_account, to_account))
# Husk commit() for INSERT og UPDATE, men ikke til SELECT!
conn.commit()
cur.close()
def select_emp_cus_accounts(emp_cpr_number):
cur = conn.cursor()
sql = """
SELECT
e.name employee
, c.name customer
, cpr_number
, account_number
FROM manages m
NATURAL JOIN accounts
NATURAL JOIN customers c
JOIN employees e ON m.emp_cpr_number = e.id
WHERE emp_cpr_number = %s
;
"""
cur.execute(sql, (emp_cpr_number,))
tuple_resultset = cur.fetchall()
cur.close()
return tuple_resultset
def select_investments(emp_cpr_number):
cur = conn.cursor()
sql = """
SELECT i.account_number, a.cpr_number, a.created_date
FROM investmentaccounts i
JOIN accounts a ON i.account_number = a.account_number
JOIN manages m ON m.account_number = a.account_number
JOIN employees e ON e.id = m.emp_cpr_number
WHERE e.id = %s
"""
cur.execute(sql, (emp_cpr_number,))
tuple_resultset = cur.fetchall()
cur.close()
return tuple_resultset
def select_investments_with_certificates(emp_cpr_number):
cur = conn.cursor()
sql = """
SELECT i.account_number, a.cpr_number, a.created_date
, cd.cd_number, start_date, maturity_date, rate, amount
FROM investmentaccounts i
JOIN accounts a ON i.account_number = a.account_number
JOIN certificates_of_deposit cd ON i.account_number = cd.account_number
JOIN manages m ON m.account_number = a.account_number
JOIN employees e ON e.id = m.emp_cpr_number
WHERE e.id = %s
"""
cur.execute(sql, (emp_cpr_number,))
tuple_resultset = cur.fetchall()
cur.close()
return tuple_resultset
def select_investments_certificates_sum(emp_cpr_number):
cur = conn.cursor()
sql = """
SELECT account_number, cpr_number, created_date, sum
FROM vw_cd_sum
WHERE emp_cpr_number = %s
"""
cur.execute(sql, (emp_cpr_number,))
tuple_resultset = cur.fetchall()
cur.close()
return tuple_resultset

101
bank/schema.sql Normal file
View File

@ -0,0 +1,101 @@
\i schema_drop.sql
CREATE TABLE IF NOT EXISTS Customers(
CPR_number integer PRIMARY KEY,
risk_type boolean default False,
password varchar(120),
name varchar(60),
address text
);
CREATE TABLE IF NOT EXISTS Employees(
id integer PRIMARY KEY,
name varchar(20),
password varchar(120)
);
-- Solving the accounts ISA Hierachy.
-- (-)relational style. In this case every entity is implemented
-- -objects atyle. In this case only typed objects. Implement a type on manages
-- -nulls style. In this case only accounts
-- Serial this is the account number across the system
--
CREATE TABLE IF NOT EXISTS Accounts(
account_number SERIAL PRIMARY KEY,
created_date date,
CPR_number integer REFERENCES Customers(CPR_number)
);
CREATE TABLE IF NOT EXISTS manages(
emp_cpr_number INTEGER NOT NULL REFERENCES employees(id),
account_number INTEGER NOT NULL REFERENCES accounts
);
ALTER TABLE manages ADD CONSTRAINT pk_manages
PRIMARY KEY (emp_cpr_number, account_number)
;
CREATE TABLE IF NOT EXISTS CheckingAccounts(
account_number INTEGER PRIMARY KEY
);
ALTER TABLE CheckingAccounts ADD CONSTRAINT fk_ChAcc_001
FOREIGN KEY (account_number) REFERENCES Accounts(account_number)
;
CREATE TABLE IF NOT EXISTS InvestmentAccounts(
account_number SERIAL PRIMARY KEY
);
ALTER TABLE InvestmentAccounts ADD CONSTRAINT fk_InAcc_001
FOREIGN KEY (account_number) REFERENCES Accounts(account_number)
;
-- transfers
CREATE TABLE IF NOT EXISTS Transfers(
id SERIAL PRIMARY KEY,
transfer_date date,
amount INTEGER,
from_account INTEGER REFERENCES accounts(account_number),
to_account INTEGER REFERENCES accounts(account_number)
);
COMMENT ON COLUMN Transfers.from_account IS 'has origin';
COMMENT ON COLUMN Transfers.to_account IS 'has destination';
-- checking accounts
CREATE TABLE IF NOT EXISTS Withdraws(
id SERIAL PRIMARY KEY,
account_number INTEGER REFERENCES CheckingAccounts(account_number),
amount integer,
withdraw_date date
);
CREATE TABLE IF NOT EXISTS Deposits(
id SERIAL PRIMARY KEY,
account_number INTEGER REFERENCES CheckingAccounts(account_number),
amount integer,
deposit_date date
);
-- investments
-- Solving the certificate ISA Hierachy.
-- -relational style. In this case every entity is implemented
-- -objects atyle. In this case only typed objects.
-- (-)nulls style. In this case only one certificate entity set
CREATE TABLE IF NOT EXISTS Certificates_of_deposit(
cd_number SERIAL PRIMARY KEY,
account_number INTEGER REFERENCES InvestmentAccounts(account_number),
start_date date,
amount integer,
maturity_date date,
rate integer --at fixed rate certificated´s of deposite
);
COMMENT ON COLUMN Certificates_of_deposit.rate IS 'at fixed rate certificated´s of deposite';
\i sql_ddl/vw_cd_sum.sql
\i sql_ddl/vw_invest_accounts.sql
\i sql_ddl/vw_invest_certificates.sql
\i sql_ddl/vw_tdw.sql

21
bank/schema_drop.sql Normal file
View File

@ -0,0 +1,21 @@
--DROP VIEW IF EXISTS vw_tdw;
--DROP VIEW IF EXISTS ww_invest_certificates;
--DROP VIEW IF EXISTS vw_invest_accounts;
DROP VIEW IF EXISTS vw_cd_sum;
--
DROP TABLE IF EXISTS Withdraws;
DROP TABLE IF EXISTS Deposits;
-- ROLLBACK; commit;
DROP TABLE IF EXISTS CheckingAccounts;
DROP TABLE IF EXISTS Certificates_of_deposit;
--
DROP TABLE IF EXISTS Transfers;
DROP TABLE IF EXISTS InvestmentAccounts;
DROP TABLE IF EXISTS Manages;
--
DROP TABLE IF EXISTS Accounts;
--
DROP TABLE IF EXISTS Employees;
DROP TABLE IF EXISTS Customers;

109
bank/schema_ins.sql Normal file
View File

@ -0,0 +1,109 @@
DELETE FROM deposits;
DELETE FROM withdraws;
DELETE FROM checkingaccounts;
DELETE FROM certificates_of_deposit;
--
DELETE FROM InvestmentAccounts;
DELETE FROM CheckingAccounts;
DELETE FROM manages;
DELETE FROM transfers;
--
DELETE FROM accounts;
DELETE FROM employees;
DELETE FROM customers;
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5000, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-DB3-C-Lasse', 'aud Auditorium A, bygning 1, 1. sal Universitetsparken 15 (Zoo)');
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5001, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-PD3-C-Anders', 'øv* Kursussal 1, bygning 3, 1.sal Universitetsparken 15 (Zoo)');
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5002, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-DB2-C-Ziming', 'øv 4032, Ole Maaløes Vej 5 (Biocenter)');
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5003, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-PD2-C-Hubert', 'øv Auditorium Syd, Nørre Alle 51');
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5004, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-DB1-C-Jan', 'øv A112, Universitetsparken 5, HCØ');
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5005, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-PD1-C-Marco', 'Aud 07, Universitetsparken 5, HCØ');
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5006, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-LE1-C-Marcos', 'AUD 02 in the HCØ building (HCØ, Universitetsparken 5)');
INSERT INTO public.customers(cpr_number, risk_type, password, name, address) VALUES (5007, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-LE2-C-Finn', 'AUD 02 in the HCØ building (HCØ, Universitetsparken 5)');
INSERT INTO public.Employees(id, name, password)
VALUES (6000, 'UIS-DB3-E-Lasse', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx')
, (6001, 'UIS-PD3-E-Anders', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6002, 'UIS-DB2-E-Ziming', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6003, 'UIS-PD2-E-Hubert', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6004, 'UIS-DB1-E-Jan' , '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6005, 'UIS-PD1-E-Marco' , '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6006, 'UIS-LE1-E-Marcos', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6007, 'UIS-LE2-E-Finn' , '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
;
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8000, '2018-06-01',5000);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8001, '2018-07-01',5000);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8002, '2018-08-01',5001);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8003, '2018-09-01',5001);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8004, '2018-10-01',5002);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8005, '2018-11-01',5002);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8006, '2018-12-01',5003);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8007, '2018-02-01',5003);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8008, '2018-03-01',5004);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8009, '2018-04-01',5004);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8010, '2018-05-01',5005);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8011, '2018-06-01',5005);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8012, '2018-07-01',5006);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8013, '2018-08-01',5006);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8014, '2018-09-01',5007);
INSERT INTO public.accounts(account_number, created_date, cpr_number) VALUES (8015, '2018-10-01',5007);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6000, 8000);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6000, 8001);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6001, 8002);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6001, 8003);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6002, 8004);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6002, 8005);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6003, 8006);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6003, 8007);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6004, 8008);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6004, 8009);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6005, 8010);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6005, 8011);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6006, 8012);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6006, 8013);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6007, 8014);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6007, 8015);
INSERT INTO checkingaccounts(account_number)
VALUES (8000),(8001),(8002),(8003),(8004),(8005),(8006),(8007);
INSERT INTO InvestmentAccounts(account_number)
VALUES (8008),(8009),(8010),(8011),(8012),(8013),(8014),(8015);
-- contraints missing on transfers
INSERT INTO transfers (transfer_date, amount, from_account, to_account) VALUES (now(), 10, 8000, 8001);
INSERT INTO transfers (transfer_date, amount, from_account, to_account) VALUES (now(), 20, 8009, 8008);
INSERT INTO transfers (transfer_date, amount, from_account, to_account) VALUES (now(), 40, 8005, 8006);
INSERT INTO transfers (transfer_date, amount, from_account, to_account) VALUES (now(), 80, 8003, 8011);
INSERT INTO transfers (transfer_date, amount, from_account, to_account) VALUES (now(), 160, 8002, 8003);
INSERT INTO transfers (transfer_date, amount, from_account, to_account) VALUES (now(), 320, 8004, 8012);
-- contraints missing on withdraws
INSERT INTO withdraws ( amount, withdraw_date) VALUES (20480, now())
, (10240, now()), (5120, now()), (2560, now()), (1280, now()), (640, now());
-- contraints missing on deposits
INSERT INTO deposits ( amount, deposit_date) VALUES (40960, now())
, (81920, now()), (163840, now()), (327696, now()), (655392, now()), (1310784, now());
-- new certificate
INSERT INTO public.certificates_of_deposit(start_date, amount, maturity_date,account_number) VALUES (now(), 10000, now(), 8014);
INSERT INTO public.certificates_of_deposit(start_date, amount, maturity_date,account_number) VALUES (now(), 20000, now(), 8014);
INSERT INTO public.certificates_of_deposit(start_date, amount, maturity_date,account_number) VALUES (now(), 40000, now(), 8014);
INSERT INTO public.certificates_of_deposit(start_date, amount, maturity_date,account_number) VALUES (now(), 1000, now(), 8014);
INSERT INTO public.certificates_of_deposit(start_date, amount, maturity_date,account_number) VALUES (now(), 2000, now(), 8014);
-- cd_number given
INSERT INTO public.certificates_of_deposit(cd_number, start_date, amount, maturity_date,account_number) VALUES (7000, now(), 10000, now(),8015);
-- new certificate fixed rate 4 percent
INSERT INTO public.certificates_of_deposit(start_date, amount, maturity_date,account_number, rate) VALUES (now(), 10000, now(), 8013, 4);
-- cd_number given fixed rate 5 percent
INSERT INTO public.certificates_of_deposit(cd_number, start_date, amount, maturity_date,account_number, rate) VALUES (7001, now(), 10000, now(),8012, 5);

58
bank/schema_upd.sql Normal file
View File

@ -0,0 +1,58 @@
INSERT INTO public.customers(cpr_number, risk_type, password, name, address)
VALUES (5008, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-PD1-C-Rikke', 'AUD 08, Universitetsparken 5, HCØ')
, (5009, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-DB1-C-Pax' , 'AUD 05, Universitetsparken 5, HCØ')
, (5010, TRUE, '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'UIS-PD2-C-Nadja', 'AUD 08, Universitetsparken 5, HCØ')
;
UPDATE public.customers SET address = 'AUD 08, Universitetsparken 5, HCØ' WHERE cpr_number IN (5001);
UPDATE public.customers SET address = 'aud - Lille UP1 - 04-1-22, Universitetsparken 1-3, DIKU' WHERE cpr_number IN (5003, 5007);
UPDATE public.customers SET address = 'online-zoom' WHERE cpr_number IN (5006);
UPDATE public.customers SET name = 'UIS-DB2-C-Anders' WHERE cpr_number IN (5008);
UPDATE public.customers SET name = 'UIS-LE-C-Hubert' WHERE cpr_number IN (5003);
INSERT INTO public.Employees(id, name, password)
VALUES (6008, 'UIS-PD3-E-Rikke', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6009, 'UIS-DB2-E-Pax' , '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
, (6010, 'UIS-PD2-E-Nadja', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO')
;
INSERT INTO public.accounts(account_number, created_date, cpr_number)
VALUES (8016, '2018-06-01',5008), (8017, '2018-06-01',5008), (8018, '2018-06-01',5008)
, (8019, '2018-06-01',5009), (8020, '2018-06-01',5009), (8021, '2018-06-01',5009)
, (8022, '2018-06-01',5010), (8023, '2018-06-01',5010), (8024, '2018-06-01',5010)
;
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6008, 8010), (6008, 8011), (6008, 8016), (6008, 8017), (6008, 8018);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6009, 8012), (6009, 8013), (6009, 8019), (6009, 8020), (6009, 8021);
INSERT INTO public.manages(emp_cpr_number, account_number) VALUES (6010, 8014), (6010, 8015), (6010, 8022), (6010, 8023), (6010, 8024);
INSERT INTO deposits (account_number, amount, deposit_date)
VALUES (8000, 40960, now()), (8001, 81920, now()), (8002, 163840, now()), (8003, 327696, now()), (8004, 655392, now()), (8005, 1310784, now()), (8006, 16394, now()), (8007, 3154, now())
, (8000, 40960, now()), (8001, 81920, now()), (8002, 163840, now()), (8003, 327696, now()), (8004, 655392, now()), (8005, 1310784, now()), (8006, 16394, now()), (8007, 3154, now())
, (8000, 40960, now()), (8001, 81920, now()), (8002, 163840, now()), (8003, 327696, now()), (8004, 655392, now()), (8005, 1310784, now()), (8006, 16394, now()), (8007, 3154, now())
;
INSERT INTO withdraws (account_number, amount, withdraw_date)
VALUES (8000, 40960, now()), (8001, 81920, now()), (8002, 163840, now()), (8003, 327696, now()), (8004, 655392, now()), (8005, 1310784, now()), (8006, 16394, now()), (8007, 3154, now())
, (8000, 40960, now()), (8001, 81920, now()), (8002, 163840, now()), (8003, 327696, now()), (8004, 655392, now()), (8005, 1310784, now()), (8006, 16394, now()), (8007, 3154, now())
, (8000, 40960, now()), (8001, 81920, now()), (8002, 163840, now()), (8003, 327696, now()), (8004, 655392, now()), (8005, 1310784, now()), (8006, 16394, now()), (8007, 3154, now())
;
INSERT INTO transfers (transfer_date, amount, from_account, to_account)
VALUES (now(), 5000, 8000, 8016), (now(), 5000, 8001, 8017), (now(), 5000, 8002, 8018), (now(), 5000, 8003, 8019), (now(), 5000, 8004, 8020), (now(), 5000, 8005, 8021), (now(), 5000, 8006, 8022), (now(), 5000, 8007, 8023)
;
INSERT INTO investmentaccounts (account_number)
VALUES (8016), (8019), (8022)
;

BIN
bank/site.db Normal file

Binary file not shown.

View File

@ -0,0 +1,10 @@
CREATE OR REPLACE VIEW vw_cd_sum
AS
SELECT m.emp_cpr_number, i.account_number, a.cpr_number, a.created_date
, sum (amount)
FROM investmentaccounts i
JOIN accounts a ON i.account_number = a.account_number
JOIN certificates_of_deposit cd ON i.account_number = cd.account_number
JOIN manages m ON m.account_number = a.account_number
JOIN employees e ON e.id = m.emp_cpr_number
GROUP BY m.emp_cpr_number, i.account_number, a.cpr_number, a.created_date;

View File

@ -0,0 +1,5 @@
CREATE OR REPLACE VIEW vw_invest_accounts
AS
SELECT i.account_number, a.cpr_number, a.created_date
FROM investmentaccounts i
JOIN accounts a ON i.account_number = a.account_number ;

View File

@ -0,0 +1,7 @@
CREATE OR REPLACE VIEW vw_invest_certificates
AS
SELECT i.account_number, a.cpr_number, a.created_date
, cd.cd_number, start_date, maturity_date, rate, amount
FROM investmentaccounts i
JOIN accounts a ON i.account_number = a.account_number
JOIN certificates_of_deposit cd ON i.account_number = cd.account_number ;

8
bank/sql_ddl/vw_tdw.sql Normal file
View File

@ -0,0 +1,8 @@
CREATE OR REPLACE VIEW vw_tdw
AS
SELECT 'T', transfer_date, amount FROM transfers
UNION
SELECT 'D', deposit_date, amount FROM deposits
UNION
SELECT 'W', withdraw_date, amount FROM withdraws
;

88
bank/static/main.css Normal file
View File

@ -0,0 +1,88 @@
body {
background: #fafafa;
color: #333333;
margin-top: 5rem;
}
h1, h2, h3, h4, h5, h6 {
color: #444444;
}
.bg-steel {
background-color: #5f788a;
}
.site-header .navbar-nav .nav-link {
color: #cbd5db;
}
.site-header .navbar-nav .nav-link:hover {
color: #ffffff;
}
.site-header .navbar-nav .nav-link.active {
font-weight: 500;
}
.site-header .dropdown-menu > li > .nav-item.nav-link {
color: #495057;
}
.site-header .dropdown-menu > li > .nav-item.nav-link:hover {
color: #798592;
}
.content-section {
background: #ffffff;
padding: 10px 20px;
border: 1px solid #dddddd;
border-radius: 3px;
margin-bottom: 20px;
}
.article-title {
color: #444444;
}
a.article-title:hover {
color: #428bca;
text-decoration: none;
}
.article-content {
white-space: pre-line;
}
.article-img {
height: 65px;
width: 65px;
margin-right: 16px;
}
.article-metadata {
padding-bottom: 1px;
margin-bottom: 4px;
border-bottom: 1px solid #e3e3e3
}
.article-metadata a:hover {
color: #333;
text-decoration: none;
}
.article-svg {
width: 25px;
height: 25px;
vertical-align: middle;
}
.account-img {
height: 125px;
width: 125px;
margin-right: 20px;
margin-bottom: 16px;
}
.account-heading {
font-size: 2.5rem;
}

30
bank/templates/about.html Normal file
View File

@ -0,0 +1,30 @@
{% extends "layout.html" %}
{% block content %}
<h1>About Page</h1>
<p>Dette er UIS-prototypen bragt til dig af UIS-holdet 2021/2022:</p>
<ul>
<li style="color: gray;">Ziming Lou</li>
<li style="color: gray;">Lasse Pedersen</li>
<li style="color: gray;">Jan Rolandsen</li>
<li style="color: gray;">Marco Ugo Gambetta</li>
<li>Hubert Dariusz Zajac</li>
<li>Anders Lassen</li>
<li>Finn Kensing</li>
<li>Marcos Vas Salles</li>
<li>Pax Ravn</li>
<li>Nadja Petersen</li>
<li>Rikke Vesterbæk Nielsen</li>
</ul>
<p>I kan registrere nye kundekonti, men medarbejderkonti skal indtastes ved at foretage jeres ændringer i DML-scriptet schema_ins.sql. For at logge ind har vi oprettet nogle testkonti. Kunde-login kan tilgås ved hjælp af et kunde-cpr i intervallerne 5001 til 5007 med adgangskoden "UIS" med store bogstaver. Medarbejder-login kan tilgås ved hjælp af medarbejder-id 6001..6007 og samme adgangskode.</p>
<p>For at tilføje flere eksempeldata skal du foretage dine ændringer i DML-scriptet schema_ins.sql.</p>
<p>Prototypen er vertikal. Vi har implementeret nogle funktioner, men projektet er ufuldstændigt. Prototypen giver et udgangspunkt for jeres arbejde.</p>
<p><b>EN:</b></p>
<p>You can register new customer accounts, but employee accounts must be entered by making your changes to the DML-script schema_ins.sql. To log in we have created some test accounts. The customer login can be accesed using a customer cpr in ranges 5001 to 5007 with the password 'UIS' in uppercase. The employee login can be accessed using employee id 6001..6007 and the same password.</p>
<p>To add more sample data make your changes to the DML-script schema_ins.sql.</p>
<p>The prototype is vertical. We have implemented some functions and not completed. The prototype provides a starting point for your work.</p>
<p>AL/PR 20220504</p>
{% endblock content %}

View File

@ -0,0 +1,4 @@
{% extends "layout.html" %}
{% block content %}
<h1>{{ current_user.name }}</h1>
{% endblock content %}

View File

@ -0,0 +1,59 @@
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Add a new customer</legend>
<div class="form-group">
{{ form.username.label(class="form-control-label") }}
{% if form.username.errors %}
{{ form.username(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.username.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.CPR_number.label(class="form-control-label") }}
{% if form.CPR_number.errors %}
{{ form.CPR_number(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.CPR_number.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.CPR_number(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
<div class="border-top pt-3">
<small class="text-muted">
Already Have An Account? <a class="ml-2" href="{{ url_for('Login.login') }}">Sign In</a>
</small>
</div>
{% endblock content %}

16
bank/templates/home.html Normal file
View File

@ -0,0 +1,16 @@
{% extends "layout.html" %}
{% block content %}
<h1>{{ current_user.name }}</h1>
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="#">{{ post.author }}</a>
<small class="text-muted">{{ post.date_posted }}</small>
</div>
<h2><a class="article-title" href="#">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content }}</p>
</div>
</article>
{% endfor %}
{% endblock content %}

View File

@ -0,0 +1,79 @@
{% extends "layout_acc.html" %}
{% block content %}
<h1>{{ current_user.name }}</h1>
<div class="content-section">
<p>Investments:</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">account_number</th>
<th scope="col">cpr_number</th>
<th scope="col">creation date</th>
</tr>
</thead>
<tbody>
{% for n in inv %}
<tr>
<th scope="row">{{n[0]}}</th>
<td>{{n[1]}}</td>
<td>{{n[2]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="content-section">
<p>Investment accounts:</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">account_number</th>
<th scope="col">cpr_number</th>
<th scope="col">account created</th>
<th scope="col">deposit total (CD)</th>
</tr>
</thead>
<tbody>
{% for n in inv_sums %}
<tr>
<th scope="row">{{n[0]}}</th>
<td>{{n[1]}}</td>
<td>{{n[2]}}</td>
<td>{{n[3]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="content-section">
<p>Investment certificats of deposit:</p>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">acc</th>
<th scope="col">cd_number</th>
<th scope="col">start_date</th>
<th scope="col">maturity_date</th>
<th scope="col">rate</th>
<th scope="col">amount</th>
</tr>
</thead>
<tbody>
{% for n in inv_cd_list %}
<tr>
<th scope="row">{{n[0]}}</th>
<td>{{n[3]}}</td>
<td>{{n[4]}}</td>
<td>{{n[5]}}</td>
<td>{{n[6]}}</td>
<td>{{n[7]}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock content %}

104
bank/templates/layout.html Normal file
View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
{% if title %}
<title>UIS Prototype - {{ title }}</title>
{% else %}
<title>UIS Prototype</title>
{% endif %}
</head>
<body>
<header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
<div class="container">
<a class="navbar-brand mr-4" href="/">UIS Prototype</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{{ url_for('Login.home') }}">Home</a>
{% if current_user.is_authenticated %}
<li class="dropdown">
<a href="#" class="nav-item nav-link dropdown-toggle" data-toggle="dropdown">UIS bank<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a></li>
<li><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
<li class="divider"></li>
<li><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a></li>
<li class="divider"></li>
<li><a class="nav-item nav-link" href="https://www.pgadmin.org">site pgAdmin</a></li>
<li><a class="nav-item nav-link" href="http://127.0.0.1:58653/browser/ ">pgAdmin4</a></li>
</ul>
</li>
{% else %}
{% endif %}
<a class="nav-item nav-link" href="{{ url_for('Login.about') }}">About</a>
</div>
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if current_user.is_authenticated %}
<a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a>
<a class="nav-item nav-link" href="{{ url_for('Employee.addcustomer') }}">Add customer</a>
<a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a>
<a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a>
<a class="nav-item nav-link" href="{{ url_for('Login.logout') }}">Logout</a>
{% else %}
<a class="nav-item nav-link" href="{{ url_for('Login.login') }}">Login</a>
{% endif %}
</div>
</div>
</div>
</nav>
</header>
<main role="main" class="container">
<div class="row">
<div class="col-md-8">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<div class="col-md-4">
<div class="content-section">
<h3>Account</h3>
<ul class="list-group">
{% if current_user.is_authenticated %}
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
<li class="list-group-item list-group-item-light">Checking Accounts</li>
<li class="list-group-item list-group-item-light">Investment Accounts</li>
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">View investment accounts</a></li>
<li class="list-group-item list-group-item-light">etc</li>
{% else %}
<li class="list-group-item list-group-item-light">etc</li>
{% endif %}
</ul>
</p>
</div>
</div>
</div>
</main>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,100 @@
<!DOCTYPE html>
<html>
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
{% if title %}
<title>UIS Prototype - {{ title }}</title>
{% else %}
<title>UIS Prototype</title>
{% endif %}
</head>
<body>
<header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
<div class="container">
<a class="navbar-brand mr-4" href="/">UIS Prototype</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{{ url_for('Login.home') }}">Home</a>
{% if current_user.is_authenticated %}
<li class="dropdown">
<a href="#" class="nav-item nav-link dropdown-toggle" data-toggle="dropdown">UIS bank<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a></li>
<li><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
<li class="divider"></li>
<li><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a></li>
<li class="divider"></li>
<li><a class="nav-item nav-link" href="https://www.pgadmin.org">site pgAdmin</a></li>
<li><a class="nav-item nav-link" href="http://127.0.0.1:58653/browser/ ">pgAdmin4</a></li>
</ul>
</li>
{% else %}
{% endif %}
<a class="nav-item nav-link" href="{{ url_for('Login.about') }}">About</a>
</div>
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if current_user.is_authenticated %}
<a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a>
<a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a>
<a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a>
<a class="nav-item nav-link" href="{{ url_for('Login.logout') }}">Logout</a>
{% else %}
<a class="nav-item nav-link" href="{{ url_for('Login.login') }}">Login</a>
<a class="nav-item nav-link" href="{{ url_for('Employee.addcustomer') }}">Register</a>
{% endif %}
</div>
</div>
</div>
</nav>
</header>
<main role="main" class="container">
<div class="row">
<div class="col-md-8">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<div class="col-md-4">
<div class="content-section">
<h3>Account</h3>
<ul class="list-group">
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
<li class="list-group-item list-group-item-light">Checking Accounts</li>
<li class="list-group-item list-group-item-light">Investment Accounts</li>
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">View investment accounts</a></li>
<li class="list-group-item list-group-item-light">etc</li>
</ul>
</p>
</div>
</div>
</div>
</main>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>

54
bank/templates/login.html Normal file
View File

@ -0,0 +1,54 @@
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Log In</legend>
<div class="form-group">
{{ form.id.label(class="form-control-label") }}
{% if form.id.errors %}
{{ form.id(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.id.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.id(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-check">
{{ form.remember(class="form-check-input") }}
{{ form.remember.label(class="form-check-label") }}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
<small class="text-muted">
<a href="#">Forgot Password?</a>
</small>
<small class="text-muted ml-2">
{% if is_employee %}
<a href="/login?is_employee=false">Customer login?</a>
{% else %}
<a href="/login?is_employee=true">Employee login?</a>
{% endif %}
</small>
</form>
</div>
{% endblock content %}

View File

@ -0,0 +1,46 @@
{% extends "layout.html" %}
{% block content %}
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.sourceAccount.label(class="form-control-label") }}
{{ form.sourceAccount(class="form-control")}}
</div>
<fieldset class="form-group">
<div class="form-group">
{{ form.amount.label(class="form-control-label") }}
{% if form.amount.errors %}
{{ form.amount(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.password.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.amount(class="form-control form-control-lg") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.targetAccount.label(class="form-control-label") }}
{{ form.targetAccount(class="form-control") }}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
<div class="content-section">
<p>Dropdown customer account tuples:</p>
<ul class="list-group">
{% for n in drop_cus_acc %}
<li class="list-group-item list-group-item-light">{{n}}}</li>
{% endfor %}
</ul>
<br>
<p>Same list with a filter: {{ drop_cus_acc|join(', ') }}</p>
</div>
{% endblock content %}

6
requirements.txt Normal file
View File

@ -0,0 +1,6 @@
flask
flask_bcrypt
flask_login
flask_wtf
wtforms
psycopg2

3
run.py Normal file
View File

@ -0,0 +1,3 @@
from bank import app
if __name__ == '__main__':
app.run(debug=True)