From ee3a5025c1a65fc003a73319c49baef14febf6a9 Mon Sep 17 00:00:00 2001 From: shahzeydyfah Date: Sat, 3 Oct 2026 22:29:07 +0330 Subject: [PATCH] fix(report):add change --- app/models/report.py | 6 +- app/repositories/report.py | 123 +++++++++++++++++++++++++++++++++---- app/urls/report.py | 18 ++++-- 3 files changed, 130 insertions(+), 17 deletions(-) diff --git a/app/models/report.py b/app/models/report.py index f9b5972..11b4bc3 100644 --- a/app/models/report.py +++ b/app/models/report.py @@ -22,10 +22,14 @@ class DelayDonutDetail(pydantic.BaseModel): project_id:uuid.UUID select:Literal['financial','force_major','technical'] +class DonutReport(pydantic.BaseModel): + only_current: bool = Field(default=False, description='فقط پروژه‌های نظارت جاری؛ مقدار false برای همه پروژه‌های نظارت') + + class DonutList(pydantic.BaseModel): type: int = Field(description='مقدار وارد شده در گزارش قبل') donut_select: str = Field(description='آیتم دونات انتخاب شده') class PhysicalMonth(pydantic.BaseModel): from_date:datetime.datetime - to_date:datetime.datetime \ No newline at end of file + to_date:datetime.datetime diff --git a/app/repositories/report.py b/app/repositories/report.py index f9841e1..7902e8e 100644 --- a/app/repositories/report.py +++ b/app/repositories/report.py @@ -3,7 +3,7 @@ from datetime import time from app.config import TaskEnv from app.models.project import ProjectPriceReport -from app.models.report import StatusReport, ReportCountry, DonutList, DelayDonutDetail, PhysicalMonth +from app.models.report import StatusReport, ReportCountry, DonutList, DonutReport, DelayDonutDetail, PhysicalMonth from core.service.mongo_db import use_collection @@ -150,6 +150,64 @@ class ReportRepository(): ]).to_list(None) return report + async def donut_v2(self, _select: int, _inp: DonutReport): + project_filter = {"has_monitor": True} + if _inp.only_current: + project_filter["monitor.sts"] = 2 + + report = None + if _select == 1: + report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([ + {"$match": project_filter}, + {"$group": {"_id": "$design.nature_id", 'count': {'$sum': 1}}} + ]).to_list(None) + elif _select == 2: + report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([ + {"$match": project_filter}, + { + "$group": { + "_id": { + "$cond": [ + {"$lt": ["$design.building_infrastructure", 1000]}, # Check if a < 10 + "less_than_1000", + { + "$cond": [ + {"$and": [{"$gte": ["$design.building_infrastructure", 1000]}, + {"$lt": ["$design.building_infrastructure", 5000]}]}, + # Check if 10 <= a < 20 + "between_1000_and_5000", + { + "$cond": [ + {"$and": [{"$gte": ["$design.building_infrastructure", 5000]}, + {"$lt": ["$design.building_infrastructure", 15000]}]}, + "between_5000_and_15000", + { + "$cond": [ + {"$and": [{"$gte": ["$design.building_infrastructure", 15000]}, + {"$lt": ["$design.building_infrastructure", 30000]}]}, + "between_15000_and_30000", + "greater_than_or_equal_30000" # Otherwise, a >= 30 + ] + } + ] + } + ] + } + ] + }, + "total": {"$sum": 1}, + } + } + ]).to_list(None) + + elif _select == 3: + report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([ + {"$match": project_filter}, + {"$group": {"_id": "$design.type_id", 'count': {'$sum': 1}}} + ]).to_list(None) + return report + + async def list_donut(self, _inp: DonutList): _filter = None if _inp.type == 1: @@ -230,6 +288,13 @@ class ReportRepository(): async def categorize_deviation(self): report = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate( [{"$match": {"deviation": {"$exists": True, "$ne": None}}}, + {"$lookup": { + "from": TaskEnv.CLN_PROJECT, + "localField": "project_id", + "foreignField": "_id", + "as": "project" + }}, + {"$match": {"project.monitor.sts": 2}}, {"$group": { "_id": { "$cond": [ @@ -267,6 +332,28 @@ class ReportRepository(): ]).to_list(None) return report + async def delay_donut_all_v2(self, _inp: DonutReport): + project_filter = {"project.has_monitor": True} + if _inp.only_current: + project_filter["project.monitor.sts"] = 2 + + report = await use_collection(TaskEnv.CLN_BILL_DELAY).aggregate([ + {"$lookup": { + "from": TaskEnv.CLN_PROJECT, + "localField": "project_id", + "foreignField": "_id", + "as": "project" + }}, + {"$match": project_filter}, + {'$group': {"_id": None, "total_financial": {"$sum": "$financial.total"}, + "total_force_major": {"$sum": "$force_major.total"}, + "total_technical": {"$sum": "$technical.total"}, + "total_extra_new_work": {"$sum": "$extra_new_work"}, + "total_other": {"$sum": "$other"}, + }} + ]).to_list(None) + return report + async def list_delay_donut(self, _select: str): get_list = [] _map = {'1': 'financial.total', '2': 'force_major.total', '3': 'technical.total', '4': 'extra_new_work', @@ -420,6 +507,15 @@ class ReportRepository(): } } }, + { + "$lookup": { + "from": TaskEnv.CLN_PROJECT, + "localField": "project_id", + "foreignField": "_id", + "as": "project" + } + }, + {"$match": {"project.monitor.sts": 2}}, { "$group": { "_id": { @@ -440,22 +536,18 @@ class ReportRepository(): } } ]).to_list(None) - - # result = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate([ - # {"$match":{"date_at":{"$lte":to_date,"$gte":from_date}}}, - # { - # "$sort": {'date_at': -1} - # }, - # {"$group": - # {'_id': {"year": "$year", "month": "$month"}, - # 'avg': {'$avg': "$real"}}, - # } - # ]).to_list(None) return result async def design_progress_status(self): result = await use_collection("design_progress").aggregate([ {'$match':{'complete_at':{"$exists":0},'parent_id':{"$exists":0}}}, + {"$lookup": { + "from": TaskEnv.CLN_PROJECT, + "localField": "project_id", + "foreignField": "_id", + "as": "project" + }}, + {"$match": {"project.design.sts": 2}}, {"$group": {'_id': '$type', 'count': {'$sum': 1}, @@ -468,6 +560,13 @@ class ReportRepository(): async def design_progress_status_state(self): result = await use_collection("design_progress").aggregate([ {'$match':{'complete_at':{"$exists":0},'parent_id':{"$exists":0}}}, + {"$lookup": { + "from": TaskEnv.CLN_PROJECT, + "localField": "project_id", + "foreignField": "_id", + "as": "project" + }}, + {"$match": {"project.design.sts": 2}}, {"$group": {'_id': {'state':"$state",'type':'$type'}, 'count': {'$sum': 1}, diff --git a/app/urls/report.py b/app/urls/report.py index a2a0cf5..9aebc00 100644 --- a/app/urls/report.py +++ b/app/urls/report.py @@ -2,7 +2,7 @@ import uuid from fastapi import Body -from app.models.report import StatusReport, ReportCountry, DonutList, DelayDonutDetail, PhysicalMonth +from app.models.report import StatusReport, ReportCountry, DonutList, DonutReport, DelayDonutDetail, PhysicalMonth from app.repositories.report import ReportRepository from core.app import app from core.utils.router import generate_router, shrink @@ -62,15 +62,25 @@ def sum_add_time_end_project(): @shrink(repo.delay_donut_all) def delay_donut_all(): pass + +@router.post('/donut-v2/delay/all', tags=_tag_base) +@shrink(repo.delay_donut_all_v2) +def delay_donut_all_v2(_inp: DonutReport = Body(...)): + pass #لیست پروژه ها را نمایش میده @router.get('/donut/delay/{_select}', tags=_tag_base) @shrink(repo.list_delay_donut) def list_delay_donut(_select): pass #تفکیک پروژه ها بر حسب زیربنا و تفکیک ماهیت پروژه و تفکیک بر حسب نوع پروژه -@router.get('/donut/{_select}', tags=_tag_base) +@router.post('/donut/{_select}', tags=_tag_base) @shrink(repo.donut) -def donut(_select:int): +def donut(_select: int, _inp: DonutReport = Body(...)): + pass + +@router.post('/donut-v2/{_select}', tags=_tag_base) +@shrink(repo.donut_v2) +def donut_v2(_select: int, _inp: DonutReport = Body(...)): pass @router.post('/list-donut', tags=_tag_base) @@ -145,4 +155,4 @@ def get_extra_project(project_id: uuid.UUID): def design_chart(project_id: uuid.UUID): pass -app.include_router(router) \ No newline at end of file +app.include_router(router)