Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resident Directory Filters Component #218

Merged
merged 10 commits into from
Jan 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions backend/app/rest/residents_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ def get_residents():
except:
filters = None

filters = None
try:
filters = json.loads(request.args.get("filters"))
except:
pass

results_per_page = 10
try:
results_per_page = int(request.args.get("results_per_page"))
Expand All @@ -157,10 +163,15 @@ def get_residents():
@require_authorization_by_role({"Relief Staff", "Regular Staff", "Admin"})
def count_residents():
"""
Get number of residents
Get number of residents. Can optionally add filters
"""
try:
residents = residents_service.count_residents()
filters = json.loads(request.args.get("filters"))
except:
filters = None

try:
residents = residents_service.count_residents(filters)
return jsonify(residents), 201
except Exception as e:
error_message = getattr(e, "message", None)
Expand Down
42 changes: 21 additions & 21 deletions backend/app/services/implementations/log_records_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,23 +92,23 @@ def to_json_list(self, logs):
except Exception as postgres_error:
raise postgres_error

def filter_by_building_id(self, building_id):
if type(building_id) == list:
sql_statement = f"\nlogs.building_id={building_id[0]}"
for i in range(1, len(building_id)):
def filter_by_buildings(self, buildings):
if type(buildings) == list:
sql_statement = f"\nlogs.building_id={buildings[0]}"
for i in range(1, len(buildings)):
sql_statement = (
sql_statement + f"\nOR logs.building_id={building_id[i]}"
sql_statement + f"\nOR logs.building_id={buildings[i]}"
)
return sql_statement
return f"\logs.building_id={building_id}"
return f"\logs.building_id={buildings}"

def filter_by_employee_id(self, employee_id):
if type(employee_id) == list:
sql_statement = f"\nemployee_id={employee_id[0]}"
for i in range(1, len(employee_id)):
sql_statement = sql_statement + f"\nOR employee_id={employee_id[i]}"
def filter_by_employees(self, employees):
if type(employees) == list:
sql_statement = f"\nemployee_id={employees[0]}"
for i in range(1, len(employees)):
sql_statement = sql_statement + f"\nOR employee_id={employees[i]}"
return sql_statement
return f"\nemployee_id={employee_id}"
return f"\nemployee_id={employees}"

def filter_by_residents(self, residents):
if type(residents) == list:
Expand All @@ -120,13 +120,13 @@ def filter_by_residents(self, residents):
return sql_statement
return f"\n'{residents}'=ANY (resident_ids)"

def filter_by_attn_to(self, attn_to):
if type(attn_to) == list:
sql_statement = f"\nattn_to={attn_to[0]}"
for i in range(1, len(attn_to)):
sql_statement = sql_statement + f"\nOR attn_to={attn_to[i]}"
def filter_by_attn_tos(self, attn_tos):
if type(attn_tos) == list:
sql_statement = f"\nattn_to={attn_tos[0]}"
for i in range(1, len(attn_tos)):
sql_statement = sql_statement + f"\nOR attn_to={attn_tos[i]}"
return sql_statement
return f"\nattn_to={attn_to}"
return f"\nattn_to={attn_tos}"

def filter_by_date_range(self, date_range):
sql = ""
Expand Down Expand Up @@ -166,10 +166,10 @@ def filter_log_records(self, filters=None):
is_first_filter = True

options = {
"building_id": self.filter_by_building_id,
"employee_id": self.filter_by_employee_id,
"buildings": self.filter_by_buildings,
"employees": self.filter_by_employees,
"residents": self.filter_by_residents,
"attn_to": self.filter_by_attn_to,
"attn_tos": self.filter_by_attn_tos,
"date_range": self.filter_by_date_range,
"tags": self.filter_by_tags,
"flagged": self.filter_by_flagged,
Expand Down
177 changes: 108 additions & 69 deletions backend/app/services/implementations/residents_service.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from flask import current_app
from ..interfaces.residents_service import IResidentsService
from ...models.residents import Residents
from ...models.log_record_residents import LogRecordResidents
from ...models.buildings import Buildings
from ...models import db
from datetime import datetime
from sqlalchemy import select, cast, Date
import json
from sqlalchemy.sql.expression import or_, and_
from pytz import timezone


class ResidentsService(IResidentsService):
Expand All @@ -22,22 +23,38 @@ def __init__(self, logger):
"""
self.logger = logger

def to_resident_json(self, resident):
def to_resident_json(self, resident, current_date):
resident, building = resident[0], resident[1]

resident_dict = resident.to_dict()
resident_dict["building"]["name"] = building
resident_dict["status"] = self.get_resident_status(current_date,
resident_dict["date_joined"], resident_dict["date_left"]
)

return resident_dict

def to_residents_json_list(self, resident_results):
def to_residents_json_list(self, residents, current_date):
residents_json_list = []
for result in resident_results:
for result in residents:
resident, building = result[0], result[1]

resident_dict = resident.to_dict()
resident_dict["building"]["name"] = building
resident_dict["status"] = self.get_resident_status(current_date,
resident_dict["date_joined"], resident_dict["date_left"]
)

residents_json_list.append(resident_dict)
return residents_json_list

def get_resident_status(self, current_date, date_joined, date_left):
if current_date < date_joined:
return "Future"
elif date_left is None or current_date <= date_left:
return "Current"
else:
return "Past"

def convert_to_date_obj(self, date):
return datetime.strptime(date, "%Y-%m-%d")
Expand All @@ -58,6 +75,60 @@ def is_date_left_invalid_resident(self, resident):

return False

def construct_filters(self, query, filters, current_date):

residents = filters.get("residents")
buildings = filters.get("buildings")
statuses = filters.get("statuses")
date_left = None
date_joined = None

if filters.get("date_range") is not None:
date_joined, date_left = filters.get("date_range")
if date_joined is not None:
date_joined = datetime.strptime(
date_joined, "%Y-%m-%d"
).replace(hour=0, minute=0)
if date_left is not None:
date_left = datetime.strptime(date_left, "%Y-%m-%d").replace(
hour=0, minute=0
)

if buildings is not None:
query = query.filter(
Residents.building_id.in_(buildings)
)
if residents is not None:
query = query.filter(
Residents.id.in_(residents)
)
if statuses is not None:
conditions = []

#Construct the conditions for each case
for status in statuses:
if status == "Future":
conditions.append(Residents.date_joined > current_date);
elif status == "Current":
conditions.append(and_(Residents.date_joined <= current_date,
or_(Residents.date_left.is_(None), Residents.date_left >= current_date)))
elif status == "Past":
conditions.append(Residents.date_left < current_date)

#OR them together and add to filter
query = query.filter(or_(*conditions))

if date_joined is not None:
query = query.filter(
Residents.date_joined >= date_joined
)
if date_left is not None:
query = query.filter(
Residents.date_left <= date_left
)

return query

def add_resident(self, resident):
try:
new_resident = Residents(**resident)
Expand Down Expand Up @@ -109,6 +180,8 @@ def delete_resident(self, resident_id):

def get_resident_by_id(self, resident_id):
try:
current_date = datetime.now(timezone('US/Eastern')).strftime('%Y-%m-%d')

resident = (
Residents.query.join(
Buildings, Buildings.id == Residents.building_id
Expand All @@ -117,84 +190,50 @@ def get_resident_by_id(self, resident_id):
.filter_by(resident_id=resident_id)
.first()
)
return self.to_resident_json(resident)
return self.to_resident_json(resident, current_date) if resident else None
except Exception as postgres_error:
raise postgres_error

def get_residents(
self, return_all, page_number, results_per_page, filters=None
):
try:
if return_all:
residents_results = (
Residents.query.join(
Buildings, Buildings.id == Residents.building_id
)
.with_entities(Residents, Buildings.name.label("building"))
.all()
)
elif filters:
resident_id = filters.get("resident_id")
building_id = filters.get("building_id")
date_left = None
date_joined = None

if filters.get("date_range") is not None:
date_joined, date_left = filters.get("date_range")
if date_joined is not None:
date_joined = datetime.strptime(
date_joined, "%Y-%m-%d"
).replace(hour=0, minute=0)
if date_left is not None:
date_left = datetime.strptime(date_left, "%Y-%m-%d").replace(
hour=0, minute=0
)

residents_results = Residents.query.join(
Buildings, Buildings.id == Residents.building_id
).with_entities(Residents, Buildings.name.label("building"))
current_date = datetime.now(timezone('US/Eastern')).strftime('%Y-%m-%d')

if building_id is not None:
residents_results = residents_results.filter(
Residents.building_id.in_(building_id)
)
if resident_id is not None:
residents_results = residents_results.filter(
Residents.resident_id.in_(resident_id)
)
if date_joined is not None and date_left is not None:
residents_results = residents_results.filter(
Residents.date_joined >= date_joined
)
residents_results = residents_results.filter(
Residents.date_left <= date_left
)
elif date_joined is not None:
residents_results = residents_results.filter(
Residents.date_joined >= date_joined
)
elif date_left is not None:
residents_results = residents_results.filter(
Residents.date_left <= date_left
)
else:
residents_results = (
Residents.query.join(
Buildings, Buildings.id == Residents.building_id
)
.limit(results_per_page)
.offset((page_number - 1) * results_per_page)
.with_entities(Residents, Buildings.name.label("building"))
.all()
residents_results = (
Residents.query.join(
Buildings, Buildings.id == Residents.building_id
)
.with_entities(Residents, Buildings.name.label("building"))
)
if filters:
residents_results = self.construct_filters(residents_results, filters, current_date)

if not return_all:
residents_results = residents_results.limit(results_per_page).offset((page_number - 1) * results_per_page)

residents_results = residents_results.all()

return {"residents": self.to_residents_json_list(residents_results)}
return {"residents": self.to_residents_json_list(residents_results, current_date)}

except Exception as postgres_error:
raise postgres_error

def count_residents(self):
def count_residents(self, filters):
try:
count = Residents.query.count()

residents_results = (
Residents.query.join(
Buildings, Buildings.id == Residents.building_id
)
.with_entities(Residents, Buildings.name.label("building"))
)

if filters:
current_date = datetime.now(timezone('US/Eastern')).strftime('%Y-%m-%d')
residents_results = self.construct_filters(residents_results, filters, current_date)

count = residents_results.count()
return {"num_results": count}

except Exception as postgres_error:
Expand Down
4 changes: 3 additions & 1 deletion backend/app/services/interfaces/residents_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@ def get_residents(
pass

@abstractmethod
def count_residents(self):
def count_residents(self, filters):
"""
Count the total number of residents
:param filters: filters for the query
:type filters: json
:return: count of residents
:rtype: int
:raises Exception: if resident count fails
Expand Down
Loading
Loading