diff --git a/app/model/ProjectModel.py b/app/model/ProjectModel.py index d5410c1..f6ae6cb 100644 --- a/app/model/ProjectModel.py +++ b/app/model/ProjectModel.py @@ -16,7 +16,7 @@ class ProjectModel(BasicModel, table=True): name: str = Field(default=None, description="项目名称") description: str = Field(default=None, description="项目描述") budget: Decimal = Field(default=None, description="项目预算金额") - version: int = Field(default=None, description="项目版本号") + # version: int = Field(default=None, description="项目版本号") # /*---------------------------------------leader_id-------------------------------------------*/ diff --git a/app/tools/tool_list.py b/app/tools/tool_list.py index 724047a..a766540 100644 --- a/app/tools/tool_list.py +++ b/app/tools/tool_list.py @@ -2,6 +2,7 @@ from app.tools.tool_add import tool_add from app.tools.tool_book_hotel import tool_book_hotel from app.tools.tool_get_datetime import tool_get_datetime from app.tools.tool_multiple import tool_multiply +from app.tools.tool_project_analysis import tool_project_analysis from app.tools.tool_query_direct_subordinates import tool_query_direct_subordinates from app.tools.tool_query_projects import tool_query_projects @@ -12,4 +13,5 @@ tool_list = [ tool_multiply, tool_query_direct_subordinates, tool_query_projects, + tool_project_analysis, ] diff --git a/app/tools/tool_project_analysis.py b/app/tools/tool_project_analysis.py index 4be16ed..0deca18 100644 --- a/app/tools/tool_project_analysis.py +++ b/app/tools/tool_project_analysis.py @@ -1,15 +1,92 @@ +from decimal import Decimal +from typing import Annotated, List + from langchain_core.tools import tool +from app.model.ProjectModel import ProjectService, ProjectModel +from app.model.ReimburseModel import ReimburseService, ReimburseModel +from app.model.ReimburseOtherModel import ReimburseOtherModel +from app.model.ReimburseTravelModel import ReimburseTravelModel +from app.utils.PageQueryParams import PageQueryParams +from app.utils.db_utils import async_session + @tool( name_or_callable="tool_project_analysis", description="做项目成本分析报告" ) -def tool_project_analysis() -> float: - return [ - "", - { - "component": "DirectSubordinates", - "props": {}, - } - ] +async def tool_project_analysis(project_name: Annotated[str, "项目名称"]) -> float: + async with async_session() as session: + project_cls: ProjectModel = await ProjectService.query_item( + session=session, + row_dict={"name": project_name} + ) + if not project_cls: + return f"找不到名为「{project_name}」的项目" + + query_cls_list, has_next, total = await ReimburseService.query_list(session=session, query_param=PageQueryParams(all=True, filters={"proj_id": project_cls.id})) + + reimburse_list: List[ReimburseModel] = [item for item in query_cls_list if item.approve is not None and item.approve.status == 'approved'] + + member_amount = {} # 人员成本分析 + member_cost_description_list = {} # 人员费用描述 + + reimburse_travel_list: List[ReimburseTravelModel] = [] + reimburse_other_list: List[ReimburseOtherModel] = [] + + for reimburse_cls in reimburse_list: + reimburse_travel_list.extend(reimburse_cls.travel_list) + reimburse_other_list.extend(reimburse_cls.other_list) + + if not member_amount.get(reimburse_cls.user.full_name, None): + member_amount[reimburse_cls.user.full_name] = Decimal(0) + if not member_cost_description_list.get(reimburse_cls.user.full_name, None): + member_cost_description_list[reimburse_cls.user.full_name] = [] + + member_amount[reimburse_cls.user.full_name] += reimburse_cls.amount + for item in reimburse_cls.travel_list: + member_cost_description_list[reimburse_cls.user.full_name].append(f""" + 费用描述:{item.title},差旅费用——{item.type},{item.amount}元,{item.depart_time}——{item.arrive_time},{item.depart_city}——{item.arrive_city} + """) + for item in reimburse_cls.other_list: + member_cost_description_list[reimburse_cls.user.full_name].append(f""" + 费用描述:{item.title},其他费用——{item.type},{item.amount}元 + """) + + cost_amount = {} # 费用类型成本分析 + + for item in reimburse_travel_list: + if not cost_amount.get(item.type, None): + cost_amount[item.type] = Decimal(0) + cost_amount[item.type] += item.amount + + for item in reimburse_other_list: + if not cost_amount.get(item.type, None): + cost_amount[item.type] = Decimal(0) + cost_amount[item.type] += item.amount + + member_description = '\n'.join([f"{user_full_name}:{user_spent}" for user_full_name, user_spent in member_amount.items()]) + cost_description = '\n'.join([f"{cost_type}:{cost_amount}" for cost_type, cost_amount in cost_amount.items()]) + member_cost_description = '\n'.join([f"{user_full_name}产生的费用:{''.join(user_cost_description)}" for user_full_name, user_cost_description in member_cost_description_list.items()]) + + description = f""" + 项目预算:{project_cls.budget} + 项目花费金额:{project_cls.spent} + 项目预算余额:{project_cls.balance} + + 项目成员成本分析: + {member_description} + + 费用类型成本分析: + {cost_description} + + 人员费用清单: + + {member_cost_description} + """ + + return { + "member_amount": member_amount, + "cost_amount": cost_amount, + "description": description, + }