Compare commits
42 Commits
9a35d8cbc8
...
main
Author | SHA1 | Date | |
---|---|---|---|
594bade890 | |||
7db90aac3c | |||
32becc8f1f | |||
16269c8950 | |||
c5c2b24cab | |||
7998490040 | |||
0db8c55675 | |||
1d25c819a1 | |||
ca0099063a | |||
6d09e89603 | |||
a1f9d2b065 | |||
95c5ec2a66 | |||
575b84f191 | |||
a405cf772d | |||
83ca3fdf1b | |||
b4c7cc1b0a | |||
213eec1813 | |||
dc9f48cc1c | |||
f5f1fa721b | |||
3ab1c58c14 | |||
66ef5e9e25 | |||
14343422d3 | |||
9d02b2529a | |||
dfc925d5c2 | |||
5f95d59f2e | |||
5c76f8f9be | |||
abf12212f5 | |||
3e1fa025cc | |||
674c8741e7 | |||
5ecfe3b836 | |||
b21a9c71a1 | |||
4592591c4e | |||
0d93a37a5c | |||
f5ac1a6c15 | |||
de1fb39833 | |||
5fec84b6b7 | |||
06b40f5158 | |||
e70708d937 | |||
999f2b3a62 | |||
0a4b769481 | |||
1325d12b46 | |||
4325a15342 |
111
README.md
111
README.md
@ -1,101 +1,18 @@
|
||||
# April 24, 2019 - MAY 1ST, 2019 DEVELOPMENT SPRINT
|
||||
# Opsætning
|
||||
* Installer afhængigheder med `pip install -r requirements.txt`
|
||||
* Opret databasen med `schema.sql`
|
||||
* Indsæt database navn, brugernavn og kodeord i `__init__.py`
|
||||
* Start flask appen med `run.py` i python
|
||||
|
||||
Reviewing the prioritized user stories. User stories to be picked.
|
||||
# Brugervejledning
|
||||
### Tilmeld/afmeld grupper
|
||||
Tryk på menupunktet Grupper for at komme til gruppesiden. Her kan du se alle de grupper som du kan tilmelde og afmelde dig. Det er også her du finder de grupper du er meld af.
|
||||
|
||||
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.
|
||||
### Opret opslag og tråde i grupper
|
||||
På gruppesiden, vælg den gruppe som du ønsker at oprette et opslag eller en tråd i. Nederste på siden kan du skrive et opslag og til højre kan du oprette en gruppe tråd.
|
||||
|
||||
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.
|
||||
### Opret grupper
|
||||
På gruppesiden kan du, hvis du er logget ind som lærer, benytte boksen til højre på siden til at oprette en ny gruppe. Her kan du også indikere om gruppen er obligatorisk.
|
||||
|
||||
### Find tråd
|
||||
Tråde kan enten findes ved at navigere til en gruppe og vælge en af dens tråde i boksen til højre. Eller du kan vælge menupunktet Tråde som viser alle de tråde du har adgang til.
|
@ -1,13 +1,58 @@
|
||||
from flask import render_template, url_for, flash, redirect, request, Blueprint
|
||||
from flask import render_template, Blueprint, flash, redirect
|
||||
from flask_login import current_user, login_required
|
||||
from aula.models import select_users_by_id
|
||||
import sys, datetime
|
||||
from aula.models import get_group, insert_group, group_exist
|
||||
from aula.forms import CreateThreadForm, CreateGroupForm, CreatePostForm
|
||||
|
||||
Group = Blueprint('Group', __name__)
|
||||
|
||||
@Group.route("/groups", methods=['GET'])
|
||||
def index():
|
||||
current_user.join_group(1000)
|
||||
groups = current_user.get_groups()
|
||||
return render_template('groups.html', groups=groups)
|
||||
@login_required
|
||||
def groups():
|
||||
groups = current_user.get_groups_joinable()
|
||||
form = CreateGroupForm()
|
||||
return render_template('groups.html', groups=groups, form=form)
|
||||
|
||||
@Group.route("/groups/<int:group_id>", methods=['GET'])
|
||||
@login_required
|
||||
def show(group_id):
|
||||
group = get_group(group_id)
|
||||
posts = group.get_posts()
|
||||
threads = group.get_threads()
|
||||
form = CreateThreadForm()
|
||||
formpost = CreatePostForm()
|
||||
if (group is not None):
|
||||
return render_template('group_show.html', group=group, posts=posts, threads=threads, form=form, formpost=formpost)
|
||||
else:
|
||||
return f"Der findes ikke en gruppe med id {group_id}."
|
||||
|
||||
@Group.route("/groups/create", methods=['POST'])
|
||||
@login_required
|
||||
def create():
|
||||
form = CreateGroupForm()
|
||||
|
||||
# Make sure we dont try to create group with same name as others
|
||||
# Since name has UNIQUE constraint.
|
||||
if group_exist(form.title.data):
|
||||
flash('En gruppe med det navn findes allerede', 'danger')
|
||||
return redirect(f"/groups")
|
||||
|
||||
group = insert_group(form.title.data, form.mandatory.data)
|
||||
current_user.join_group(group.group_id)
|
||||
flash('Gruppen blev oprettet', 'success')
|
||||
return redirect(f"/groups")
|
||||
|
||||
@Group.route("/groups/join/<int:group_id>", methods=['GET'])
|
||||
def join(group_id):
|
||||
group = get_group(group_id)
|
||||
|
||||
current_user.join_group(group_id)
|
||||
flash(f'Du er nu tilmeldt {group.name} gruppen', 'success')
|
||||
return redirect(f"/groups/{group_id}")
|
||||
|
||||
@Group.route("/groups/leave/<int:group_id>", methods=['GET'])
|
||||
def leave(group_id):
|
||||
group = get_group(group_id)
|
||||
|
||||
current_user.leave_group(group_id)
|
||||
flash(f'Du er frameldt {group.name} gruppen', 'success')
|
||||
return redirect(f"/groups")
|
@ -3,7 +3,7 @@ from flask_login import current_user, login_user, logout_user, login_required
|
||||
|
||||
from aula import bcrypt
|
||||
from aula.forms import UserLoginForm
|
||||
from aula.models import select_users_by_email, get_posts_for_user
|
||||
from aula.models import select_users_by_cpr, get_posts_for_user
|
||||
|
||||
Login = Blueprint('Login', __name__)
|
||||
|
||||
@ -18,11 +18,6 @@ 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:
|
||||
@ -31,7 +26,7 @@ def login():
|
||||
form = UserLoginForm()
|
||||
# Først bekræft, at inputtet fra formen er gyldigt... (f.eks. ikke tomt)
|
||||
if form.validate_on_submit():
|
||||
user = select_users_by_email(form.email.data)
|
||||
user = select_users_by_cpr(form.cpr_num.data)
|
||||
# Derefter tjek om hashet af adgangskoden passer med det fra databasen...
|
||||
if user != None and bcrypt.check_password_hash(user[3], form.password.data):
|
||||
login_user(user, remember=form.remember.data)
|
||||
|
14
aula/Post/routes.py
Normal file
14
aula/Post/routes.py
Normal file
@ -0,0 +1,14 @@
|
||||
from flask import render_template, Blueprint, flash, redirect
|
||||
from flask_login import current_user, login_required
|
||||
from aula.models import insert_post
|
||||
from aula.forms import CreatePostForm
|
||||
|
||||
Post = Blueprint('Post', __name__)
|
||||
|
||||
@Post.route("/posts/create", methods=['POST'])
|
||||
@login_required
|
||||
def create():
|
||||
form = CreatePostForm()
|
||||
insert_post(form.group_id.data, form.author_id.data, form.title.data, form.content.data)
|
||||
flash('Opslag blev oprettet', 'success')
|
||||
return redirect(f"/groups/{form.group_id.data}")
|
@ -1,12 +1,38 @@
|
||||
from flask import render_template, url_for, flash, redirect, request, Blueprint
|
||||
from bank import app, conn, bcrypt
|
||||
from aula.forms import TransferForm, DepositForm, AddCustomerForm
|
||||
from flask_login import current_user, login_required
|
||||
import sys, datetime
|
||||
from flask import redirect, render_template, Blueprint, flash
|
||||
from flask_login import login_required, current_user
|
||||
from aula.models import get_thread, insert_message, insert_thread
|
||||
from aula.forms import SendMessageForm, CreateThreadForm
|
||||
|
||||
Group = Blueprint('Threads', __name__)
|
||||
Threads = Blueprint('Threads', __name__)
|
||||
|
||||
@Threads.route("/threads", methods=['GET'])
|
||||
@login_required
|
||||
def threads():
|
||||
threads_data = current_user.get_threads()
|
||||
return render_template("threads.html", threads=threads_data)
|
||||
|
||||
@Threads.route("/threads/<int:thread_id>", methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def show(thread_id):
|
||||
thread = get_thread(thread_id)
|
||||
if thread is None:
|
||||
return f"Der findes ikke en tråd med id {thread_id}."
|
||||
elif not current_user.is_member_of_group(thread.group_id):
|
||||
return f"Du har ikke adgang til tråden med id {thread_id}."
|
||||
else:
|
||||
form = SendMessageForm()
|
||||
|
||||
if form.validate_on_submit():
|
||||
insert_message(form.besked.data, thread_id, current_user.cpr_num)
|
||||
return redirect(f"/threads/{thread_id}")
|
||||
|
||||
return render_template("thread_show.html", thread=thread, messages=thread.get_messages(), form=form)
|
||||
|
||||
@Threads.route("/threads/create", methods=['POST'])
|
||||
@login_required
|
||||
def create():
|
||||
form = CreateThreadForm()
|
||||
insert_thread(form.group_id.data, form.title.data)
|
||||
flash('Tråden blev oprettet', 'success')
|
||||
return redirect(f"/groups/{form.group_id.data}")
|
||||
|
||||
@login_required()
|
||||
@Group.route("threads/index", methods=['GET'])
|
||||
def index():
|
||||
return render_template()
|
||||
|
@ -11,16 +11,17 @@ conn = psycopg2.connect(db)
|
||||
|
||||
bcrypt = Bcrypt(app)
|
||||
login_manager = LoginManager(app)
|
||||
login_manager.login_view = 'login'
|
||||
login_manager.login_view = 'Login.login'
|
||||
login_manager.login_message_category = 'info'
|
||||
|
||||
from aula.Login.routes import Login
|
||||
# from bank.Customer.routes import Customer
|
||||
# from bank.Employee.routes import Employee
|
||||
# from bank.Pax.routes import Pax
|
||||
from aula.Group.routes import Group
|
||||
from aula.Threads.routes import Threads
|
||||
from aula.Post.routes import Post
|
||||
|
||||
app.register_blueprint(Login)
|
||||
# app.register_blueprint(Customer)
|
||||
# app.register_blueprint(Employee)
|
||||
# app.register_blueprint(Pax)
|
||||
app.register_blueprint(Group)
|
||||
app.register_blueprint(Threads)
|
||||
app.register_blueprint(Post)
|
||||
|
||||
#from bank import routes
|
||||
|
@ -1,5 +1,5 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, PasswordField, SubmitField, BooleanField
|
||||
from wtforms import StringField, PasswordField, SubmitField, BooleanField, HiddenField
|
||||
from wtforms.validators import DataRequired, Length
|
||||
|
||||
class AddUserForm(FlaskForm):
|
||||
@ -11,7 +11,29 @@ class AddUserForm(FlaskForm):
|
||||
submit = SubmitField('Add')
|
||||
|
||||
class UserLoginForm(FlaskForm):
|
||||
email = StringField('Email', validators=[DataRequired()])
|
||||
cpr_num = StringField('CPR Nummer', validators=[DataRequired()])
|
||||
password = PasswordField('Password', validators=[DataRequired()])
|
||||
remember = BooleanField('Remember Me')
|
||||
submit = SubmitField('Login')
|
||||
|
||||
class SendMessageForm(FlaskForm):
|
||||
besked = StringField('Besked', validators=[DataRequired()])
|
||||
submit = SubmitField('Send')
|
||||
|
||||
class CreateThreadForm(FlaskForm):
|
||||
group_id = HiddenField('GroupID', validators=[DataRequired()])
|
||||
title = StringField('Title', validators=[DataRequired()])
|
||||
submit = SubmitField()
|
||||
|
||||
class CreateGroupForm(FlaskForm):
|
||||
title = StringField('Title', validators=[DataRequired()])
|
||||
mandatory = BooleanField('Obligatorisk gruppe')
|
||||
submit = SubmitField("Opret gruppe")
|
||||
|
||||
class CreatePostForm(FlaskForm):
|
||||
title = StringField('Title', validators=[DataRequired()])
|
||||
content = StringField('Indhold', validators=[DataRequired()])
|
||||
author_id = HiddenField('AuthorID', validators=[DataRequired()])
|
||||
group_id = HiddenField('GroupID', validators=[DataRequired()])
|
||||
submit = SubmitField("Opret opslag")
|
||||
|
||||
|
308
aula/models.py
308
aula/models.py
@ -1,22 +1,28 @@
|
||||
# write all your SQL queries in this file.
|
||||
from datetime import datetime, timedelta
|
||||
from flask_login import UserMixin
|
||||
|
||||
from aula import conn, login_manager
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
def load_user(cpr_num):
|
||||
cur = conn.cursor()
|
||||
|
||||
user_sql = """
|
||||
SELECT * FROM users
|
||||
WHERE user_id = %s
|
||||
WHERE cpr_num = %s
|
||||
"""
|
||||
|
||||
cur.execute(user_sql, (user_id,))
|
||||
cur.execute(user_sql, (cpr_num,))
|
||||
user = User(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
cur.close()
|
||||
return user
|
||||
|
||||
def convert_role(role):
|
||||
if role == "student": return "Elev"
|
||||
elif role == "parent": return "Forældre"
|
||||
else: return "Lærer"
|
||||
|
||||
#
|
||||
# Models
|
||||
#
|
||||
@ -24,17 +30,20 @@ class Group(tuple):
|
||||
def __init__(self, group_data):
|
||||
self.group_id = group_data[0]
|
||||
self.name = group_data[1]
|
||||
self.hidden = group_data[2]
|
||||
self.mandatory = group_data[2]
|
||||
super().__init__()
|
||||
|
||||
def get_posts(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM posts
|
||||
WHERE group_id = %s
|
||||
SELECT post_id, title, content, created_date, g.group_id, g.name, g.mandatory, u.cpr_num, u.first_name, u.last_name, u.role FROM posts as p
|
||||
INNER JOIN groups g on g.group_id = p.group_id
|
||||
INNER JOIN users u on u.cpr_num = p.author_cpr_num
|
||||
WHERE p.group_id = %s
|
||||
ORDER BY created_date DESC;
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
Posts = Posts(cur.fetchall()) if cur.rowcount > 0 else None
|
||||
Posts = cur.fetchall()
|
||||
result = []
|
||||
for post_data in Posts:
|
||||
result.append(Post(post_data))
|
||||
@ -44,13 +53,14 @@ class Group(tuple):
|
||||
def get_threads(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM threads
|
||||
SELECT thread_id, title, g.group_id, g.name, g.mandatory FROM threads
|
||||
INNER JOIN groups g on g.group_id = threads.group_id
|
||||
WHERE threads.group_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
Thread = Thread(cur.fetchall()) if cur.rowcount > 0 else None
|
||||
threads = cur.fetchall()
|
||||
result = []
|
||||
for thread_data in Thread:
|
||||
for thread_data in threads:
|
||||
result.append(Thread(thread_data))
|
||||
cur.close()
|
||||
return result
|
||||
@ -60,83 +70,106 @@ class Message(tuple):
|
||||
self.message_id = message_data[0]
|
||||
self.content = message_data[1]
|
||||
self.thread_id = message_data[2]
|
||||
self.author_id = message_data[3]
|
||||
self.created_date = message_data[4]
|
||||
self._created_date = message_data[3]
|
||||
self.author = {
|
||||
"cpr_num": message_data[4],
|
||||
"first_name": message_data[5],
|
||||
"last_name": message_data[6],
|
||||
"role": convert_role(message_data[7]),
|
||||
}
|
||||
super().__init__()
|
||||
|
||||
@property
|
||||
def created_date(self):
|
||||
now = datetime.now()
|
||||
if now.date() == self._created_date.date():
|
||||
return self._created_date.strftime("Idag %X")
|
||||
elif now.date() == self._created_date.date() + timedelta(days=1):
|
||||
return self._created_date.strftime("Igår %X")
|
||||
elif now < self._created_date + timedelta(days=7):
|
||||
dag = [
|
||||
"Mandag",
|
||||
"Tirsdag",
|
||||
"Onsdag",
|
||||
"Torsdag",
|
||||
"Fredag",
|
||||
"Lørdag",
|
||||
"Søndag",
|
||||
][int(self._created_date.strftime("%w"))]
|
||||
return self._created_date.strftime(f"{dag} %X")
|
||||
elif now.strftime("%y") == self._created_date.strftime("%y"):
|
||||
return self._created_date.strftime("%d/%m %X")
|
||||
else:
|
||||
return self._created_date.strftime("%d/%m/%y %X")
|
||||
|
||||
class Post(tuple):
|
||||
def __init__(self, post_data):
|
||||
self.post_id = post_data[0]
|
||||
self.group_id = post_data[1]
|
||||
self.group_name = ""
|
||||
self.author_id = post_data[2]
|
||||
self.author_name = ""
|
||||
self.title = post_data[3]
|
||||
self.content = post_data[4]
|
||||
self.created_date = post_data[5]
|
||||
self._get_group_name()
|
||||
self._get_author_name()
|
||||
self.title = post_data[1]
|
||||
self.content = post_data[2]
|
||||
self.created_date = post_data[3]
|
||||
self.group = {
|
||||
'group_id': post_data[4],
|
||||
'name': post_data[5],
|
||||
'mandatory': post_data[6],
|
||||
}
|
||||
self.author = {
|
||||
'cpr_num': post_data[7],
|
||||
'first_name': post_data[8],
|
||||
'last_name': post_data[9],
|
||||
'role': convert_role(post_data[7]),
|
||||
}
|
||||
super().__init__()
|
||||
|
||||
def _get_author_name(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT first_name, last_name FROM users WHERE user_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.author_id,))
|
||||
self.author_name = ' '.join(cur.fetchone())
|
||||
|
||||
def _get_group_name(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT name FROM groups WHERE group_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
self.group_name = cur.fetchone()[0]
|
||||
|
||||
class Thread(tuple):
|
||||
def __init__(self, thread_data):
|
||||
self.thread_id = thread_data[0]
|
||||
self.title = thread_data[1]
|
||||
self.group = {
|
||||
"group_id": thread_data[2],
|
||||
"name": thread_data[3],
|
||||
"mandatory": thread_data[4]
|
||||
}
|
||||
self.group_id = thread_data[2]
|
||||
self.creator_id = thread_data[3]
|
||||
if len(thread_data) == 6:
|
||||
self.last_message_date = thread_data[5]
|
||||
super().__init__()
|
||||
|
||||
def get_message(self):
|
||||
def get_messages(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM message
|
||||
WHERE message.thread_id = %s.thread_id
|
||||
SELECT message_id, content, thread_id, created_date ,u.cpr_num, u.first_name, u.last_name, u.role FROM messages
|
||||
INNER JOIN users u on u.cpr_num = messages.author_cpr_num
|
||||
WHERE messages.thread_id = %s
|
||||
ORDER BY created_date ASC;
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
Thread = Thread(cur.fetchall()) if cur.rowcount > 0 else None
|
||||
cur.execute(sql_call, (self.thread_id,))
|
||||
messages = cur.fetchall()
|
||||
result = []
|
||||
for thread_data in Thread:
|
||||
result.append(Thread(thread_data))
|
||||
for message_data in messages:
|
||||
result.append(Message(message_data))
|
||||
cur.close()
|
||||
return result
|
||||
|
||||
|
||||
class User(tuple, UserMixin):
|
||||
def __init__(self, user_data):
|
||||
self.user_id = user_data[0]
|
||||
self.cpr_num = user_data[0]
|
||||
self.first_name = user_data[1]
|
||||
self.last_name = user_data[2]
|
||||
self.password = user_data[3]
|
||||
self.email = user_data[4]
|
||||
self.address = user_data[5]
|
||||
self.role = user_data[6]
|
||||
self.role = convert_role(user_data[4])
|
||||
super().__init__()
|
||||
|
||||
def get_id(self):
|
||||
return self.user_id
|
||||
return self.cpr_num
|
||||
|
||||
def get_groups(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT groups.* FROM users_groups JOIN groups ON users_groups.group_id = groups.group_id WHERE users_groups.user_id = %s
|
||||
SELECT groups.* FROM users_in_groups JOIN groups ON users_in_groups.group_id = groups.group_id WHERE users_in_groups.cpr_num = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.user_id,))
|
||||
cur.execute(sql_call, (self.cpr_num,))
|
||||
groups = cur.fetchall()
|
||||
result = []
|
||||
for group_data in groups:
|
||||
@ -144,15 +177,24 @@ class User(tuple, UserMixin):
|
||||
cur.close()
|
||||
return result
|
||||
|
||||
def is_member_of_group(self, group_id):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM users_in_groups WHERE cpr_num = %s AND group_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.cpr_num, group_id))
|
||||
return cur.rowcount > 0
|
||||
|
||||
|
||||
def get_groups_joinable(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT groups.* FROM groups INNER JOIN users_groups ON groups.group_id = users_groups.group_id WHERE users_groups.user_id = %s
|
||||
SELECT groups.* FROM groups INNER JOIN users_in_groups ON groups.group_id = users_in_groups.group_id WHERE users_in_groups.cpr_num = %s
|
||||
UNION
|
||||
SELECT groups.* FROM groups WHERE groups.hidden = TRUE
|
||||
ORDER BY hidden ASC, name DESC
|
||||
SELECT groups.* FROM groups WHERE groups.mandatory = FALSE
|
||||
ORDER BY mandatory ASC, name DESC
|
||||
"""
|
||||
cur.execute(sql_call, (self.user_id,))
|
||||
cur.execute(sql_call, (self.cpr_num,))
|
||||
groups = cur.fetchall()
|
||||
result = []
|
||||
for group_data in groups:
|
||||
@ -164,84 +206,164 @@ class User(tuple, UserMixin):
|
||||
# TODO: Tjek om brugeren må forlade gruppen
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
DELETE FROM users_groups WHERE user_id = %s AND group_id = %s
|
||||
DELETE FROM users_in_groups WHERE cpr_num = %s AND group_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.user_id, group_id))
|
||||
cur.execute(sql_call, (self.cpr_num, group_id))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def join_group(self, group_id):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
INSERT INTO users_groups VALUES (%s, %s)
|
||||
INSERT INTO users_in_groups VALUES (%s, %s)
|
||||
"""
|
||||
cur.execute(sql_call, (self.user_id, group_id))
|
||||
cur.execute(sql_call, (self.cpr_num, group_id))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def get_all_threads(self):
|
||||
|
||||
def get_threads(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM threads WHERE group_id =
|
||||
(SELECT groups.group_id FROM
|
||||
groups INNER JOIN users_groups ON groups.group_id = users_groups.group_id
|
||||
WHERE users_groups.user_id = %s )
|
||||
SELECT threads.thread_id, title, g.group_id, g.name, g.mandatory, lm.last_message_date FROM threads
|
||||
INNER JOIN
|
||||
groups g
|
||||
ON g.group_id = threads.group_id
|
||||
LEFT JOIN
|
||||
(SELECT thread_id, MAX(created_date) as last_message_date FROM messages GROUP BY thread_id) lm
|
||||
ON threads.thread_id = lm.thread_id
|
||||
WHERE g.group_id IN
|
||||
(
|
||||
SELECT group_id FROM users_in_groups
|
||||
WHERE cpr_num = %s
|
||||
)
|
||||
ORDER BY last_message_date DESC NULLS LAST;
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
Thread = Thread(cur.fetchall()) if cur.rowcount > 0 else None
|
||||
cur.execute(sql_call, (self.cpr_num,))
|
||||
threads = cur.fetchall()
|
||||
result = []
|
||||
for thread_data in Thread:
|
||||
for thread_data in threads:
|
||||
result.append(Thread(thread_data))
|
||||
cur.close()
|
||||
return result
|
||||
|
||||
|
||||
def in_thread(self, thread_id):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM users_threads WHERE
|
||||
cpr_num = %s AND
|
||||
thread_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.cpr_num, thread_id))
|
||||
return cur.rowcount > 0
|
||||
|
||||
def insert_users(user_id, first_name, last_name, password, email, adresse, role):
|
||||
def insert_users(cpr_num, first_name, last_name, password, email, adresse, role):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
INSERT INTO users(user_id, first_name, last_name, password, email, adresse, role)
|
||||
INSERT INTO users(cpr_num, first_name, last_name, password, email, adresse, role)
|
||||
VALUES (%s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
cur.execute(sql_call, (user_id, first_name, last_name, password, email, adresse, role))
|
||||
cur.execute(sql_call, (cpr_num, first_name, last_name, password, email, adresse, role))
|
||||
# Husk commit() for INSERT og UPDATE, men ikke til SELECT!
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def select_users_by_id(user_id):
|
||||
def select_users_by_cpr(cpr_num):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM users
|
||||
WHERE user_id = %s
|
||||
WHERE cpr_num = %s
|
||||
"""
|
||||
cur.execute(sql_call, (user_id,))
|
||||
cur.execute(sql_call, (cpr_num,))
|
||||
user = User(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
cur.close()
|
||||
return user
|
||||
|
||||
def select_users_by_email(email):
|
||||
def get_posts_for_user(cpr_num):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM users
|
||||
WHERE email = %s
|
||||
"""
|
||||
cur.execute(sql_call, (email,))
|
||||
user = User(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
cur.close()
|
||||
return user
|
||||
|
||||
def get_posts_for_user(user_id):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM posts
|
||||
WHERE group_id in (
|
||||
SELECT group_id FROM users_groups
|
||||
WHERE user_id = %s
|
||||
SELECT post_id, title, content, created_date, g.group_id, g.name, g.mandatory, u.cpr_num, u.first_name, u.last_name, u.role FROM posts as p
|
||||
INNER JOIN groups g on g.group_id = p.group_id
|
||||
INNER JOIN users u on u.cpr_num = p.author_cpr_num
|
||||
WHERE g.group_id in (
|
||||
SELECT group_id FROM users_in_groups
|
||||
WHERE cpr_num = 5001
|
||||
)
|
||||
ORDER BY created_date DESC
|
||||
"""
|
||||
cur.execute(sql_call, (user_id,))
|
||||
cur.execute(sql_call, (cpr_num,))
|
||||
user = [Post(i) for i in cur.fetchmany(50)] if cur.rowcount > 0 else []
|
||||
cur.close()
|
||||
return user
|
||||
|
||||
def get_group(group_id):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
SELECT * FROM groups
|
||||
WHERE group_id = %s
|
||||
"""
|
||||
cur.execute(sql, (group_id,))
|
||||
group = Group(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
cur.close()
|
||||
return group
|
||||
|
||||
def get_thread(thread_id):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
SELECT thread_id, title, g.group_id, g.name, g.mandatory FROM threads
|
||||
INNER JOIN groups g on g.group_id = threads.group_id
|
||||
WHERE thread_id = %s
|
||||
"""
|
||||
cur.execute(sql, (thread_id,))
|
||||
thread = Thread(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
cur.close()
|
||||
return thread
|
||||
|
||||
def insert_thread(group_id, title):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
INSERT INTO threads(group_id, title) VALUES (%s, %s)
|
||||
"""
|
||||
cur.execute(sql, (group_id, title))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def group_exist(name):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
SELECT COUNT(*) FROM groups WHERE name = %s
|
||||
"""
|
||||
cur.execute(sql, (name,))
|
||||
return cur.fetchone()[0] > 0
|
||||
|
||||
def insert_group(name, mandatory):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
INSERT INTO groups(name, mandatory) VALUES (%s, %s) RETURNING *
|
||||
"""
|
||||
cur.execute(sql, (name, mandatory))
|
||||
|
||||
result = Group(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
return result
|
||||
|
||||
def insert_post(group_id, author_cpr_num, title, content):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
INSERT INTO posts(group_id, author_cpr_num, title, content) VALUES (%s, %s, %s, %s)
|
||||
"""
|
||||
cur.execute(sql, (group_id, author_cpr_num, title, content))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def insert_message(content, thread_id, author_cpr_num):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
INSERT INTO messages(content, thread_id, author_cpr_num, created_date)
|
||||
VALUES (%s, %s, %s, NOW())
|
||||
"""
|
||||
cur.execute(sql_call, (content, thread_id, author_cpr_num))
|
||||
# Husk commit() for INSERT og UPDATE, men ikke til SELECT!
|
||||
conn.commit()
|
||||
cur.close()
|
@ -1,19 +1,17 @@
|
||||
\i schema_drop.sql;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
user_id SERIAL PRIMARY KEY,
|
||||
cpr_num INTEGER PRIMARY KEY,
|
||||
first_name varchar(64) NOT NULL,
|
||||
last_name varchar(64) NOT NULL,
|
||||
password varchar(120) NOT NULL,
|
||||
email varchar(64) NOT NULL UNIQUE,
|
||||
address varchar(64) NOT NULL,
|
||||
role varchar(64) NOT NULL CHECK ( role in ('student', 'parent', 'teacher') )
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS groups (
|
||||
group_id SERIAL PRIMARY KEY,
|
||||
name varchar(64) NOT NULL UNIQUE,
|
||||
hidden boolean DEFAULT TRUE
|
||||
mandatory boolean DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS threads (
|
||||
@ -26,28 +24,24 @@ CREATE TABLE IF NOT EXISTS messages (
|
||||
message_id SERIAL PRIMARY KEY,
|
||||
content text NOT NULL,
|
||||
thread_id integer REFERENCES threads(thread_id) NOT NULL,
|
||||
author_id integer REFERENCES users(user_id) NOT NULL,
|
||||
author_cpr_num integer REFERENCES users(cpr_num) NOT NULL,
|
||||
created_date timestamp NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS posts (
|
||||
post_id SERIAL PRIMARY KEY,
|
||||
group_id integer REFERENCES groups(group_id) NOT NULL,
|
||||
author_id integer REFERENCES users(user_id) NOt NULL,
|
||||
author_cpr_num integer REFERENCES users(cpr_num) NOt NULL,
|
||||
title varchar(64) NOT NULL,
|
||||
content text NOT NULL,
|
||||
created_date timestamp NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Relationships
|
||||
CREATE TABLE IF NOT EXISTS users_threads (
|
||||
user_id integer REFERENCES users(user_id) NOT NULL,
|
||||
thread_id integer REFERENCES threads(thread_id) NOT NULL,
|
||||
PRIMARY KEY (user_id, thread_id)
|
||||
CREATE TABLE IF NOT EXISTS users_in_groups (
|
||||
cpr_num integer REFERENCES users(cpr_num) NOT NULL,
|
||||
group_id integer REFERENCES groups(group_id) NOT NULL,
|
||||
PRIMARY KEY (cpr_num, group_id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users_groups (
|
||||
user_id integer REFERENCES users(user_id) NOT NULL,
|
||||
group_id integer REFERENCES groups(group_id) NOT NULL,
|
||||
PRIMARY KEY (user_id, group_id)
|
||||
);
|
||||
\i schema_ins.sql;
|
@ -1,5 +1,4 @@
|
||||
DROP TABLE IF EXISTS users_threads;
|
||||
DROP TABLE IF EXISTS users_groups;
|
||||
DROP TABLE IF EXISTS users_in_groups;
|
||||
DROP TABLE IF EXISTS messages;
|
||||
DROP TABLE IF EXISTS threads;
|
||||
DROP TABLE IF EXISTS posts;
|
||||
|
@ -1,25 +1,32 @@
|
||||
TRUNCATE users, groups, threads, messages, posts, users_groups, users_threads;
|
||||
TRUNCATE users, groups, threads, messages, posts, users_in_groups;
|
||||
|
||||
INSERT INTO public.users(user_id, first_name, last_name, password, email, address, role) VALUES
|
||||
(5000, 'Gordon', 'Freeman', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'gordon@test.dk', 'Black Mesa', 'teacher'),
|
||||
(5001, 'Rachel', 'Green', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'rachel@test.dk', 'Cnetral Park', 'parent'),
|
||||
(5002,'Joey', 'Trib', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'joey@test.dk', 'New York', 'student'),
|
||||
(5003,'Chandler', 'Bing', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'chandler@test.dk', 'Central Park', 'student'),
|
||||
(5004,'Phoebe', 'Buffay', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'phoebe@test.dk', 'Central Perk', 'parent'),
|
||||
(5005,'Ross', 'Geller', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'ross@test.dk', 'Central Perk', 'student');
|
||||
INSERT INTO public.users(cpr_num, first_name, last_name, password, role) VALUES
|
||||
(5000, 'Gordon', 'Freeman', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'teacher'),
|
||||
(5001, 'Rachel', 'Green', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'parent'),
|
||||
(5002,'Joey', 'Trib', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'parent'),
|
||||
(5003,'Chandler', 'Bing', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'parent'),
|
||||
(5004,'Phoebe', 'Buffay', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'parent'),
|
||||
(5005,'Ross', 'Geller', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'parent');
|
||||
|
||||
INSERT INTO public.groups(group_id, name, hidden) VALUES
|
||||
(1000, 'fodbold', TRUE),
|
||||
(1001,'3a', FALSE);
|
||||
INSERT INTO public.groups(group_id, name, mandatory) VALUES
|
||||
(1000, 'fodbold', FALSE),
|
||||
(1001,'3a', TRUE);
|
||||
|
||||
INSERT INTO users_groups (user_id, group_id) VALUES (5000, 1000), (5001, 1001);
|
||||
INSERT INTO users_in_groups (cpr_num, group_id) VALUES (5000, 1000), (5000, 1001), (5001, 1001), (5001, 1000), (5002, 1000);
|
||||
|
||||
INSERT INTO threads(thread_id ,title, group_id) VALUES
|
||||
INSERT INTO threads(thread_id ,title, group_id) VALUES
|
||||
(2000, 'Anbefalinger til fodboldsko?', 1000);
|
||||
|
||||
INSERT INTO messages (message_id, content, thread_id, author_id) VALUES (4000,'Eleverne har ondt i fødderne når de spiller fodbild. Hvem kender et godt skomærke?', 2000, 5000);
|
||||
INSERT INTO messages (content, thread_id, author_cpr_num, created_date) VALUES
|
||||
('Eleverne har ondt i fødderne når de spiller fodbild. Hvem kender et godt skomærke?', 2000, 5000, NOW() - INTERVAL '3.189 day'),
|
||||
('Jeg tror min søn har nogle han er glad for. Jeg spørger ham lige', 2000, 5002, NOW() - INTERVAL '2.951 day'),
|
||||
('Tak', 2000, 5000, NOW() - INTERVAL '1.894 day'),
|
||||
('Er det meningen vi skal give dem sko med????', 2000, 5001, NOW() - INTERVAL '1.05 hour'),
|
||||
('Rachel, ja dine børn skal selv have sko med til fodbold?', 2000, 5002, NOW() - INTERVAL '0.95 hour'),
|
||||
('Okay, Det troede jeg lånte af skolen', 2000, 5001, NOW() - INTERVAL '0.91 hour'),
|
||||
('Det har jeg aldrig hørt om', 2000, 5003, NOW() - INTERVAL '0.908 hour'),
|
||||
('Lad os komme tilbage til pointen', 2000, 5000, NOW() - INTERVAL '0.9 hour'),
|
||||
('Okay', 2000, 5001, NOW() - INTERVAL '0.898 hour'),
|
||||
('Ja god ide', 2000, 5003, NOW() - INTERVAL '0.89 hour');
|
||||
|
||||
INSERT INTO users_threads (user_id, thread_id) VALUES (5000, 2000);
|
||||
|
||||
INSERT INTO posts (post_id, group_id, author_id, title, content) VALUES (6000, 1000, 5001, 'Fodbold på torsdag', 'HUSK BOLDEN DENNE GANG!!');
|
||||
|
||||
INSERT INTO posts (post_id, group_id, author_cpr_num, title, content) VALUES (6000, 1000, 5001, 'Fodbold på torsdag', 'HUSK BOLDEN DENNE GANG!!');
|
||||
|
@ -1,8 +1,8 @@
|
||||
body {
|
||||
background: #fafafa;
|
||||
color: #333333;
|
||||
margin-top: 5rem;
|
||||
font-family: Lato, sans-serif;
|
||||
min-height: 80vh;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
@ -19,6 +19,126 @@ h1, h2, h3, h4, h5, h6 {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.thread-name {
|
||||
color: #333333;
|
||||
text-decoration: none !important;
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
color: #333333;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.thread {
|
||||
border-radius: 20px !important;
|
||||
height: 80vh;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.thread h1 {
|
||||
margin-top: 20px;
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.messages {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: auto;
|
||||
height: 61vh;
|
||||
overflow: scroll;
|
||||
padding-right: 5px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
border-top: 3px black solid;
|
||||
border-bottom: 3px black solid;
|
||||
}
|
||||
|
||||
.message-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.message-container .message {
|
||||
position: inherit;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: fit-content;
|
||||
max-width: 40%;
|
||||
border-radius: 20px !important;
|
||||
padding-top: 5px !important;
|
||||
padding-bottom: 10px !important;
|
||||
padding-left: 15px !important;
|
||||
padding-right: 15px !important;
|
||||
background-color: rgb(22, 97, 148) !important;
|
||||
color: #ffffff !important;
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.new-message form {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
padding-right: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.new-message form .message-box {
|
||||
height: auto;
|
||||
font-size: large;
|
||||
display: flex;
|
||||
flex-grow: 3;
|
||||
margin-right: 10px;
|
||||
border-radius: 10px;
|
||||
border: 2px black solid;
|
||||
padding: 3px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.new-message form .send:hover {
|
||||
background-color: rgb(84 158 199);
|
||||
border: 2px rgb(22 97 148) solid;
|
||||
}
|
||||
|
||||
.new-message form .send {
|
||||
color: #fff;
|
||||
background-color: rgb(22 97 148);
|
||||
border-radius: 10px;
|
||||
border: 2px black solid;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.message-container .timestamp {
|
||||
align-self: flex-start;
|
||||
margin-right: 5px;
|
||||
margin-left: 5px;
|
||||
margin-bottom: 0;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.message-container.self .timestamp {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.message p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.message-container.self .message {
|
||||
background-color: rgb(84 158 199) !important;
|
||||
right: 0;
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
.message a.author-name {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
|
||||
.group-name {
|
||||
align-self: flex-end;
|
||||
position: inherit;
|
||||
@ -50,7 +170,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
height: 80px;
|
||||
height: 75px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
@ -62,11 +182,11 @@ h1, h2, h3, h4, h5, h6 {
|
||||
color: #cbd5db;
|
||||
font-weight: 700;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
height: 80px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
text-align: center;
|
||||
padding-top: 35px;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.site-header .navbar-nav .nav-link:hover {
|
||||
|
@ -1,30 +0,0 @@
|
||||
{% 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 %}
|
||||
|
@ -1,4 +1,70 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>{{ current_user.name }}</h1>
|
||||
{% endblock content %}
|
||||
<h1>Bruger Information</h1>
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Attribute</th>
|
||||
<th scope="col">værdi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">cpr_num</th>
|
||||
<td>{{ current_user.cpr_num }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">first_name</th>
|
||||
<td>{{ current_user.first_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">last_name</th>
|
||||
<td>{{ current_user.last_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">role</th>
|
||||
<td>{{ current_user.role }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><b>Grupper</b></p>
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">group_id</th>
|
||||
<th scope="col">name</th>
|
||||
<th scope="col">mandatory</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for group in current_user.get_groups() %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.group_id }}</a></td>
|
||||
<td>{{ group.name }}</td>
|
||||
<td>{{ group.mandatory }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><b>Tråde</b></p>
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">thread_id</th>
|
||||
<th scope="col">title</th>
|
||||
<th scope="col">group_id</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for thread in current_user.get_threads() %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}">{{ thread.thread_id }}</a></td>
|
||||
<td>{{ thread.title }}</td>
|
||||
<td>{{ thread.group_id }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock content %}
|
@ -1,59 +0,0 @@
|
||||
{% 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 %}
|
74
aula/templates/group_show.html
Normal file
74
aula/templates/group_show.html
Normal file
@ -0,0 +1,74 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>{{ group.name }}
|
||||
</h1>
|
||||
<hr>
|
||||
{% if posts|length == 0 %}
|
||||
<p>Gruppen har ingen opslag endnu</p>
|
||||
{% endif %}
|
||||
{% for post in posts %}
|
||||
<article class="media content-section">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }} ({{ post.author.role }})</a>
|
||||
<small class="text-muted float-right">{{ post.created_date.strftime('%H:%M %d-%m-%Y')}}</small>
|
||||
</div>
|
||||
<h2><a class="article-title" href="#">{{ post.title }}</a></h2>
|
||||
<p class="article-content">{{ post.content }}</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<p style="font-weight: bold;">Skriv opslag</p>
|
||||
<form method="POST" action="{{ url_for('Post.create')}}">
|
||||
{{ formpost.group_id(value=group.group_id) }}
|
||||
{{ formpost.author_id(value=current_user.cpr_num) }}
|
||||
<div class="row">
|
||||
<div class="col-md-4">{{ formpost.title(class="form-control", placeholder="Title") }}</div>
|
||||
<div class="col-md-8">{{ formpost.content(class="form-control", placeholder="Indhold") }}</div>
|
||||
<div class="col-md-12 mt-2">{{ formpost.submit(class="btn btn-primary btn-block btn-sm", value="Opret opslag") }}</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<p style="font-weight: bold;">Gruppe tråde</p>
|
||||
{% if threads|length == 0 %}
|
||||
<p>Gruppen har ingen tråde endnu</p>
|
||||
{% endif %}
|
||||
{% for thread in threads %}
|
||||
<p><a href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}">{{ thread.title }}</a></p>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
<form method="POST" action="{{ url_for('Threads.create')}}">
|
||||
{{ form.group_id(value=group.group_id) }}
|
||||
<p>{{ form.title(class="form-control", placeholder="Trådens title") }}</p>
|
||||
<p>{{ form.submit(class="btn btn-primary btn-block", value="Start tråd") }}</p>
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
|
||||
<p>Tilmeld dig gruppe for at se gruppe tråde og skrive opslag</p>
|
||||
<p><a class="btn btn-success btn-sm btn-block" href="{{ url_for('Group.join', group_id = group.group_id) }}">Tilmeld</a></p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<p>
|
||||
<hr>
|
||||
{% if group.mandatory %}
|
||||
<a class="btn btn-secondary btn-sm disabled" href="#">Obligatorisk gruppe</a>
|
||||
{% else %}
|
||||
<a class="btn btn-danger btn-sm btn-block" href="{{ url_for('Group.leave', group_id = group.group_id) }}">Forlad gruppen</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% endblock sidebar %}
|
@ -1,14 +1,43 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>Grupper</h1>
|
||||
<hr>
|
||||
{% if groups|length == 0%}
|
||||
<p>Ikke medlem af nogle grupper</p>
|
||||
{% else %}
|
||||
{% for group in groups %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
{{ group.name }}
|
||||
<p>
|
||||
<a class="group-name" href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.name }}</a>
|
||||
{% if not group.mandatory %}
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<a class="btn btn-danger btn-sm float-right" href="{{ url_for('Group.leave', group_id = group.group_id) }}">Afmeld</a>
|
||||
{% else %}
|
||||
<a class="btn btn-success btn-sm float-right" href="{{ url_for('Group.join', group_id = group.group_id) }}">Tilmeld</a>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<a class="btn btn-secondary btn-sm float-right" href="#" disabled>Obligatorisk</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block sidebar %}
|
||||
<p style="font-weight: bold;">Opret gruppe</p>
|
||||
{% if current_user.role == "Lærer" %}
|
||||
<form method="POST" action="{{ url_for('Group.create')}}">
|
||||
<p>{{ form.title(class="form-control", placeholder="Gruppens navn") }}</p>
|
||||
|
||||
<p>{{ form.mandatory() }} {{ form.mandatory.label(class="form-check-label") }}</p>
|
||||
<p>{{ form.submit(class="btn btn-primary btn-block") }}</p>
|
||||
</form>
|
||||
{% else %}
|
||||
<p>Denne funktion er kun tilgængelig for lærer</p>
|
||||
{% endif %}
|
||||
{% endblock sidebar %}
|
||||
|
@ -8,17 +8,19 @@
|
||||
<article class="media content-section">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2" href="#">{{ post.author_name }}</a>
|
||||
<small class="text-muted">{{ post.date_posted }}</small>
|
||||
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }}</a>
|
||||
<small class="text-muted float-right">{{ post.created_date.strftime('%H:%M %d-%m-%Y')}}</small>
|
||||
</div>
|
||||
<h2><a class="article-title" href="#">{{ post.title }}</a></h2>
|
||||
<p class="article-content">{{ post.content }}</p>
|
||||
<a class="group-name" href="#">
|
||||
{{ post.group_name }}
|
||||
<a class="group-name" href="{{ url_for('Group.show', group_id = post.group.group_id) }}">
|
||||
{{ post.group.name }}
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<h1>Forside</h1>
|
||||
<p>Login <a href="{{ url_for('Login.login') }}">her</a></p>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
@ -1,79 +0,0 @@
|
||||
{% 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 %}
|
@ -31,8 +31,8 @@
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<div class="navbar-nav mr-auto">
|
||||
<a class="nav-item nav-link" href="{{ url_for('Login.home') }}">Forside</a>
|
||||
<a class="nav-item nav-link" href="/">Grupper</a>
|
||||
<a class="nav-item nav-link" href="/">Tråde</a>
|
||||
<a class="nav-item nav-link" href="{{ url_for('Group.groups') }}">Grupper</a>
|
||||
<a class="nav-item nav-link" href="{{ url_for('Threads.threads') }}">Tråde</a>
|
||||
</div>
|
||||
<!-- Navbar Right Side -->
|
||||
<div class="navbar-nav">
|
||||
@ -59,10 +59,12 @@
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="content-section">
|
||||
{% block sidebar %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,100 +0,0 @@
|
||||
<!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>
|
@ -6,16 +6,16 @@
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4">Log In</legend>
|
||||
<div class="form-group">
|
||||
{{ form.email.label(class="form-control-label") }}
|
||||
{% if form.email.errors %}
|
||||
{{ form.email(class="form-control form-control-lg is-invalid") }}
|
||||
{{ form.cpr_num.label(class="form-control-label") }}
|
||||
{% if form.cpr_num.errors %}
|
||||
{{ form.cpr_num(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.email.errors %}
|
||||
{% for error in form.cpr_num.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.email(class="form-control form-control-lg") }}
|
||||
{{ form.cpr_num(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -45,3 +45,15 @@
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
|
||||
{% block sidebar %}
|
||||
<h3>Login Information</h3>
|
||||
<p style="font-weight:bold">Lærer</p>
|
||||
<p> Brugernavne: 5000</p>
|
||||
<p> Kodeord: UIS</p>
|
||||
<p style="font-weight:bold">Forældre</p>
|
||||
<p> Brugernavne: 5001-5005</p>
|
||||
<p> Kodeord: UIS</p>
|
||||
|
||||
{% endblock sidebar %}
|
||||
|
@ -1,70 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>Test Page</h1>
|
||||
<p>Dette er en testside. Hej med dig. <b>fed tekst,</b> <i>kursiv tekst</i> </p>
|
||||
<p><b>fed tekst, <i>fed og kursiv tekst</i></b></p>
|
||||
|
||||
<p>Liste af ansatte:</p>
|
||||
<ul>
|
||||
{% for e in emp %}
|
||||
<li>{{ e[1] }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<form method="POST" action="">
|
||||
{{ form.hidden_tag() }}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4">Add a new employee</legend>
|
||||
<!-- Id-felt -->
|
||||
<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>
|
||||
<!-- Username-felt -->
|
||||
<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>
|
||||
<!-- Password-felt -->
|
||||
<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>
|
||||
<!-- Submit-knap -->
|
||||
<div class="form-group">
|
||||
{{ form.submit(class="btn btn-outline-info") }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
37
aula/templates/thread_show.html
Normal file
37
aula/templates/thread_show.html
Normal file
@ -0,0 +1,37 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<div class="thread content-section">
|
||||
<h1>{{ thread.title }}</h1>
|
||||
<div id="messages" class="messages">
|
||||
{% for message in messages %}
|
||||
{% if message.author.cpr_num == current_user.cpr_num %}
|
||||
<div class="message-container self">
|
||||
{% else %}
|
||||
<div class="message-container">
|
||||
{% endif %}
|
||||
<div class="content-section message">
|
||||
<a class="author-name" href="#">{{ message.author.first_name }} ({{ message.author.role }})</a>
|
||||
<p>{{ message.content }}</p>
|
||||
</div>
|
||||
<p class="timestamp">{{ message.created_date }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="new-message">
|
||||
<form method="POST" action="">
|
||||
{{ form.hidden_tag() }}
|
||||
{{ form.besked(class="message-box") }}
|
||||
{{ form.submit(class="send") }}
|
||||
</form>
|
||||
</div>
|
||||
<script>
|
||||
var objDiv = document.getElementById("messages");
|
||||
objDiv.scrollTop = objDiv.scrollHeight;
|
||||
</script>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
{% block sidebar %}
|
||||
<a class="group-name" href="{{ url_for('Group.show', group_id = thread.group_id) }}">{{thread.group.name}}</a>
|
||||
|
||||
{% endblock sidebar %}
|
@ -1,46 +1,11 @@
|
||||
{% 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>
|
||||
|
||||
<h1>Tråde</h1>
|
||||
<hr>
|
||||
{% for thread in threads %}
|
||||
<div class="content-section">
|
||||
<a class="thread-name" href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}"">{{thread.title}}</a>
|
||||
<a class="float-right group-name" href="{{ url_for('Group.show', group_id = thread.group_id) }}">{{thread.group.name}}</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock content %}
|
||||
|
@ -1,46 +0,0 @@
|
||||
{% 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 %}
|
@ -1,49 +0,0 @@
|
||||
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)
|
||||
|
||||
|
@ -1,71 +0,0 @@
|
||||
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)
|
@ -1,52 +0,0 @@
|
||||
from flask import render_template, url_for, flash, redirect, request, Blueprint
|
||||
from bank import bcrypt
|
||||
from bank.forms import CustomerLoginForm, EmployeeLoginForm
|
||||
from flask_login import login_user, current_user, logout_user, login_required
|
||||
from bank.models import 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')
|
@ -1,26 +0,0 @@
|
||||
from flask import render_template, url_for, flash, redirect, request, Blueprint
|
||||
from bank import app, conn, bcrypt
|
||||
from bank.forms import AddEmployeeForm
|
||||
from flask_login import login_user, current_user, logout_user, login_required
|
||||
from bank.models import select_all_Employees, insert_Employees
|
||||
|
||||
Pax = Blueprint('Pax', __name__)
|
||||
|
||||
posts = [{}]
|
||||
|
||||
|
||||
@Pax.route("/test", methods=['GET', 'POST'])
|
||||
def test():
|
||||
form = AddEmployeeForm()
|
||||
# Nedenstånde kode køres kun ved POST-forespørgsler:
|
||||
if form.validate_on_submit():
|
||||
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
|
||||
id=form.id.data
|
||||
name=form.username.data
|
||||
password=hashed_password
|
||||
insert_Employees(id, name, password)
|
||||
flash('Employee has been created! The employee is now able to log in', 'success')
|
||||
return redirect(url_for('Login.home'))
|
||||
# Og denne køres GET-forespørgsler:
|
||||
employees = select_all_Employees()
|
||||
return render_template('test.html', title='Hej med dig', emp=employees, form=form)
|
@ -1,26 +0,0 @@
|
||||
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
|
||||
from bank.Pax.routes import Pax
|
||||
app.register_blueprint(Login)
|
||||
app.register_blueprint(Customer)
|
||||
app.register_blueprint(Employee)
|
||||
app.register_blueprint(Pax)
|
||||
|
||||
#from bank import routes
|
@ -1,46 +0,0 @@
|
||||
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 AddEmployeeForm(FlaskForm):
|
||||
id = IntegerField('Id',
|
||||
validators=[DataRequired()])
|
||||
username = StringField('Username',
|
||||
validators=[DataRequired(), Length(min=2, max=20)])
|
||||
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')
|
214
bank/models.py
214
bank/models.py
@ -1,214 +0,0 @@
|
||||
# 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 insert_Employees(id, name, password):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
INSERT INTO Employees(id, name, password)
|
||||
VALUES (%s, %s, %s)
|
||||
"""
|
||||
cur.execute(sql, (id, name, 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 select_all_Employees():
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
SELECT * FROM Employees
|
||||
"""
|
||||
cur.execute(sql)
|
||||
tuple_resultset = cur.fetchall()
|
||||
cur.close()
|
||||
return tuple_resultset
|
||||
|
||||
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
101
bank/schema.sql
@ -1,101 +0,0 @@
|
||||
\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
|
@ -1,21 +0,0 @@
|
||||
--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;
|
@ -1,109 +0,0 @@
|
||||
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);
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
|
||||
|
||||
|
||||
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
BIN
bank/site.db
Binary file not shown.
@ -1,10 +0,0 @@
|
||||
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;
|
@ -1,5 +0,0 @@
|
||||
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 ;
|
@ -1,7 +0,0 @@
|
||||
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 ;
|
@ -1,8 +0,0 @@
|
||||
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
|
||||
;
|
@ -1,84 +0,0 @@
|
||||
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 li > .nav-item.nav-link {
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.site-header .navbar-nav .nav-link:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.site-header .navbar-nav .nav-link.active {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
{% 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 %}
|
||||
|
@ -1,4 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>{{ current_user.name }}</h1>
|
||||
{% endblock content %}
|
@ -1,59 +0,0 @@
|
||||
{% 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 %}
|
@ -1,16 +0,0 @@
|
||||
{% 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 %}
|
@ -1,79 +0,0 @@
|
||||
{% 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 %}
|
@ -1,105 +0,0 @@
|
||||
<!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('Pax.test') }}">Test</a>
|
||||
<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>
|
@ -1,100 +0,0 @@
|
||||
<!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>
|
@ -1,54 +0,0 @@
|
||||
{% 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 %}
|
@ -1,70 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>Test Page</h1>
|
||||
<p>Dette er en testside. Hej med dig. <b>fed tekst,</b> <i>kursiv tekst</i> </p>
|
||||
<p><b>fed tekst, <i>fed og kursiv tekst</i></b></p>
|
||||
|
||||
<p>Liste af ansatte:</p>
|
||||
<ul>
|
||||
{% for e in emp %}
|
||||
<li>{{ e[1] }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<form method="POST" action="">
|
||||
{{ form.hidden_tag() }}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4">Add a new employee</legend>
|
||||
<!-- Id-felt -->
|
||||
<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>
|
||||
<!-- Username-felt -->
|
||||
<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>
|
||||
<!-- Password-felt -->
|
||||
<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>
|
||||
<!-- Submit-knap -->
|
||||
<div class="form-group">
|
||||
{{ form.submit(class="btn btn-outline-info") }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
@ -1,46 +0,0 @@
|
||||
{% 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 %}
|
Reference in New Issue
Block a user