From 2e1b532e5c818401b9e08417ee6ace03d9ae53b9 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Sun, 20 Jun 2021 10:31:04 +0200 Subject: [PATCH 1/6] Import struttura base del progetto --- .gitignore | 164 +++++++++++++++++++++++++++++++++++++++++++ Makefile | 5 ++ db/__init__.py | 0 db/access.py | 105 +++++++++++++++++++++++++++ main.py | 26 +++++++ models/__init__.py | 0 models/department.py | 23 ++++++ models/employee.py | 67 ++++++++++++++++++ models/location.py | 37 ++++++++++ requirements.txt | 4 ++ setup.py | 12 ++++ 11 files changed, 443 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 db/__init__.py create mode 100644 db/access.py create mode 100644 main.py create mode 100644 models/__init__.py create mode 100644 models/department.py create mode 100644 models/employee.py create mode 100644 models/location.py create mode 100644 requirements.txt create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..42e87b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,164 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/Python,Pycharm +# Edit at https://www.toptal.com/developers/gitignore?templates=Python,Pycharm + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea + +# CMake +cmake-build-*/ + +# File-based project format +*.iws + +# IntelliJ +out/ + +# JIRA plugin +atlassian-ide-plugin.xml + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# End of https://www.toptal.com/developers/gitignore/api/Python,Pycharm diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e25ebf0 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +init: + pip install -r requirements.txt + +test: + nosetests tests \ No newline at end of file diff --git a/db/__init__.py b/db/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/db/access.py b/db/access.py new file mode 100644 index 0000000..9daf80f --- /dev/null +++ b/db/access.py @@ -0,0 +1,105 @@ +from typing import List + +from psycopg2 import connect, extras as dbopts + +from models.department import Department +from models.employee import Employee +from models.location import Location + +db_url: str = 'postgresql://postgres:@localhost:5432/postgres' + + +def __create_department(row): + return Department( + department_id=row["department_id"], + name=row["department_name"], + location=Location( + location_id=row["location_id"], + postal_code=row["postal_code"], + street_address=row["street_address"], + state_province=row["state_province"], + country_id=row["country_id"], + city=row["city"] + )) + + +def fetch_european_departments() -> List[Department]: + """ + Ricerca tutti i dipartimenti dei paesi europei dove sono presenti + dei dipartimenti. + :return: elenco dei dipartimenti europei + """ + 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 in ('UK', 'DE') + """ + ) + + # Prendo dal DB tutti i dipartimenti presenti nel Regno Unito e Germania + departments = [__create_department(row) for row in cursor.fetchall()] + + return departments + + +def fetch_department_employees(department_id: int) -> List[Employee]: + """ + Ricerca tutti i dipendenti di un dipartimento + :param department_id: dipartimento da ricercare + :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 + from + hr.employees e + where + e.department_id = {department_id} + """, + department_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=None + )) + + return employees diff --git a/main.py b/main.py new file mode 100644 index 0000000..9a56ffd --- /dev/null +++ b/main.py @@ -0,0 +1,26 @@ +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/__init__.py b/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/models/department.py b/models/department.py new file mode 100644 index 0000000..876acf2 --- /dev/null +++ b/models/department.py @@ -0,0 +1,23 @@ +from models.location import Location + + +class Department: + def __init__(self, department_id: int, name: str, location: Location): + self.__department_id = department_id + self.__name = name + self.__location = location + + @property + def department_id(self) -> int: + return self.__department_id + + @property + def name(self) -> str: + return self.__name + + @property + def location_id(self) -> Location: + return self.__location + + def __str__(self): + return f"Department({self.__department_id}, {self.__name}, {self.__location})" diff --git a/models/employee.py b/models/employee.py new file mode 100644 index 0000000..e78a2d0 --- /dev/null +++ b/models/employee.py @@ -0,0 +1,67 @@ +from datetime import date + +from models.department import Department + + +class Person: + def __init__(self, first_name, last_name): + self.__first_name = first_name + self.__last_name = last_name + + @property + def first_name(self) -> str: + return self.__first_name + + @property + def last_name(self) -> str: + return self.__last_name + + +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): + super().__init__(first_name, last_name) + self.__employee_id = employee_id + self.__email = email + self.__phone_number = phone_number + self.__hire_date = hire_date + self.__department = department + self.__job_id = job_id + self.__salary = salary + self.__manager_id = manager_id + + @property + def employee_id(self) -> int: + return self.__employee_id + + @property + def email(self) -> str: + return self.__email + + @property + def phone_number(self) -> str: + return self.__phone_number + + @property + def hire_date(self) -> date: + return self.__hire_date + + @property + def department(self) -> Department: + return self.__department + + @property + def job_id(self) -> int: + return self.__job_id + + @property + def salary(self) -> float: + return self.__salary + + @property + def manager_id(self) -> int: + return 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 new file mode 100644 index 0000000..612cf58 --- /dev/null +++ b/models/location.py @@ -0,0 +1,37 @@ +class Location: + def __init__(self, location_id: int, street_address: str, postal_code: str, + city: str, state_province: str, country_id: int): + self.__location_id = location_id + self.__street_address = street_address + self.__postal_code = postal_code + self.__city = city + self.__state_province = state_province + self.__country_id = country_id + + @property + def location_id(self) -> int: + return self.__location_id + + @property + def street_address(self) -> str: + return self.__street_address + + @property + def postal_code(self) -> str: + return self.__postal_code + + @property + def city(self) -> str: + return self.__city + + @property + def state_province(self) -> str: + return self.__state_province + + @property + def country_id(self) -> int: + return 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 new file mode 100644 index 0000000..9f17428 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +records~=0.5.3 +psycopg2-binary~=2.9.1 +setuptools~=57.0.0 +python-dateutil~=2.8.1 \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..9142566 --- /dev/null +++ b/setup.py @@ -0,0 +1,12 @@ +from setuptools import setup + +setup( + name='hr-resources', + version='0.1.0', + packages=[''], + url='', + license='', + author='Fabio Scotto di Santolo', + author_email='fabio.scottodisantolo@gmail.com', + description='Servizio per la visualizzazione delle risorse umane' +) From cf9ab44d5d5ea7d18eeb8c0197ea000280e74572 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Sun, 20 Jun 2021 15:08:59 +0200 Subject: [PATCH 2/6] Modificato in una REST API con Flask --- app.py | 76 ++++++++++++++++++++ db/access.py | 168 +++++++++++++++++++++++++++++++++++++++++-- main.py | 26 ------- models/department.py | 7 ++ models/employee.py | 18 ++++- models/location.py | 10 +++ requirements.txt | 3 +- 7 files changed, 275 insertions(+), 33 deletions(-) create mode 100644 app.py delete mode 100644 main.py 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 From 2f0ee3697891f7b70e0af0fe2cd7c09a43d7881b Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Sun, 20 Jun 2021 16:31:31 +0200 Subject: [PATCH 3/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d5ce48d..c7d1323 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # hr-resources -Esempio in Python di un gestore delle risorse umane +Esempio in Python di una REST API per la gestione delle risorse umane From af0b60e1c28580278dca8cbedfe5025ac2ec5452 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Sun, 20 Jun 2021 23:12:16 +0200 Subject: [PATCH 4/6] Gestiti campi data e numeri decimali --- models/employee.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/models/employee.py b/models/employee.py index f94575a..7241209 100644 --- a/models/employee.py +++ b/models/employee.py @@ -68,11 +68,10 @@ class Employee(Person): 'first_name': self.first_name, 'last_name': self.last_name, 'email': self.__email, - 'hire_date': self.__hire_date, + 'hire_date': f"{self.__hire_date: %Y-%m-%d}", '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), + 'salary': f"{self.__salary:,.2f}", 'manager_id': self.__manager_id } From a3e5229bfa685d88833b01adc405b711ab469202 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Mon, 21 Jun 2021 19:53:57 +0200 Subject: [PATCH 5/6] Corretti nomi per evitare effetti di shadowing --- app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app.py b/app.py index 9128c27..d678510 100644 --- a/app.py +++ b/app.py @@ -32,7 +32,7 @@ def handle_error(error): @app.get("/employee") -def employees(): +def all_employees(): return {"employees": [e.to_json() for e in fetch_employees()]} @@ -40,10 +40,10 @@ def __employees_group_by_seniority(departments: List[Department]) -> Dict[str, d result = {} for department in departments: # Per ogni dipartimento ricerco i suoi impiegati - employees = fetch_department_employees(department.department_id) + department_employees = fetch_department_employees(department.department_id) # Raggruppo gli impiegati per anni di anzianità - employee_group_by_years = itertools.groupby(employees, + employee_group_by_years = itertools.groupby(department_employees, lambda e: period.relativedelta(date.today(), e.hire_date).years) result[department.name] = {year: [e.to_json() for e in employees] From b53629ae6e0121a7d691fa4663a91a0dbf0f780e Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Thu, 24 Jun 2021 20:59:13 +0200 Subject: [PATCH 6/6] Aggiunto modulo per la conversione degli oggetti in JSON --- app.py | 9 +++++++-- models/department.py | 4 ++-- models/employee.py | 6 +++--- models/location.py | 2 +- requirements.txt | 3 ++- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app.py b/app.py index d678510..7b84d0d 100644 --- a/app.py +++ b/app.py @@ -4,6 +4,7 @@ from typing import List, Dict from dateutil import relativedelta as period from flask import Flask +from flask_json import FlaskJSON from db.access import fetch_european_departments, \ fetch_department_employees, \ @@ -14,6 +15,10 @@ from db.access import fetch_european_departments, \ from models.department import Department app = Flask(__name__) +FlaskJSON(app) + +app.config['JSON_DATE_FORMAT'] = '%d/%m/%Y' +app.config['JSON_USE_ENCODE_METHODS'] = True @app.get("/") @@ -33,7 +38,7 @@ def handle_error(error): @app.get("/employee") def all_employees(): - return {"employees": [e.to_json() for e in fetch_employees()]} + return {"employees": [e for e in fetch_employees()]} def __employees_group_by_seniority(departments: List[Department]) -> Dict[str, dict]: @@ -46,7 +51,7 @@ def __employees_group_by_seniority(departments: List[Department]) -> Dict[str, d employee_group_by_years = itertools.groupby(department_employees, lambda e: period.relativedelta(date.today(), e.hire_date).years) - result[department.name] = {year: [e.to_json() for e in employees] + result[department.name] = {year: [e for e in employees] for (year, employees) in employee_group_by_years} return result diff --git a/models/department.py b/models/department.py index 6b7194a..65ea1e9 100644 --- a/models/department.py +++ b/models/department.py @@ -19,11 +19,11 @@ class Department: def location_id(self) -> Location: return self.__location - def to_json(self): + def __json__(self): return { 'department_id': self.__department_id, 'name': self.__name, - 'location': self.__location.to_json() if self.__location is not None else None + 'location': self.__location if self.__location is not None else None } def __str__(self): diff --git a/models/employee.py b/models/employee.py index 7241209..706008f 100644 --- a/models/employee.py +++ b/models/employee.py @@ -62,14 +62,14 @@ class Employee(Person): def manager_id(self) -> int: return self.__manager_id - def to_json(self): + def __json__(self): return { 'employee_id': self.__employee_id, 'first_name': self.first_name, 'last_name': self.last_name, 'email': self.__email, - 'hire_date': f"{self.__hire_date: %Y-%m-%d}", - 'department': self.__department.to_json() if self.__department is not None else None, + 'hire_date': self.__hire_date, + 'department': self.__department if self.__department is not None else None, 'job_id': self.__job_id, 'salary': f"{self.__salary:,.2f}", 'manager_id': self.__manager_id diff --git a/models/location.py b/models/location.py index 7d73cb2..125dc63 100644 --- a/models/location.py +++ b/models/location.py @@ -32,7 +32,7 @@ class Location: def country_id(self) -> int: return self.__country_id - def to_json(self): + def __json__(self): return { 'location_id': self.__location_id, 'street_address': self.__street_address, diff --git a/requirements.txt b/requirements.txt index cbe7c79..e0bc9b0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ records~=0.5.3 psycopg2-binary~=2.9.1 setuptools~=57.0.0 python-dateutil~=2.8.1 -Flask~=2.0.1 \ No newline at end of file +Flask~=2.0.1 +Flask-JSON~=0.3.4 \ No newline at end of file