diff --git a/app.py b/app.py
new file mode 100644
index 0000000..9128c27
--- /dev/null
+++ b/app.py
@@ -0,0 +1,76 @@
+import itertools
+from datetime import date
+from typing import List, Dict
+
+from dateutil import relativedelta as period
+from flask import Flask
+
+from db.access import fetch_european_departments, \
+ fetch_department_employees, \
+ fetch_american_departments, \
+ fetch_employees, \
+ fetch_departments, \
+ fetch_canadian_departments
+from models.department import Department
+
+app = Flask(__name__)
+
+
+@app.get("/")
+def index():
+ return "
Homepage HR Resources
"
+
+
+@app.errorhandler(404)
+@app.errorhandler(500)
+def handle_error(error):
+ return {
+ "status": error.code,
+ "description": error.description,
+ "name": error.name
+ }
+
+
+@app.get("/employee")
+def employees():
+ return {"employees": [e.to_json() for e in fetch_employees()]}
+
+
+def __employees_group_by_seniority(departments: List[Department]) -> Dict[str, dict]:
+ result = {}
+ for department in departments:
+ # Per ogni dipartimento ricerco i suoi impiegati
+ employees = fetch_department_employees(department.department_id)
+
+ # Raggruppo gli impiegati per anni di anzianità
+ employee_group_by_years = itertools.groupby(employees,
+ lambda e: period.relativedelta(date.today(), e.hire_date).years)
+
+ result[department.name] = {year: [e.to_json() for e in employees]
+ for (year, employees) in employee_group_by_years}
+
+ return result
+
+
+@app.get("/employee/all-by-seniority")
+def employees_by_seniority():
+ departments = fetch_departments()
+ return __employees_group_by_seniority(departments)
+
+
+@app.get("/employee/american-by-seniority")
+def american_employees_by_seniority():
+ american_departments = fetch_american_departments()
+ return __employees_group_by_seniority(american_departments)
+
+
+@app.get("/employee/canadian-by-seniority")
+def canadian_employees_by_seniority():
+ canadian_departments = fetch_canadian_departments()
+ return __employees_group_by_seniority(canadian_departments)
+
+
+@app.get("/employee/european-by-seniority")
+def european_employees_by_seniority():
+ european_departments = fetch_european_departments()
+ return __employees_group_by_seniority(european_departments)
diff --git a/db/access.py b/db/access.py
index 9daf80f..568beed 100644
--- a/db/access.py
+++ b/db/access.py
@@ -23,6 +23,100 @@ def __create_department(row):
))
+def fetch_departments() -> List[Department]:
+ """
+ Ricerca tutti i dipartimenti attivi
+ :return: elenco dei dipartimenti
+ """
+ with connect(db_url) as connection:
+ with connection.cursor(cursor_factory=dbopts.DictCursor) as cursor:
+ cursor.execute(
+ """
+ select
+ d.department_id,
+ d.department_name,
+ d.location_id,
+ l.postal_code,
+ l.street_address,
+ l.city,
+ l.state_province,
+ l.country_id
+ from
+ hr.departments d
+ left join hr.locations l on
+ d.location_id = l.location_id
+ """
+ )
+
+ departments = [__create_department(row) for row in cursor.fetchall()]
+
+ return departments
+
+
+def fetch_american_departments() -> List[Department]:
+ """
+ Ricerca tutti i dipartimenti presenti negli USA.
+ :return: elenco dei dipartimenti USA
+ """
+ with connect(db_url) as connection:
+ with connection.cursor(cursor_factory=dbopts.DictCursor) as cursor:
+ cursor.execute(
+ """
+ select
+ d.department_id,
+ d.department_name,
+ d.location_id,
+ l.postal_code,
+ l.street_address,
+ l.city,
+ l.state_province,
+ l.country_id
+ from
+ hr.departments d
+ left join hr.locations l on
+ d.location_id = l.location_id
+ where
+ l.country_id = 'US'
+ """
+ )
+
+ departments = [__create_department(row) for row in cursor.fetchall()]
+
+ return departments
+
+
+def fetch_canadian_departments() -> List[Department]:
+ """
+ Ricerca tutti i dipartimenti presenti in Canada.
+ :return: elenco dei dipartimenti canadesi
+ """
+ with connect(db_url) as connection:
+ with connection.cursor(cursor_factory=dbopts.DictCursor) as cursor:
+ cursor.execute(
+ """
+ select
+ d.department_id,
+ d.department_name,
+ d.location_id,
+ l.postal_code,
+ l.street_address,
+ l.city,
+ l.state_province,
+ l.country_id
+ from
+ hr.departments d
+ left join hr.locations l on
+ d.location_id = l.location_id
+ where
+ l.country_id = 'CA'
+ """
+ )
+
+ departments = [__create_department(row) for row in cursor.fetchall()]
+
+ return departments
+
+
def fetch_european_departments() -> List[Department]:
"""
Ricerca tutti i dipartimenti dei paesi europei dove sono presenti
@@ -78,13 +172,24 @@ def fetch_department_employees(department_id: int) -> List[Employee]:
e.job_id,
e.salary,
e.manager_id,
- e.department_id
+ e.department_id,
+ d.department_name,
+ l.location_id,
+ l.city,
+ l.postal_code,
+ l.state_province,
+ l.street_address,
+ l.country_id
from
hr.employees e
+ left join hr.departments d on
+ e.department_id = d.department_id
+ left join hr.locations l on
+ d.location_id = l.location_id
where
- e.department_id = {department_id}
+ e.department_id = %s
""",
- department_id
+ (department_id,)
)
# Prendo dal DB tutti i dipendenti di un dipartimento
@@ -99,7 +204,62 @@ def fetch_department_employees(department_id: int) -> List[Employee]:
job_id=row["job_id"],
salary=row["salary"],
manager_id=row["manager_id"],
- department=None
+ department=__create_department(row)
+ ))
+
+ return employees
+
+
+def fetch_employees() -> List[Employee]:
+ """
+ Ricerca tutti i dipendenti dell'azienda
+ :return: elenco dei dipendenti
+ """
+ employees = []
+ with connect(db_url) as connection:
+ with connection.cursor(cursor_factory=dbopts.DictCursor) as cursor:
+ cursor.execute(
+ f"""
+ select
+ e.employee_id,
+ e.first_name,
+ e.last_name,
+ e.email,
+ e.phone_number,
+ e.hire_date,
+ e.job_id,
+ e.salary,
+ e.manager_id,
+ e.department_id,
+ d.department_name,
+ l.location_id,
+ l.city,
+ l.postal_code,
+ l.state_province,
+ l.street_address,
+ l.country_id
+ from
+ hr.employees e
+ left join hr.departments d on
+ e.department_id = d.department_id
+ left join hr.locations l on
+ d.location_id = l.location_id
+ """
+ )
+
+ # Prendo dal DB tutti i dipendenti di un dipartimento
+ for row in cursor.fetchall():
+ employees.append(Employee(
+ employee_id=row["employee_id"],
+ first_name=row["first_name"],
+ last_name=row["last_name"],
+ email=row["email"],
+ phone_number=row["phone_number"],
+ hire_date=row["hire_date"],
+ job_id=row["job_id"],
+ salary=row["salary"],
+ manager_id=row["manager_id"],
+ department=__create_department(row)
))
return employees
diff --git a/main.py b/main.py
deleted file mode 100644
index 9a56ffd..0000000
--- a/main.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import itertools
-from datetime import date
-
-from dateutil import relativedelta as datedelta
-
-from db.access import fetch_european_departments, fetch_department_employees
-
-if __name__ == '__main__':
- # Ricerco tutti i dipartimenti europei
- for department in fetch_european_departments():
- print(f"\n####### Department of {department.name} #######\n")
- # Per ogni dipartimento ricerco i suoi impiegati
- employees = [employee for employee in fetch_department_employees(department.department_id)]
- for employee in employees:
- print(f"{employee.last_name} {employee.first_name}")
-
- print("\n")
- # Raggruppo gli impiegati per anni di anzianità
- calculate_seniority = lambda e: datedelta.relativedelta(date.today(), e.hire_date).years
- employee_group_by_years = itertools.groupby(employees, calculate_seniority)
- # Stampo i risultati dell'aggregazione
- for years_to_employees in employee_group_by_years:
- print(f"Employees with {years_to_employees[0]} years of seniority:")
- for employee in years_to_employees[1]:
- print(employee.last_name, employee.first_name)
- print("\n")
diff --git a/models/department.py b/models/department.py
index 876acf2..6b7194a 100644
--- a/models/department.py
+++ b/models/department.py
@@ -19,5 +19,12 @@ class Department:
def location_id(self) -> Location:
return self.__location
+ def to_json(self):
+ return {
+ 'department_id': self.__department_id,
+ 'name': self.__name,
+ 'location': self.__location.to_json() if self.__location is not None else None
+ }
+
def __str__(self):
return f"Department({self.__department_id}, {self.__name}, {self.__location})"
diff --git a/models/employee.py b/models/employee.py
index e78a2d0..f94575a 100644
--- a/models/employee.py
+++ b/models/employee.py
@@ -18,8 +18,8 @@ class Person:
class Employee(Person):
- def __init__(self, employee_id, first_name, last_name, email, phone_number,
- hire_date, department, job_id=0, salary=0, manager_id=0):
+ def __init__(self, employee_id: int, first_name: str, last_name: str, email: str, phone_number: str,
+ hire_date: date, department: Department, job_id: int = 0, salary: float = 0, manager_id: int = 0):
super().__init__(first_name, last_name)
self.__employee_id = employee_id
self.__email = email
@@ -62,6 +62,20 @@ class Employee(Person):
def manager_id(self) -> int:
return self.__manager_id
+ def to_json(self):
+ return {
+ 'employee_id': self.__employee_id,
+ 'first_name': self.first_name,
+ 'last_name': self.last_name,
+ 'email': self.__email,
+ 'hire_date': self.__hire_date,
+ 'department': self.__department.to_json() if self.__department is not None else None,
+ 'job_id': self.__job_id,
+ # FIXME devo gestire meglio i tipi decimali
+ 'salary': str(self.__salary),
+ 'manager_id': self.__manager_id
+ }
+
def __str__(self):
return f"Employee({self.__employee_id}, {self.first_name}, {self.last_name}, " \
f"{self.__email}, {self.__phone_number}, {self.__hire_date})"
diff --git a/models/location.py b/models/location.py
index 612cf58..7d73cb2 100644
--- a/models/location.py
+++ b/models/location.py
@@ -32,6 +32,16 @@ class Location:
def country_id(self) -> int:
return self.__country_id
+ def to_json(self):
+ return {
+ 'location_id': self.__location_id,
+ 'street_address': self.__street_address,
+ 'postal_code': self.__postal_code,
+ 'city': self.__city,
+ 'state_province': self.__state_province,
+ 'country_id': self.__country_id
+ }
+
def __str__(self):
return f"Location({self.__location_id}, {self.__postal_code}, " \
f"{self.__street_address}, {self.__city}, {self.__state_province}) "
diff --git a/requirements.txt b/requirements.txt
index 9f17428..cbe7c79 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
records~=0.5.3
psycopg2-binary~=2.9.1
setuptools~=57.0.0
-python-dateutil~=2.8.1
\ No newline at end of file
+python-dateutil~=2.8.1
+Flask~=2.0.1
\ No newline at end of file