Skip to content

Commit

Permalink
Merge pull request #14 from moevm/dev
Browse files Browse the repository at this point in the history
Dev to main
  • Loading branch information
Dlexeyn authored Dec 12, 2024
2 parents c23db21 + 1edd09f commit bbb010b
Show file tree
Hide file tree
Showing 35 changed files with 3,218 additions and 965 deletions.
136 changes: 102 additions & 34 deletions backend/dao/project.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from datetime import datetime
import re
from bson import ObjectId

from dao.base import BaseDao
from database import db
from schemas.project import ProjectCreate, ProjectResponse, Procurement, Stage, Risk, ProcurementResponse, \
from schemas.project import ProjectCreate, ProjectResponse, Procurement, ProjectStatus, Stage, Risk, ProcurementResponse, \
RiskResponse, \
StageResponse, ProjectUpdate, RiskUpdate, ProcurementUpdate, StageUpdate
from schemas.user import User, Contact, ContactResponse
from schemas.user import Role, User, Contact, ContactResponse
from schemas.utils import object_id_to_str, generate_id, get_date_now


Expand Down Expand Up @@ -47,20 +49,24 @@ async def get_project_by_name(cls, project_name: str) -> ProjectResponse | None:
return ProjectResponse(**project)

@classmethod
async def get_all_projects(cls) -> list[ProjectResponse] | list[None]:
cursor = cls.collection.find()
projects_list = await cursor.to_list()
result = []
for project in projects_list:
project = object_id_to_str(project)
result.append(ProjectResponse(**project))
return result

@classmethod
async def get_projects_by_user(cls, user_id: str) -> list[ProjectResponse] | list[None]:
cursor = cls.collection.find(
{f"contacts.{user_id}": {"$exists": True}}
)
async def get_all_projects(cls, project_name: str = "", project_status: ProjectStatus = ProjectStatus.none_status,
start_date: datetime = None, end_date: datetime = None, user_id: str = "") -> list[ProjectResponse] | list[None]:

filters = {}

if project_name:
filters["name"] = {"$regex": project_name, "$options": "i"}
if project_status:
filters["status"] = str(project_status.value)
if start_date:
filters["start_date"] = {"$gte": start_date}
if end_date:
filters["end_date"] = {"$lte": end_date}
if user_id:
filters[f"contacts.{user_id}"] = {"$exists": True}

print(filters)
cursor = cls.collection.find(filters)
projects_list = await cursor.to_list()
result = []
for project in projects_list:
Expand Down Expand Up @@ -166,17 +172,48 @@ async def delete_procurement(cls, project_id: str, procurement_id: str) -> str |
)

@classmethod
async def get_procurements_by_project_id(cls, project_id: str) -> list[ProcurementResponse] | list[None] | None:
project = await cls.collection.find_one({"_id": ObjectId(project_id)}, {"procurements": 1})
async def get_procurements_by_project_id(cls, project_id: str, name: str = "", creator_role: Role = None, state: bool = None,
start_date: datetime = None, end_date: datetime = None) -> list[ProcurementResponse] | list[None] | None:

procurements = []
project = await cls.collection.find_one({"_id": ObjectId(project_id)})
if project and "procurements" in project:
procurements = [ProcurementResponse(id=procurement_id, **procurement_data) for
procurement_id, procurement_data
in
project["procurements"].items()]
return procurements
for procurement_id, procurement in project.get("procurements", {}).items():

if name:
name_match = re.search(name, procurement["item_name"], re.IGNORECASE)
else:
name_match = True

if creator_role:
role_match = procurement["created_by"]["role"] == creator_role
else:
role_match = True

if state is not None:
state_match = procurement["inStock"] == state
else:
state_match = True

if start_date and procurement["delivery_date"] is not None:
start_date_match = start_date <= procurement["delivery_date"]
else:
start_date_match = True


if end_date and procurement["delivery_date"] is not None:
end_date_match = end_date >= procurement["delivery_date"]
else:
end_date_match = True

if name_match and state_match and role_match and start_date_match and end_date_match:
procurements.append(
ProcurementResponse(id=procurement_id, **procurement)
)

elif project is None:
return None
return []
return procurements

@classmethod
async def get_procurement_by_id(cls, project_id: str, procurement_id: str) -> ProcurementResponse | None:
Expand Down Expand Up @@ -247,15 +284,38 @@ async def delete_stage(cls, project_id: str, stage_id: str) -> str | None:
return stage_id

@classmethod
async def get_stages_by_project_id(cls, project_id: str) -> list[StageResponse] | list[None] | None:
async def get_stages_by_project_id(cls, project_id: str, name: str = "", start_date: datetime = None,
end_date: datetime = None) -> list[StageResponse] | list[None] | None:
project = await cls.collection.find_one({"_id": ObjectId(project_id)}, {"stages": 1})

stages = []
if project and "stages" in project:
stages = [StageResponse(id=stage_id, **stage_data) for stage_id, stage_data in
project["stages"].items()]
return stages
for stage_id, stage in project.get("stages", {}).items():

if name:
name_match = re.search(name, stage["name"], re.IGNORECASE)
else:
name_match = True

if start_date:
start_date_match = start_date <= stage["start_date"]
else:
start_date_match = True


if end_date:
end_date_match = end_date >= stage["end_date"]
else:
end_date_match = True

if name_match and start_date_match and end_date_match:
stages.append(
StageResponse(id=stage_id, **stage)
)

elif project is None:
return None
return []
return stages

@classmethod
async def get_stage_by_id(cls, project_id: str, stage_id: str) -> StageResponse | None:
Expand Down Expand Up @@ -319,15 +379,23 @@ async def delete_risk(cls, project_id: str, risk_id: str) -> str | None:
return risk_id

@classmethod
async def get_risks_by_project_id(cls, project_id: str) -> list[RiskResponse] | list[None] | None:
async def get_risks_by_project_id(cls, project_id: str, name: str = "") -> list[RiskResponse] | list[None] | None:
project = await cls.collection.find_one({"_id": ObjectId(project_id)}, {"risks": 1})

risks = []
if project and "risks" in project:
risks = [RiskResponse(id=risk_id, **risk_data) for risk_id, risk_data in
project["risks"].items()]
return risks

for risk_id, risk in project.get("risks", {}).items():
if name:
name_match = re.search(name, risk["name"], re.IGNORECASE)
else:
name_match = True

if name_match:
risks.append(RiskResponse(id=risk_id, **risk))
elif project is None:
return None
return []
return risks

@classmethod
async def get_risk_by_id(cls, project_id: str, risk_id: str) -> RiskResponse | None:
Expand Down
115 changes: 99 additions & 16 deletions backend/dao/task.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from datetime import datetime
import re
from bson import ObjectId

from dao.base import BaseDao
from database import db
from schemas.task import Task, TaskResponse, TaskUpdate, TaskStatusUpdate, ProjectTaskResponse
from schemas.task import Task, TaskResponse, TaskStatus, TaskUpdate, TaskStatusUpdate, ProjectTaskResponse
from schemas.user import Worker
from schemas.utils import generate_id, get_date_now

Expand Down Expand Up @@ -98,14 +100,17 @@ async def update_task_status(cls, project_id: str, stage_id: str, task_id: str,
}
}
)

if updated_id is None:
return None

return await cls.get_task_by_id(project_id, stage_id, task_id)

@classmethod
async def get_tasks_by_stage_id(cls, project_id: str, stage_id: str) -> list[TaskResponse] | list[None]:
async def get_tasks_by_stage_id(cls, project_id: str, stage_id: str, task_name: str = "", project_name: str = "",
task_status: TaskStatus = TaskStatus.none_status,
start_date: datetime = None, end_date: datetime = None) -> list[TaskResponse] | \
list[None]:
project = await cls.collection.find_one(
{
"_id": ObjectId(project_id),
Expand All @@ -116,15 +121,45 @@ async def get_tasks_by_stage_id(cls, project_id: str, stage_id: str) -> list[Tas
if not project or "stages" not in project or stage_id not in project["stages"]:
return []

tasks = project["stages"][stage_id].get("tasks", {})
tasks = []

for task_id, task in project["stages"][stage_id].get("tasks", {}).items():

if task_name:
name_match = re.search(task_name, task["name"], re.IGNORECASE)
print(f'name match is: {name_match}')
else:
name_match = True

if task_status:
status_match = task_status == task["status"]
print(f'status match is: {status_match}')
else:
status_match = True

tasks_list = [
TaskResponse(id=task_id, **task_data) for task_id, task_data in tasks.items()
]
return tasks_list
if start_date:
start_date_match = start_date <= task["start_date"]
else:
start_date_match = True

if end_date:
end_date_match = end_date >= task["end_date"]
else:
end_date_match = True

if status_match and name_match and start_date_match and end_date_match:
tasks.append(TaskResponse(
id=task_id,
**task
))
return tasks

@classmethod
async def get_all_tasks_by_user(cls, user_id: str) -> list[ProjectTaskResponse] | list[None]:
async def get_all_tasks_by_user(cls, user_id: str, task_name: str = "", project_name: str = "",
task_status: TaskStatus = TaskStatus.none_status,
start_date: datetime = None, end_date: datetime = None) -> list[
ProjectTaskResponse] | \
list[None]:
cursor = cls.collection.find(
{
"stages": {
Expand All @@ -133,20 +168,68 @@ async def get_all_tasks_by_user(cls, user_id: str) -> list[ProjectTaskResponse]
}
)

search_params = {}

if task_name:
search_params["name"] = task_name
if project_name:
search_params["project_name"] = project_name
if task_status:
search_params["status"] = task_status
if start_date is not None:
search_params["start_date"] = start_date
if end_date is not None:
search_params["end_date"] = end_date

tasks = []
async for project in cursor:

if "project_name" in search_params:
project_match = re.search(search_params["project_name"], project["name"], re.IGNORECASE)
print(f'project match is: {project_match}')
else:
project_match = True

if project_match is None:
continue

for stage_id, stage in project.get("stages", {}).items():
for task_id, task in stage.get("tasks", {}).items():
for worker_id, worker in task.get("workers", {}).items():
if worker_id == user_id:
tasks.append(ProjectTaskResponse(
id=task_id,
project_id=str(project["_id"]),
project_name=project["name"],
stage_id=str(stage_id),
**task
))

if "name" in search_params:
name_match = re.search(search_params["name"], task["name"], re.IGNORECASE)
print(f'name match is: {name_match}')
else:
name_match = True

if "status" in search_params:
status_match = search_params["status"] == task["status"]
print(f'status match is: {status_match}')
else:
status_match = True

if "start_date" in search_params:
start_date_match = search_params["start_date"] <= task["start_date"]
else:
start_date_match = True

if "end_date" in search_params:
end_date_match = search_params["end_date"] >= task["end_date"]
else:
end_date_match = True

if status_match and name_match and start_date_match and end_date_match:
tasks.append(ProjectTaskResponse(
id=task_id,
project_id=str(project["_id"]),
project_name=project["name"],
stage_id=str(stage_id),
**task
))

print(f'Finded tasks: {len(tasks)}')
return tasks

@classmethod
Expand Down
17 changes: 17 additions & 0 deletions backend/database.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime
import json

from bson import ObjectId
Expand Down Expand Up @@ -44,8 +45,24 @@ def load_default_data():
with open(settings.DEFAULT_DATA_FILE, "r") as file:
data = json.load(file)

def convert_dates(item):
if isinstance(item, dict):
for key, value in item.items():
if isinstance(value, str):
# Попробуем распознать ISO формат
try:
item[key] = datetime.fromisoformat(value)
except ValueError:
pass # Если это не дата, оставляем строку
elif isinstance(value, (list, dict)):
convert_dates(value)
elif isinstance(item, list):
for sub_item in item:
convert_dates(sub_item)

for collection_name, documents in data.items():
for doc in documents:
convert_dates(doc)
if "_id" in doc:
doc["_id"] = ObjectId(doc["_id"])

Expand Down
Loading

0 comments on commit bbb010b

Please sign in to comment.