feat: 项目成本分析报告工具

This commit is contained in:
martsforever
2025-09-10 21:57:49 +08:00
parent 2db03a4fbb
commit 6105740b31
3 changed files with 88 additions and 9 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ class ProjectModel(BasicModel, table=True):
name: str = Field(default=None, description="项目名称") name: str = Field(default=None, description="项目名称")
description: str = Field(default=None, description="项目描述") description: str = Field(default=None, description="项目描述")
budget: Decimal = Field(default=None, description="项目预算金额") budget: Decimal = Field(default=None, description="项目预算金额")
version: int = Field(default=None, description="项目版本号") # version: int = Field(default=None, description="项目版本号")
# /*---------------------------------------leader_id-------------------------------------------*/ # /*---------------------------------------leader_id-------------------------------------------*/
+2
View File
@@ -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_book_hotel import tool_book_hotel
from app.tools.tool_get_datetime import tool_get_datetime from app.tools.tool_get_datetime import tool_get_datetime
from app.tools.tool_multiple import tool_multiply 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_direct_subordinates import tool_query_direct_subordinates
from app.tools.tool_query_projects import tool_query_projects from app.tools.tool_query_projects import tool_query_projects
@@ -12,4 +13,5 @@ tool_list = [
tool_multiply, tool_multiply,
tool_query_direct_subordinates, tool_query_direct_subordinates,
tool_query_projects, tool_query_projects,
tool_project_analysis,
] ]
+84 -7
View File
@@ -1,15 +1,92 @@
from decimal import Decimal
from typing import Annotated, List
from langchain_core.tools import tool 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( @tool(
name_or_callable="tool_project_analysis", name_or_callable="tool_project_analysis",
description="做项目成本分析报告" description="做项目成本分析报告"
) )
def tool_project_analysis() -> float: async def tool_project_analysis(project_name: Annotated[str, "项目名称"]) -> float:
return [ async with async_session() as session:
"", project_cls: ProjectModel = await ProjectService.query_item(
{ session=session,
"component": "DirectSubordinates", row_dict={"name": project_name}
"props": {}, )
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,
} }
]