diff --git a/webinterface/$ b/webinterface/$ deleted file mode 100644 index 834e0dc8..00000000 --- a/webinterface/$ +++ /dev/null @@ -1,269 +0,0 @@ -from minibase.database.models import Company, Company_relation, Company_legal_entity -from minibase.database.models import Industry, Countries -from minibase.database.models import Person, Person_role, Person_competence -from minibase.database.models import Project, Project_element -from minibase import db -from numpy import genfromtxt - - -# Gets the id of company from the formated output defined at models.py for the Company Model -# The argument formatedCompanySelection is formated by SQLAlchemy in models.py files -# Please look there before changing anything here. -def getCompanyId(formatedCompanySelection): - text = formatedCompanySelection.split(",") - return text[2] # Corresponds to the ID of the Company - - -# Gets the id of Person's role -def getPersonRoleId(nameForId): - selection = Person_role.query.filter_by(name=nameForId).first() - return selection.id - - -# Gets the id of Person's competence -def getPersonCompetenceId(nameForId): - selection = Person_competence.query.filter_by(name=nameForId).first() - return selection.id - - -# Gets the country of the company based on it's id -def getCompanyCountry(companyId): - selection = Company.query.filter_by(id=companyId).first() - return selection.country_bill - - -# Gets the state of the company based on it's id -def getCompanyState(companyId): - selection = Company.query.filter_by(id=companyId).first() - return selection.street_bill - - -# Gets the city of the company based on it's id -def getCompanyCity(companyId): - selection = Company.query.filter_by(id=companyId).first() - return selection.city_bill - - -# Gets the Postal Code of the company based on it's id -def getCompanyPostCode(companyId): - selection = Company.query.filter_by(id=companyId).first() - return selection.post_code_bill - - -# Gets the Name of the street of the company based on it's id -def getCompanyStreetName(companyId): - selection = Company.query.filter_by(id=companyId).first() - return selection.street_bill - - -# Gets the Number of the street of the company based on it's id -def getCompanyStreetNo(companyId): - selection = Company.query.filter_by(id=companyId).first() - return selection.street_no_bill - - -# Returns the query of all awailable companie names on the table named Company -# Note that the formating is done during the SQLAlchemy Table declaration. -def person_role_choices(): - choices = Person_role.query.all() - return choices - - -# Returns the query of all awailable companie names on the table named Company -# Note that the formating is done during the SQLAlchemy Table declaration. -def person_competence_choices(): - choices = Person_competence.query.all() - return choices - - -# Returns the query of all awailable companie names on the table named Company -# Note that the formating is done during the SQLAlchemy Table declaration. -def company_choices(): - choices = Company.query.all() - return choices - - -# Retunrs the qurry of all awailable industrie names on the table named Industry -# Note that the formating is done during the SQLAlchemy Table declaration. -def company_industry_choices(): - choices = Industry.query.all() - return choices - - -# Retunrs the query of all awailable legal entity names on the table named Company_legal_entity -# Note that the formating is done during the SQLAlchemy Table declaration. -def company_legal_entity_choices(): - choices = Company_legal_entity.query.all() - return choices - - -# Retunrs the query of all awailable Relation names on the table named Company_relation -# Note that the formating is done during the SQLAlchemy Table declaration. -def company_relation_choices(): - choices = Company_relation.query.all() - return choices - - -# The Company Model has Industry Column as a foreign key and it requires the Industry's ID -# And not the name. so this function returns the right ID of the name shown at the -# Register Company Form -def getIndustryId(nameForId): - selection = Industry.query.filter_by(name=nameForId).first() # Gets the id of Role - return selection.id - - -# The Company Model has Relation Column as a foreign key and it requires the Industry's ID -# And not the name. so this function returns the right ID of the name shown at the -# Register Company Form -def getRelationId(nameForId): - selection = Company_relation.query.filter_by(name=nameForId).first() # Gets the id of Role - return selection.id - - -# The Company Model has Legal Entity Column as a foreign key and it requires the Industry's ID -# And not the name. so this function returns the right ID of the name shown at the -# Register Company Form -def getLegalEntityId(nameForId): - selection = Company_legal_entity.query.filter_by(name=nameForId).first() # Gets the id of Role - return selection.id - - -# Retunrs the query of all awailable Country names on the table named Countries -# Note that the formating is done during the SQLAlchemy Table declaration. -# Important note This table is ImporteD externally from a modifier SQL version of -# Github : https://github.com/dr5hn/countries-states-cities-database -def country_choices(): - choices = Countries.query.all() - return choices - -################################################################################################### -# CSV manipulation -################################################################################################### - -def openCsv(filename): - data = genfromtxt(filename, - delimiter=',', - skip_header=1, - dtype=None, - encoding='UTF-8') - return data.tolist() - - -def db_add_name_and_description(csv, table): - try: - csv_list = openCsv(csv) - for i in csv_list: - record = table(**{ - 'name': i[0], - 'description': i[1]}) - db.session.add(record) # Add all the records - db.session.commit() # Attempt to commit all the records - except: - db.session.rollback() # Rollback the changes on error - print("Error Ocured during <> upload to DB") - - -def db_add_company(csv): - try: - csv_list = openCsv(csv) - for i in csv_list: - record = Company(**{ - 'name': i[0], - 'legal_entity_id': i[1], - 'relation_id': i[2], - 'industry_id': i[3], - 'status_id': i[4], - 'website': i[5], - 'street_bill': i[6], - 'street_no_bill': i[7], - 'city_bill': i[8], - 'post_code_bill': i[9], - 'state_bill': i[10], - 'country_bill': i[11], - 'street_ship': i[12], - 'street_no_ship': i[13], - 'city_ship': i[14], - 'post_code_ship': i[15], - 'state_ship': i[16], - 'country_ship': i[17]}) - db.session.add(record) # Add all the records - db.session.commit() # Attempt to commit all the records - except Exception as error: - db.session.rollback() # Rollback the changes on error - print("Error Ocured during <> upload to DB") - print(error) - - -def db_add_person(csv): - try: - csv_list = openCsv(csv) - print(csv_list) - for i in csv_list: - record = Person(**{ - 'name': i[0], - 'last_name': i[1], - 'company_id': i[2], - 'role_id': i[3], - 'competence_id': i[4], - 'mail_prof': i[5], - 'mail_priv': i[6], - 'tel_prof_mobile': i[7], - 'street_name': i[8], - 'street_no': i[9], - 'city': i[10], - 'post_code': i[11], - 'state': i[12], - 'country': i[13] - }) - db.session.add(record) # Add all the records - db.session.commit() # Attempt to commit all the records - except Exception as error: - db.session.rollback() # Rollback the changes on error - print("Error Ocured during <> upload to DB") - print(error) - - -def db_add_project(csv): - try: - csv_list = openCsv(csv) - print(csv_list) - for i in csv_list: - record = Project(**{ - 'name': i[0], - 'description': i[1], - 'company_id': i[2], - 'status_id': i[3], - 'industry_id': i[4], - 'owner_id': i[5], - 'qte_prototype': i[6], - 'qte_start': i[7], - 'qte_production': i[8], - }) - db.session.add(record) # Add all the records - db.session.commit() # Attempt to commit all the records - except Exception as error: - db.session.rollback() # Rollback the changes on error - print(csv) - print("Error Ocured during <> upload to DB") - print(error) - -def db_add_project_element(csv): - try: - csv_list = openCsv(csv) - print(csv_list) - for i in csv_list: - record = Project_element(**{ - 'name': i[0], - 'description': i[1], - 'qte_per_project': i[2], - 'project_id': i[3], - 'owner_id': i[4], - 'status_id': i[5], - }) - db.session.add(record) # Add all the records - db.session.commit() # Attempt to commit all the records - except Exception as error: - db.session.rollback() # Rollback the changes on error - print(csv) - print("Error Ocured during <> upload to DB") - print(error) diff --git a/webinterface/__pycache__/test.cpython-311.pyc b/webinterface/__pycache__/test.cpython-311.pyc new file mode 100644 index 00000000..58451a91 Binary files /dev/null and b/webinterface/__pycache__/test.cpython-311.pyc differ diff --git a/webinterface/flask_session/2029240f6d1128be89ddc32729463129 b/webinterface/flask_session/2029240f6d1128be89ddc32729463129 new file mode 100644 index 00000000..ffb2cd9b Binary files /dev/null and b/webinterface/flask_session/2029240f6d1128be89ddc32729463129 differ diff --git a/webinterface/flask_session/85d4d4491cdf35f65aeeb65c2150079b b/webinterface/flask_session/85d4d4491cdf35f65aeeb65c2150079b new file mode 100644 index 00000000..9ae1a868 Binary files /dev/null and b/webinterface/flask_session/85d4d4491cdf35f65aeeb65c2150079b differ diff --git a/webinterface/flask_session/c955664f3c1afea310d3fa9de93b2054 b/webinterface/flask_session/c955664f3c1afea310d3fa9de93b2054 new file mode 100644 index 00000000..e7645c84 Binary files /dev/null and b/webinterface/flask_session/c955664f3c1afea310d3fa9de93b2054 differ diff --git a/webinterface/flask_session/f397c9806198dce1bc23d1226063df58 b/webinterface/flask_session/f397c9806198dce1bc23d1226063df58 new file mode 100644 index 00000000..0f7de990 Binary files /dev/null and b/webinterface/flask_session/f397c9806198dce1bc23d1226063df58 differ diff --git a/webinterface/instance/site.db b/webinterface/instance/site.db new file mode 100644 index 00000000..e1f92aed Binary files /dev/null and b/webinterface/instance/site.db differ diff --git a/webinterface/minibase/__init__.py b/webinterface/minibase/__init__.py index 785930e7..bdbf8ca8 100644 --- a/webinterface/minibase/__init__.py +++ b/webinterface/minibase/__init__.py @@ -1,6 +1,7 @@ from flask import Flask +from flask_session import Session + from flask_sqlalchemy import SQLAlchemy -from sqlalchemy.ext.declarative import declarative_base from flask_bcrypt import Bcrypt from flask_login import LoginManager from flask_mail import Mail @@ -16,6 +17,7 @@ login_manager.login_view = 'users.login' login_manager.login_message_category = 'info' # Boostrap Info Message # (EMAIL AGENT) Definition mail = Mail() +session = Session() def create_minibase(config_class=Config): @@ -31,14 +33,16 @@ def create_minibase(config_class=Config): login_manager.init_app(app) # (EMAIL AGENT) Initialisation mail.init_app(app) - # (FLASK) Importing and then registering Blueprints (Wievs) + # Session for variable manipulation on server side + # (FLASK) Importing and then registering Blueprints (Wievs) from minibase.users.routes import users from minibase.posts.routes import posts from minibase.main.routes import main from minibase.company.routes import company from minibase.admin.routes import admin from minibase.person.routes import person + from minibase.project.routes import project from minibase.errors.handlers import errors app.register_blueprint(users) app.register_blueprint(posts) @@ -46,6 +50,7 @@ def create_minibase(config_class=Config): app.register_blueprint(company) app.register_blueprint(admin) app.register_blueprint(person) + app.register_blueprint(project) app.register_blueprint(errors) - # Returnr The created app + # Return The created app return app diff --git a/webinterface/minibase/__pycache__/__init__.cpython-311.pyc b/webinterface/minibase/__pycache__/__init__.cpython-311.pyc index 6bb6acb3..36b3786b 100644 Binary files a/webinterface/minibase/__pycache__/__init__.cpython-311.pyc and b/webinterface/minibase/__pycache__/__init__.cpython-311.pyc differ diff --git a/webinterface/minibase/admin/__pycache__/utils.cpython-311.pyc b/webinterface/minibase/admin/__pycache__/utils.cpython-311.pyc index 8d9728b6..30cac5ad 100644 Binary files a/webinterface/minibase/admin/__pycache__/utils.cpython-311.pyc and b/webinterface/minibase/admin/__pycache__/utils.cpython-311.pyc differ diff --git a/webinterface/minibase/admin/utils.py b/webinterface/minibase/admin/utils.py index 8dec0b43..dde13b5d 100644 --- a/webinterface/minibase/admin/utils.py +++ b/webinterface/minibase/admin/utils.py @@ -1,6 +1,6 @@ def doesNameExistsCi(table, name): - exists = table.query.filter(table.name.ilike(name.data)).first() # Database Querry ilike means case insessitive + exists = table.query.filter(table.name.ilike(name)).first() # Database Querry ilike means case insessitive if exists: return 1 return 0 diff --git a/webinterface/minibase/company/__pycache__/forms.cpython-311.pyc b/webinterface/minibase/company/__pycache__/forms.cpython-311.pyc index 44326d88..4ae08eb7 100644 Binary files a/webinterface/minibase/company/__pycache__/forms.cpython-311.pyc and b/webinterface/minibase/company/__pycache__/forms.cpython-311.pyc differ diff --git a/webinterface/minibase/company/forms.py b/webinterface/minibase/company/forms.py index 82e3baf6..e6aa6ba5 100644 --- a/webinterface/minibase/company/forms.py +++ b/webinterface/minibase/company/forms.py @@ -2,23 +2,23 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, IntegerField, SelectField from wtforms.validators import DataRequired, Length, ValidationError, Optional from minibase.database.models import Company -import minibase.database.utils as DbUtils +import minibase.database.utils as dbUtils # Defines the form class to be used for the user registretion class companyForm(FlaskForm): # Decalarion of the fields for the form and it's propereties company_name = StringField('Name', validators=[DataRequired(), Length(min=3, max=20)]) - legal_entity_id = SelectField('Legal Entity', choices=DbUtils.company_legal_entity_choices, validators=[DataRequired()]) - relation_id = SelectField('Relation', choices=DbUtils.company_relation_choices, validators=[DataRequired()]) + legal_entity_id = SelectField('Legal Entity', choices=dbUtils.company_legal_entity_choices, validators=[DataRequired()]) + relation_id = SelectField('Relation', choices=dbUtils.company_relation_choices, validators=[DataRequired()]) website = StringField('Website', validators=[Optional(), Length(min=3, max=100)]) - country = SelectField('Country', choices=DbUtils.country_choices,validators=[DataRequired()]) + country = SelectField('Country', choices=dbUtils.getCountryNames,validators=[DataRequired()]) state = StringField('State', validators=[DataRequired()]) city = StringField('City', validators=[DataRequired()]) post = IntegerField('Zip', validators=[DataRequired()]) street = StringField('Street', validators=[DataRequired()]) no = IntegerField('No', validators=[DataRequired()]) - industry_id = SelectField('Area', choices=DbUtils.company_industry_choices, validators=[DataRequired()]) + industry_id = SelectField('Area', choices=dbUtils.getIndustryNames, validators=[DataRequired()]) submit = SubmitField('Register Company') # Queries to be made in order to validate the form : If Company name exitst within the same country diff --git a/webinterface/minibase/database/.~lock.person.csv# b/webinterface/minibase/database/.~lock.person.csv# new file mode 100644 index 00000000..06be6b1b --- /dev/null +++ b/webinterface/minibase/database/.~lock.person.csv# @@ -0,0 +1 @@ +,key,devbian,20.10.2023 11:27,file:///home/key/.config/libreoffice/4; \ No newline at end of file diff --git a/webinterface/minibase/database/__pycache__/models.cpython-311.pyc b/webinterface/minibase/database/__pycache__/models.cpython-311.pyc index c3e87c67..5919df73 100644 Binary files a/webinterface/minibase/database/__pycache__/models.cpython-311.pyc and b/webinterface/minibase/database/__pycache__/models.cpython-311.pyc differ diff --git a/webinterface/minibase/database/__pycache__/utils.cpython-311.pyc b/webinterface/minibase/database/__pycache__/utils.cpython-311.pyc index b46f2571..3cb898e7 100644 Binary files a/webinterface/minibase/database/__pycache__/utils.cpython-311.pyc and b/webinterface/minibase/database/__pycache__/utils.cpython-311.pyc differ diff --git a/webinterface/minibase/database/models.py b/webinterface/minibase/database/models.py index 36249d2d..a749f279 100644 --- a/webinterface/minibase/database/models.py +++ b/webinterface/minibase/database/models.py @@ -1,4 +1,4 @@ -from itsdangerous import TimedJSONWebSignatureSerializer as Serializer +from itsdangerous import URLSafeTimedSerializer as Serializer from datetime import datetime from minibase import db, login_manager from flask_login import UserMixin @@ -49,7 +49,6 @@ class Post(db.Model): def __repr__(self): return f"User('{self.title}', '{self.date_posted}')" - ################################################################################################### # ADMIN ################################################################################################### @@ -107,6 +106,7 @@ class Note_status(db.Model): last_update_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow) company_notes = db.relationship('Company_note', backref='company_note_status', lazy=True) person_notes = db.relationship('Person_note', backref='person_note_status', lazy=True) + project_notes = db.relationship('Project_note', backref='project_note_status', lazy=True) # returns a more information-rich, or official, string representation of an object def __repr__(self): @@ -172,8 +172,11 @@ class Person(db.Model): # One To Many relationships for a company having mutliple elements of the following indexes # Example : One company would/could have many eployees notes = db.relationship('Person_note', backref='person', lazy=True) - projects = db.relationship('Project', backref='project_responsible', lazy=True) - elements = db.relationship('Project', backref='element_responsible', lazy=True) + projects = db.relationship('Project', backref='project_responsible', lazy=True, viewonly=True) + elements = db.relationship('Project', backref='element_responsible', lazy=True, viewonly=True) + + def __repr__(self): + return f"{self.name} {' '} {self.last_name}" class Person_role(db.Model): @@ -299,7 +302,8 @@ class Company_note(db.Model): # returns a more information-rich, or official, string representation of an object def __repr__(self): - return f"{self.title}, {self.status}, {self.content}" + return f"{self.title}, {self.content}" + ################################################################################################### # Project @@ -316,8 +320,9 @@ class Project(db.Model): qte_production = db.Column(db.Integer, nullable=False) upload_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) last_update_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow) + image_file = db.Column(db.String(30), nullable=False, default='default_project.jpg') - # One To Many relationships where indexes can point o mutiple companies. + # One To Many relationships where indexes can point o mutiple compani30. company_id = db.Column(db.Integer, db.ForeignKey('company.id'), nullable=False) status_id = db.Column(db.Integer, db.ForeignKey('project_status.id'), nullable=False) industry_id = db.Column(db.Integer, db.ForeignKey('industry.id'), nullable=False) @@ -326,6 +331,7 @@ class Project(db.Model): # One To Many relationships for a company having mutliple elements of the following indexes # Example : One company would/could have many eployees elements = db.relationship('Project_element', backref='project', lazy=True) + notes = db.relationship('Project_note', backref='project', lazy=True) # returns a more information-rich, or official, string representation of an object def __repr__(self): @@ -354,13 +360,29 @@ class Project_status(db.Model): upload_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) last_update_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow) - projects = db.relationship('Project', backref='status', lazy=True) - elements = db.relationship('Project', backref='element_status', lazy=True) + projects = db.relationship('Project', backref='status', lazy=True, viewonly=True) + elements = db.relationship('Project', backref='element_status', lazy=True, viewonly=True) # returns a more information-rich, or official, string representation of an object def __repr__(self): return f"{self.name}" + +class Project_note(db.Model): + id = db.Column(db.Integer, primary_key=True) + priority = db.Column(db.Integer, nullable=False, default='0') + title = db.Column(db.String(100), nullable=False) + content = db.Column(db.Text, nullable=False) + date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + date_due = db.Column(db.DateTime, nullable=False, default=datetime.utcnow) + + project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) + status_id = db.Column(db.Integer, db.ForeignKey('note_status.id'), nullable=False) + + # returns a more information-rich, or official, string representation of an object + def __repr__(self): + return f"{self.title}, {self.content}" + ################################################################################################### # Product ################################################################################################### diff --git a/webinterface/minibase/database/person.csv b/webinterface/minibase/database/person.csv index 41ae2d9b..d406c4f6 100644 --- a/webinterface/minibase/database/person.csv +++ b/webinterface/minibase/database/person.csv @@ -1,3 +1,5 @@ name,last_name,company_id,role_id,competence_id,mail_prof,mail_priv,tel_prof_mobile,street_name,street_no,city,post_code,state,country -Kerem,Yollu,2,3,1,kerem.yollu_at_kynsight.com,kerem.yollu@gmail.com,41789716697,Meierackerstrasse,10,Uster,8610,Zürich,Switzerland -Stefan,Walker,1,2,2,stefan.walker_at_steinel.ch,stefan.walker@gmail.com,41789716697,Almeinderstrasse,10,Einsiedeln,8410,Schwyz,Switzerland +Kerem,Yollu,2,3,1,kerem.yollu@kynsight.com,kerem.yollu@gmail.com,41789716697,Meierackerstrasse,10,Uster,8610,Zürich,Switzerland +Stefan,Walker,1,2,2,stefan.walker@steinel.ch,stefan.walker@gmail.com,41789716697,Almeinderstrasse,10,Einsiedeln,8410,Schwyz,Switzerland +Meier,Müller,1,2,2,meier.mueller@steinel.ch,meier.mueller@steinel.ch,41789716697,Almeinderstrasse,10,Einsiedeln,8410,Schwyz,Switzerland +Suleyman,Siksok,1,2,2,suleyman.siksok@steinel.ch,suleyman.siksok@steinel.ch,41789716697,Almeinderstrasse,10,Einsiedeln,8410,Schwyz,Switzerland diff --git a/webinterface/minibase/database/utils.py b/webinterface/minibase/database/utils.py index 2f6a7285..299d8d93 100644 --- a/webinterface/minibase/database/utils.py +++ b/webinterface/minibase/database/utils.py @@ -1,10 +1,13 @@ from minibase.database.models import Company, Company_relation, Company_legal_entity from minibase.database.models import Industry, Countries from minibase.database.models import Person, Person_role, Person_competence -from minibase.database.models import Project, Project_element, Product +from minibase.database.models import Project, Project_element, Project_status, Project_note +from minibase.database.models import Product from minibase import db from numpy import genfromtxt +selectedCompany=0 +selectedProject=0 # Gets the id of company from the formated output defined at models.py for the Company Model # The argument formatedCompanySelection is formated by SQLAlchemy in models.py files @@ -26,6 +29,12 @@ def getPersonCompetenceId(nameForId): return selection.id +# Gets the name based on Person's id +def getPersonName(personId): + selection = Person.query.filter_by(id=personId).first() + return selection + + # Gets the country of the company based on it's id def getCompanyCountry(companyId): selection = Company.query.filter_by(id=companyId).first() @@ -62,7 +71,108 @@ def getCompanyStreetNo(companyId): return selection.street_no_bill -# Returns the query of all awailable companie names on the table named Company +# Gets the names the all the companies +def getCompanyNames(): + selection = Company.query.order_by(Company.name.asc()) + return selection + + +# Gets the Name of the street of the company based on it's id +def getCompanyName(companyId): + selection = Company.query.filter_by(id=companyId).first() + return selection.name + +#################################################################################################### +# Gets the Project class of based on it's id +def getProject(projectId): + selection = Project.query.filter_by(id=projectId).first() + return selection + +# Gets the names the all the projects +def getProjectNames(): + selection = Project.query.order_by(Project.name.asc()) + return selection + +# Gets the awailable Statuses of all the projects +def getProjectStatuses(): + selection = Project_status.query.order_by(Project_status.name.asc()) + return selection + +# Gets the Name of the street of the company based on it's id +def getProjectName(projectId): + selection = Project.query.filter_by(id=projectId).first() + return selection.name + + +# Defines the selected company for the current request. This is important to fill so that some +# Templates knows if they have to show something and warns the user if no compani was selected +def setSelectedCompany(company_id): + global selectedCompany + selectedCompany = int(company_id) + + +# Returns the Selected company +def getSelectedCompany(): + global selectedCompany + return selectedCompany + + +# Get the list of projects for the selected Company and if no company was selected +# Prints an error that will be put in the selection form. +def getProjectOfSelectedCompany(): + global selectedCompany + if selectedCompany: + selection = Project.query.filter_by(company_id=selectedCompany) + return selection + return ["No company is selected"] + +# Get the list of projects for the selected Company and if no company was selected +# Prints an error that will be put in the selection form. +def getEmployeesOfSelectedCompany(): + global selectedCompany + if selectedCompany: + selection = Person.query.filter_by(company_id=selectedCompany) + return selection + return ["No company is selected"] + + +# Defines the selected project for the current request. This is important to fill so that some +# Templates knows if they have to show something and warns the user if no compani was selected +def setSelectedProject(project_id): + global selectedProject + selectedProject = int(project_id) + + +# Returns the Selected project +def getSelectedProject(): + return selectedProject + + +def getSelectedProjectOwner(): + global selectedProject + if selectedProject: + selection = Project.query.filter_by(id=selectedProject).first() + return getPersonName(selection.project_responsible.id) + return ["No Project is selected"] + + +def getSelectedProjectNotes(): + global selectedProject + if selectedProject: + selection = Project_note.query.filter_by(project_id=selectedProject) + return selection + return ["No Project is selected"] + + +# Get the project id based on the project's name and compan's id +# As they can be project's that have the same name but corresponds to different companies. +def getProjectId(companyId, projectName): + global selectedCompany + selection = Project.query.filter_by(company_id=companyId, name=projectName).first() + return selection.id + + +# Returns the query of all awailable companie names on the table named Project # Note that the formating is done during the SQLAlchemy Table declaration. def person_role_choices(): choices = Person_role.query.all() @@ -76,16 +186,9 @@ def person_competence_choices(): return choices -# Returns the query of all awailable companie names on the table named Company -# Note that the formating is done during the SQLAlchemy Table declaration. -def company_choices(): - choices = Company.query.all() - return choices - - # Retunrs the qurry of all awailable industrie names on the table named Industry # Note that the formating is done during the SQLAlchemy Table declaration. -def company_industry_choices(): +def getIndustryNames(): choices = Industry.query.all() return choices @@ -132,10 +235,11 @@ def getLegalEntityId(nameForId): # Note that the formating is done during the SQLAlchemy Table declaration. # Important note This table is ImporteD externally from a modifier SQL version of # Github : https://github.com/dr5hn/countries-states-cities-database -def country_choices(): +def getCountryNames(): choices = Countries.query.all() return choices + ################################################################################################### # CSV manipulation ################################################################################################### diff --git a/webinterface/minibase/person/__pycache__/forms.cpython-311.pyc b/webinterface/minibase/person/__pycache__/forms.cpython-311.pyc index b183639d..ec27b333 100644 Binary files a/webinterface/minibase/person/__pycache__/forms.cpython-311.pyc and b/webinterface/minibase/person/__pycache__/forms.cpython-311.pyc differ diff --git a/webinterface/minibase/person/forms.py b/webinterface/minibase/person/forms.py index 0c51c43c..83eb118c 100644 --- a/webinterface/minibase/person/forms.py +++ b/webinterface/minibase/person/forms.py @@ -2,7 +2,7 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, SelectField, DateField from wtforms.validators import DataRequired, Length, ValidationError, Email, Optional from minibase.database.models import Person -import minibase.database.utils as DbUtils +import minibase.database.utils as dbUtils # Defines the form class to be used for the user registretion @@ -17,9 +17,9 @@ class personForm(FlaskForm): tel_prof_mobile = StringField('Tel Professional Mob', validators=[Optional()]) tel_priv_fix = StringField('Tel Private Fix', validators=[Optional()]) tel_priv_mobile = StringField('Tel Private Mob', validators=[Optional()]) - company_id = SelectField('Company', choices=DbUtils.company_choices, validators=[DataRequired()]) - competence_id = SelectField('Competence', choices=DbUtils.person_competence_choices, validators=[DataRequired()]) - role_id = SelectField('Role', choices=DbUtils.person_role_choices, validators=[DataRequired()]) + company_id = SelectField('Company', choices=dbUtils.getCompanyNames, validators=[DataRequired()]) + competence_id = SelectField('Competence', choices=dbUtils.person_competence_choices, validators=[DataRequired()]) + role_id = SelectField('Role', choices=dbUtils.person_role_choices, validators=[DataRequired()]) submit = SubmitField('Register Person') # Queries to be made in order to validate the form : If person with this name exitst within the same company diff --git a/webinterface/minibase/project/__pycache__/forms.cpython-311.pyc b/webinterface/minibase/project/__pycache__/forms.cpython-311.pyc new file mode 100644 index 00000000..07b093f3 Binary files /dev/null and b/webinterface/minibase/project/__pycache__/forms.cpython-311.pyc differ diff --git a/webinterface/minibase/project/__pycache__/routes.cpython-311.pyc b/webinterface/minibase/project/__pycache__/routes.cpython-311.pyc new file mode 100644 index 00000000..66efdbe4 Binary files /dev/null and b/webinterface/minibase/project/__pycache__/routes.cpython-311.pyc differ diff --git a/webinterface/minibase/project/forms.py b/webinterface/minibase/project/forms.py index e69de29b..ccc79d1d 100644 --- a/webinterface/minibase/project/forms.py +++ b/webinterface/minibase/project/forms.py @@ -0,0 +1,48 @@ +from flask_wtf import FlaskForm +from wtforms import SubmitField, SelectField, DateField, IntegerField, StringField +from wtforms.validators import DataRequired, Length, ValidationError +from flask_wtf.file import FileField, FileAllowed +import minibase.database.utils as dbUtils + + +class getCompanyNameForm(FlaskForm): # Defines the form class to be used for the user registretion + # Decalarion of the fields for the form and it's propereties + company = SelectField('Company Name', choices=dbUtils.getCompanyNames, validators=[DataRequired()]) + submit = SubmitField('Show Projects') + + +class getProjectNameForm(FlaskForm): # Defines the form class to be used for the user registretion + # Decalarion of the fields for the form and it's propereties + project = SelectField('Project Name', choices=dbUtils.getProjectOfSelectedCompany, validators=[DataRequired()]) + submit = SubmitField('Show Project details') + + +class projectRegisterForm(FlaskForm): + name = StringField('ProjectName', validators=[DataRequired(), Length(min=3, max=20)]) + description = StringField('ProjectName', validators=[DataRequired(), Length(min=3, max=300)]) + qtePrototype = IntegerField('Prototye Quantity', validators=[DataRequired()]) + datePrototye = DateField('Prototyping Date', validators=[DataRequired()]) + qteStart = IntegerField('Starting Quantity', validators=[DataRequired()]) + dateStart = DateField('Firts Starting Date', validators=[DataRequired()]) + qteStartProduction = IntegerField('Production Quantity', validators=[DataRequired()]) + dateProduction = DateField('Production Date', validators=[DataRequired()]) + company = SelectField('Company name', choices=dbUtils.getCompanyNames, validators=[DataRequired()]) + industry = SelectField('industry', choices=dbUtils.getIndustryNames, validators=[DataRequired()]) + picture = FileField('Update Profile Picture', validators=[FileAllowed(['jpg', 'png'])]) + submit = SubmitField('Register Project') + + +class projectUpdateForm(FlaskForm): + description = StringField('Description', validators=[DataRequired(), Length(min=3, max=300)]) + industry = SelectField('industry', validators=[DataRequired()]) + status = SelectField('Status', validators=[DataRequired()]) + responsible = SelectField('Repsonsible', validators=[DataRequired()]) + qtePrototype = IntegerField('Prototye Quantity', validators=[DataRequired()]) + datePrototype = DateField('Prototyping Date', validators=[DataRequired()]) + qteStart = IntegerField('Starting Quantity', validators=[DataRequired()]) + dateStart = DateField('Starting Date', validators=[DataRequired()]) + qteProduction = IntegerField('Production Quantity', validators=[DataRequired()]) + dateProduction = DateField('Production Date', validators=[DataRequired()]) + picture = FileField('Picture', validators=[FileAllowed(['jpg', 'png'])]) + submit = SubmitField('Update Project') + diff --git a/webinterface/minibase/project/routes.py b/webinterface/minibase/project/routes.py index 026bad8e..d71d4d08 100644 --- a/webinterface/minibase/project/routes.py +++ b/webinterface/minibase/project/routes.py @@ -1,37 +1,97 @@ -from flask import render_template, url_for, flash, redirect, request, Blueprint +from flask import render_template, url_for, flash, redirect, request, Blueprint, session from minibase import db from minibase.config import themeMinibase -from minibase.database.models import Company, Company_legal_entity, Company_relation,Company_status -from minibase.database.models import Industry, Note_status -from minibase.database.models import Person_role, Person_competence -from minibase.database.models import Project_status -from minibase.admin.forms import compLegalEntityForm, compRelationForm, industryRegisterForm,personRoleForm, personCompetenceForm, compStatusForm, noteStatusForm -from minibase.admin.forms import projectStatusForm +from minibase.project.forms import getProjectNameForm, getCompanyNameForm, projectUpdateForm +import minibase.database.utils as dbUtils +from minibase.database.models import Project, Company + # Declaring a blueprint project = Blueprint('project', __name__) -@admin.route("/register", methods=['GET', 'POST']) -def register(): - form = register() - legal_entities = Company_legal_entity.query.order_by(Company_legal_entity.name.asc()) +@project.route("/select_company", methods=['GET', 'POST']) +def select_company(): + form = getCompanyNameForm() if form.validate_on_submit(): - companyLegal = Company_legal_entity( - name=form.name.data, - description=form.description.data) - # Here we need to give the id of thr role as this is a foreign key - db.session.add(companyLegal) - db.session.commit() - - flash(f'{"Company Legal Entity registered!"}', 'success') - return render_template('admin/company_register_legal_entity.html', - title='Register Company Legal Entity', - legal_entities=legal_entities, - theme=themeMinibase, - form=form) + companyId = dbUtils.getCompanyId(form.company.data) + dbUtils.setSelectedCompany(companyId) + return redirect(url_for('project.select_project')) - return render_template('admin/company_register_legal_entity.html', - title='Register Company Legal Entity', - legal_entities=legal_entities, + return render_template('project/select_company.html', + title='Select Company Name', theme=themeMinibase, form=form) + + +@project.route("/select_project", methods=['GET', 'POST']) +def select_project(): + if dbUtils.getSelectedCompany(): # If a company is lesected + form = getProjectNameForm() + companyId = dbUtils.getSelectedCompany() + company_selected = dbUtils.getCompanyName(companyId) + if form.validate_on_submit(): + flash(f'{"Project Loaded"}', 'success') + projectId = dbUtils.getProjectId(companyId, form.project.data) + dbUtils.setSelectedProject(projectId) + return redirect(url_for('project.show_project')) + + return render_template('project/select_project.html', + title='Select Project Name for : ' + company_selected, + theme=themeMinibase, + form=form) + else: + return redirect(url_for('project.select_company')) + + + +@project.route("/show_project", methods=['GET', 'POST']) +def show_project(): + if dbUtils.getSelectedProject(): # If a project is lesected + form = projectUpdateForm() + projectId = dbUtils.getSelectedProject() + project = dbUtils.getProject(projectId) + image_file = url_for('static', filename='pics/' + project.image_file) + notes = dbUtils.getSelectedProjectNotes() + # To initiate choises as a list allow us to match it with the id's + form.responsible.choices = [(row.id, row.name +' '+row.last_name) for row in dbUtils.getEmployeesOfSelectedCompany()] + form.status.choices = [(row.id, row.name) for row in dbUtils.getProjectStatuses()] + form.industry.choices = [(row.id, row.name) for row in dbUtils.getIndustryNames()] + + if form.validate_on_submit(): + flash(f'{"Project Updated"}', 'success') + project.owner_id = int(form.responsible.data) + project.status_id = int(form.status.data) + project.description = form.description.data + project.qte_prototype = form.qtePrototype.data + project.qte_start = form.qteStart.data + project.qte_production = form.qteProduction.data + project.date_prototype = form.datePrototype.data + project.date_start = form.dateStart.data + project.date_production = form.dateProduction.data + db.session.add(project) + db.session.commit() + return redirect(url_for('project.show_project')) + elif request.method == 'GET': + form.responsible.data = str(project.owner_id) + form.status.data = str(project.status.id) + form.industry.data = str(project.industry_id) + form.description.data = project.description + form.qtePrototype.data = project.qte_prototype + form.qteStart.data = project.qte_start + form.qteProduction.data = project.qte_production + form.datePrototype.data = project.date_prototype + form.dateStart.data = project.date_start + form.dateProduction.data = project.date_production + + return render_template('project/show_project.html', + #title=project.belongs_to.name + ' : ' + project.name, + title="kerem", + companyName=project.belongs_to.name, + projectName=project.name, + projectId=project.id, + notes=notes, + image_file=image_file, + theme=themeMinibase, + form=form) + else: + return redirect(url_for('project.select_project')) diff --git a/webinterface/minibase/site.db b/webinterface/minibase/site.db index aaf4d73b..bea23c6e 100644 Binary files a/webinterface/minibase/site.db and b/webinterface/minibase/site.db differ diff --git a/webinterface/minibase/site.db.bak b/webinterface/minibase/site.db.bak new file mode 100644 index 00000000..ae68a5ed Binary files /dev/null and b/webinterface/minibase/site.db.bak differ diff --git a/webinterface/minibase/static/pics/default_project.jpg b/webinterface/minibase/static/pics/default_project.jpg new file mode 100644 index 00000000..38f286f6 Binary files /dev/null and b/webinterface/minibase/static/pics/default_project.jpg differ diff --git a/webinterface/minibase/templates/layout.html b/webinterface/minibase/templates/layout.html index 658b0204..f1197b18 100644 --- a/webinterface/minibase/templates/layout.html +++ b/webinterface/minibase/templates/layout.html @@ -1,5 +1,5 @@ - + @@ -69,8 +69,17 @@ Database - - +