Files
sakhteman/app/repositories/report.py
T

540 lines
23 KiB
Python

import uuid
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 core.service.mongo_db import use_collection
class ReportRepository():
async def project_status(self, _inp: StatusReport, type):
if _inp.state:
match = {f'{type}.sts': {'$exists': 1}, 'design.state': _inp.state}
else:
match = {f'{type}.sts': {'$exists': 1}}
if _inp.type_id:
match.update({'design.type_id': _inp.type_id})
if _inp.nature_id:
match.update({'design.nature_id': _inp.nature_id})
if type == 'monitor' and _inp.monitor_type:
match.update({'monitor.base_information.type': _inp.monitor_type})
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
{
"$match": match
},
{
'$group': {
'_id': f"${type}.sts",
'count': {'$sum': 1}
}
}
]).to_list(None)
return report
async def project_status_design(self, _inp: StatusReport):
return await self.project_status(_inp, 'design')
async def project_status_monitor(self, _inp: StatusReport):
return await self.project_status(_inp, 'monitor')
async def report_country(self, _inp: ReportCountry):
match = {}
if _inp.state:
match = {'design.state': _inp.state}
if _inp.type_id:
match.update({'design.type_id': _inp.type_id})
if _inp.nature_id:
match.update({'design.nature_id': _inp.nature_id})
if _inp.monitor_type:
match.update({'monitor.base_information.type': _inp.monitor_type})
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
{"$match": match},
{'$group': {
'_id': "$design.state",
'nature_id': {'$addToSet': '$design.nature_id'},
'type_id': {'$addToSet': '$design.type_id'},
'monitor_type': {'$addToSet': '$monitor.base_information.type'}
}},
{'$project': {
'count_nature_id': {"$size": "$nature_id"},
'count_type_id': {"$size": "$type_id"},
'count_monitor_type': {"$size": "$monitor_type"},
"_id": 1
}}
]).to_list(None)
# count_nature = await use_collection(TaskEnv.CLN_PROJECT).count_documents(
# {'design.nature_id': _inp.nature_id})
# count_type = await use_collection(TaskEnv.CLN_PROJECT).count_documents({'design.type_id':_inp.type_id})
# count_monitor_type = await use_collection(TaskEnv.CLN_PROJECT).count_documents({'monitor.base_information.type': _inp.monitor_type})
# return {'count_nature':count_nature,'count_type':count_type,'count_monitor_type':count_monitor_type}
return report
async def exist_project_state(self,_inp: StatusReport):
match ={}
aggregate = []
if _inp.type_id:
match.update({'design.type_id': _inp.type_id})
if _inp.nature_id:
match.update({'design.nature_id': _inp.nature_id})
if _inp.monitor_type:
match.update({'monitor.base_information.type': _inp.monitor_type})
if match:
aggregate.append({"$match": match})
aggregate.append({
'$group': {
'_id': "$design.state",
'count': {'$sum': 1}
}
})
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate(aggregate).to_list(None)
return report
async def donut(self, _select: int):
report = None
if _select == 1:
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
{"$group": {"_id": "$design.nature_id", 'count': {'$sum': 1}}}
]).to_list(None)
elif _select == 2:
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
{
"$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([
{"$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:
_filter = {'design.nature_id': int(_inp.donut_select)}
if _inp.type == 2:
if _inp.donut_select == "less_than_1000":
_filter = {'design.building_infrastructure': {'$lt': 1000}}
elif _inp.donut_select == "between_1000_and_5000":
_filter = {'design.building_infrastructure': {'$lt': 5000, "$gte": 1000}}
elif _inp.donut_select == "between_5000_and_15000":
_filter = {'design.building_infrastructure': {'$lt': 15000, "$gte": 5000}}
elif _inp.donut_select == "between_15000_and_30000":
_filter = {'design.building_infrastructure': {'$lt': 30000, "$gte": 15000}}
else:
_filter = {'design.building_infrastructure': {'$gte': 30000}}
elif _inp.type == 3:
_filter = {'design.type_id': int(_inp.donut_select)}
report = await use_collection(TaskEnv.CLN_PROJECT).find(_filter).to_list(None)
return report
async def delay_donut(self, project_id:uuid.UUID):
report = await use_collection(TaskEnv.CLN_BILL_DELAY).aggregate([
{"$match":{'project_id':project_id}},
{'$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 delay_donut_detail(self, _inp:DelayDonutDetail):
_group = {}
if _inp.select == 'financial':
_group = {"_id": None, "total_status": {"$sum": "$financial.status"},
"total_prepayment": {"$sum": "$financial.prepayment"},
"total_modification": {"$sum": "$financial.modification"},
"total_good_job": {"$sum": "$financial.good_job"},
}
elif _inp.select == 'force_major':
_group = {"_id": None, "total_force_event": {"$sum": "$force_major.force_event"},
"total_material": {"$sum": "$force_major.material"},
"total_rules": {"$sum": "$force_major.rules"},
"total_define_indicators": {"$sum": "$force_major.define_indicators"},
}
elif _inp.select == 'technical':
_group = {"_id": None, "total_map_technical": {"$sum": "$technical.map_technical"},
"total_permit": {"$sum": "$technical.permit"},
"total_purchase": {"$sum": "$technical.purchase"},
"total_suspense": {"$sum": "$technical.suspense"},
}
report = await use_collection(TaskEnv.CLN_BILL_DELAY).aggregate([
{"$match": {'project_id': _inp.project_id}},
{'$group': _group}
]).to_list(None)
return report
async def progress_activity(self,project_id:uuid.UUID):
secondary = await use_collection(TaskEnv.CLN_MONITOR_SECONDARY).find({"project_id":project_id}).to_list(None)
_obj = {}
for i in secondary:
_obj[str(i["_id"])] = i['title']
ids = [i["_id"] for i in secondary]
report = await use_collection(TaskEnv.CLN_MONITOR_SUB_SECONDARY).aggregate([
{"$match": {"parent_id": {"$in": ids}}},
{"$group": {
"_id":"$parent_id",
"total_program": {"$sum": "$program"},
"total_real": {"$sum": "$real"},
}}
]).to_list(None)
if report:
for i in report:
i["title"] = _obj[str(i["_id"])]
return report
async def categorize_deviation(self):
report = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate(
[{"$match": {"deviation": {"$exists": True, "$ne": None}}},
{"$group": {
"_id": {
"$cond": [
{"$lt": ["$deviation", 10]},
"less_than_10",
{
"$cond": [
{"$and": [{"$gte": ["$deviation", 10]}, {"$lt": ["$deviation", 25]}]},
"between_10_and_25",
{
"$cond": [
{"$and": [{"$gte": ["$deviation", 25]},
{"$lt": ["$deviation", 40]}]},
"between_25_and_40",
"greater_than_40"
]
}
]
}
]
},
"count": {"$sum": 1},
"projectIds": { "$addToSet": "$project_id" },
"totalDeviation": {"$sum": "$deviation"}, }}]).to_list(None)
return report
async def delay_donut_all(self):
report = await use_collection(TaskEnv.CLN_BILL_DELAY).aggregate([
{'$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',
'5': 'other'}
report = await use_collection(TaskEnv.CLN_BILL_DELAY).aggregate([
{'$match': {_map[_select]: {'$gt': 0}}},
{'$group': {"_id": '$project_id'}}
]).to_list(None)
if report:
for i in report:
get_list.append(i['_id'])
# projects = await use_collection(TaskEnv.CLN_PROJECT).find({"_id":{"$in":get_list}}).to_list(None)
return get_list
async def sum_add_time_end_project(self):
result = {}
result['less_than_20'] = []
result['bet_20_50']= []
result['bet_50_100'] = []
result['bet_100_200'] = []
result['upper_than_200'] = []
get_dict_project_id = {}
report = await use_collection(TaskEnv.CLN_BILL_DELAY).aggregate([
{'$group': {"_id": '$project_id', 'sum':{'$sum':'$total_day'}}}
]).to_list(None)
get_list_project_id = [i['_id'] for i in report] if report else []
get_dict_project_id.update( {str(i['_id']):i for i in report} if report else [])
list_project = await use_collection(TaskEnv.CLN_PROJECT).find({"_id":{"$in":get_list_project_id}}).to_list(None)
if list_project:
for i in list_project:
if 'first_time' in i['monitor']['detail'] and i['monitor']['sts'] == 5:
cal = (get_dict_project_id[str(i["_id"])]['sum']/i['monitor']['detail']['first_time'])*100
if cal < 20 :
result['less_than_20'].append(i["_id"])
elif cal < 50:
result['bet_20_50'].append(i["_id"])
elif cal < 100:
result['bet_50_100'].append(i["_id"])
elif cal < 200:
result['bet_100_200'].append(i["_id"])
else:
result['upper_than_200'].append(i["_id"])
return result
#درصد میانگین افزایش هزینه پروژه های خاتمه یافته
async def add_cost(self):
result = {}
result['less_than_20'] = []
result['bet_20_50'] = []
result['bet_50_100'] = []
result['bet_100_200'] = []
result['upper_than_200'] = []
report = await use_collection(TaskEnv.CLN_PROJECT_PRICE_REPORT).find({}).to_list(None)
if report:
for i in report:
_model = ProjectPriceReport(**i)
if 'amount_status' in _model and 'amount_adjust' in _model:
cal = (_model.first_amount-_model.amount_status +_model.amount_adjust)/_model.first_amount
if cal < 20:
result['less_than_20'].append(_model.project_id)
elif cal < 50:
result['bet_20_50'].append(_model.project_id)
elif cal < 100:
result['bet_50_100'].append(_model.project_id)
elif cal < 200:
result['bet_100_200'].append(_model.project_id)
else:
result['upper_than_200'].append(_model.project_id)
return result
async def progress_report(self):
result = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate([
{
"$sort": {'date_at': -1}
},
{
'$group':
{
'_id': "$project_id",
'records': {"$push": "$$ROOT"},
}
},
{
"$project": {
"_id": 1,
"records": {"$slice": ["$records", 1]},
}
},
]).to_list(None)
result_report = {
'less_than_1':[],
'bet_1_2':[],
'bet_2_5':[],
'upper_than_5':[],
}
for i in result:
print(i['records'])
if ('records' in i) and (len(i['records'])>0) and 'last_month' in i['records'][0]:
cal = i['records'][0]['last_month']
if cal < 1:
result_report['less_than_1'].append(i["_id"])
elif cal <= 2:
result_report['bet_1_2'].append(i["_id"])
elif cal <= 5:
result_report['bet_2_5'].append(i["_id"])
else:
result_report['upper_than_5'].append(i["_id"])
return result_report
async def progress_avg_report(self):
result = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate([
{
'$group':
{
'_id': "$project_id",
'avg':{'$avg': "$real"},
}
},
]).to_list(None)
result_report = {
'less_than_1':[],
'bet_1_2':[],
'bet_2_5':[],
'upper_than_5':[],
}
for i in result:
if i['avg'] < 1:
result_report['less_than_1'].append(i["_id"])
elif i['avg'] <= 2:
result_report['bet_1_2'].append(i["_id"])
elif i['avg'] <= 5:
result_report['bet_2_5'].append(i["_id"])
else:
result_report['upper_than_5'].append(i["_id"])
return result_report
async def progress_month_report(self,_inp:PhysicalMonth):
from datetime import datetime, time
to_date = datetime.combine(_inp.to_date.date(), time.max)
from_date = _inp.from_date.combine(_inp.from_date.date(), time.min)
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}}},
{"$group":
{'_id': '$type',
'count': {'$sum': 1},
"projectIds": {"$addToSet": "$project_id"},
},
}
]).to_list(None)
return result
async def design_progress_status_state(self):
result = await use_collection("design_progress").aggregate([
{'$match':{'complete_at':{"$exists":0},'parent_id':{"$exists":0}}},
{"$group":
{'_id': {'state':"$state",'type':'$type'},
'count': {'$sum': 1},
"projectIds": {"$addToSet": "$project_id"},
},
}
]).to_list(None)
return result
#روند وضعیت پروژه ها
async def design_progress_status_progress(self):
result = await use_collection("design_progress").aggregate([
{'$match':{'complete_at':{"$exists":0},'parent_id':{"$exists":0}}},
{"$group":
{'_id': {"created_at": {
"$dateToString": {
"format": "%Y-%m-%d", # Format to extract date only (YYYY-MM-DD)
"date": "$created_at"
}
},'type':'$type'},
'count': {'$sum': 1},
"projectIds": {"$addToSet": "$project_id"},
},
}
]).to_list(None)
return result
async def design_sts(self):
result = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
{"$group":{"_id":'$design.sts','count':{'$sum':1},"projectIds": {"$addToSet": "$_id"}}}
]).to_list(None)
return result
async def status_agreement(self):
result = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
{'$match':{'design.status_agreement':{"$exists":1}}},
{"$group":{"_id":'$design.status_agreement','count':{'$sum':1},"projectIds": {"$addToSet": "$_id"}}}
]).to_list(None)
return result
async def status_agreement_progress(self):
result = await use_collection(TaskEnv.CLN_PROJECT_AGREEMENT).aggregate([
{
"$group": {
"_id": {
"created_at": {
"$dateToString": {
"format": "%Y-%m-%d", # Format to extract date only (YYYY-MM-DD)
"date": "$created_at"
}
},
"status": "$status"
},
"count": {"$sum": 1},
"projectIds": {"$addToSet": "$_id"}
}
}
]).to_list(None)
return result
async def get_extra_project(self,project_id:uuid):
res = {}
records_status = await (
use_collection(TaskEnv.CLN_AUDIT_STATUS)
.find({"project_id": project_id})
.sort('$natural', -1)
.to_list(None)
)
res['count_audit_status'] = len(records_status)
res['last_audit_status'] = records_status[0].get('amount') if records_status else None
financial_adjust = await use_collection(TaskEnv.CLN_FINANCIAL_ADJUST).count_documents({'project_id': project_id})
res['count_financial_adjust'] = financial_adjust
financial_adjust_accept = await use_collection(TaskEnv.CLN_FINANCIAL_ADJUST).find({'project_id': project_id,'amount_cycle_supervisor':{"$exists":1}}).sort('$natural', -1).to_list(None)
if financial_adjust_accept and len(financial_adjust_accept) > 0 and 'amount_cycle_supervisor' in financial_adjust_accept[0]:
res['last_financial_adjust'] = financial_adjust_accept[0]['amount_cycle_supervisor']
else:
res['last_financial_adjust'] = None
stats = await use_collection(TaskEnv.CLN_AUDIT_PROGRAM).aggregate([
{"$match": {"project_id": project_id}},
{
"$group": {
"_id": None,
"sum_diff": {"$sum": "$diff_price"},
"count": {"$sum": 1},
"diff_prices": {
"$push": "$diff_price"
}
}
}
]).to_list(None)
if stats:
sum_diff = stats[0]["sum_diff"]
diff_prices = stats[0]["diff_prices"]
result = []
for diff in diff_prices:
percentage = round((diff / sum_diff) * 100, 2) if sum_diff else 0
result.append({
"diff_price": diff,
"percentage": percentage
})
res['audit_program'] = result
return res