Compare commits
9
Commits
d1f6c1830f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee3a5025c1 | ||
|
|
0cbf543940 | ||
|
|
b74b0067a6 | ||
|
|
6cd225f395 | ||
|
|
4ddac54ab7 | ||
|
|
439f7b3c15 | ||
|
|
9fd5481461 | ||
|
|
198784f144 | ||
|
|
759c2216c6 |
@@ -50,7 +50,7 @@ class SubRecord(pydantic.BaseModel):
|
|||||||
class Record(BaseModel):
|
class Record(BaseModel):
|
||||||
id: Optional[uuid.UUID] = Field(alias='_id')
|
id: Optional[uuid.UUID] = Field(alias='_id')
|
||||||
title: str = Field(description='عنوان در این فیلد قرار میگیرد')
|
title: str = Field(description='عنوان در این فیلد قرار میگیرد')
|
||||||
send: SubRecord = Field(description='اطلاعات ارسال در این فیلد ذخیره می شود')
|
send: Optional[SubRecord] = Field(description='اطلاعات ارسال در این فیلد ذخیره می شود')
|
||||||
receive: Optional[SubRecord] = Field(description='اطلاعات دریافت در این فیلد ذخیره می شود')
|
receive: Optional[SubRecord] = Field(description='اطلاعات دریافت در این فیلد ذخیره می شود')
|
||||||
|
|
||||||
class RecordModel(Record):
|
class RecordModel(Record):
|
||||||
|
|||||||
@@ -151,5 +151,8 @@ class ProjectStatusAgreement(BaseModel):
|
|||||||
project_id: Optional[uuid.UUID] = Field(description="کد شناسایی پروژه در این فیلد قرار می گیرد")
|
project_id: Optional[uuid.UUID] = Field(description="کد شناسایی پروژه در این فیلد قرار می گیرد")
|
||||||
status:str
|
status:str
|
||||||
|
|
||||||
|
class ListWithIds(pydantic.BaseModel):
|
||||||
|
ids: list[uuid.UUID]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ class DelayDonutDetail(pydantic.BaseModel):
|
|||||||
project_id:uuid.UUID
|
project_id:uuid.UUID
|
||||||
select:Literal['financial','force_major','technical']
|
select:Literal['financial','force_major','technical']
|
||||||
|
|
||||||
|
class DonutReport(pydantic.BaseModel):
|
||||||
|
only_current: bool = Field(default=False, description='فقط پروژههای نظارت جاری؛ مقدار false برای همه پروژههای نظارت')
|
||||||
|
|
||||||
|
|
||||||
class DonutList(pydantic.BaseModel):
|
class DonutList(pydantic.BaseModel):
|
||||||
type: int = Field(description='مقدار وارد شده در گزارش قبل')
|
type: int = Field(description='مقدار وارد شده در گزارش قبل')
|
||||||
donut_select: str = Field(description='آیتم دونات انتخاب شده')
|
donut_select: str = Field(description='آیتم دونات انتخاب شده')
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ class ContractRepository(BaseRepository):
|
|||||||
{'$match':query['query']},
|
{'$match':query['query']},
|
||||||
{'$group': {"_id": None, 'count': {'$sum': 1},'sum':{"$sum":"$amount"}}}
|
{'$group': {"_id": None, 'count': {'$sum': 1},'sum':{"$sum":"$amount"}}}
|
||||||
]).to_list(None)
|
]).to_list(None)
|
||||||
return count[0]
|
print(count)
|
||||||
else:
|
if len(count)>0:
|
||||||
return []
|
return count[0]
|
||||||
|
return []
|
||||||
|
|||||||
+740
-652
File diff suppressed because it is too large
Load Diff
@@ -139,6 +139,34 @@ class PhysicalProgressRepository(BaseRepository):
|
|||||||
else:
|
else:
|
||||||
await use_collection(COLLECTION).update_one({"_id": _i_model.id},{"$set": _update})
|
await use_collection(COLLECTION).update_one({"_id": _i_model.id},{"$set": _update})
|
||||||
return True
|
return True
|
||||||
|
# for recalc medium progress in database
|
||||||
|
# async def recalc_medium_progress(self):
|
||||||
|
# print('111111111111111111111')
|
||||||
|
# coll = use_collection(TaskEnv.CLN_MONITOR_PYSICAL)
|
||||||
|
# project_ids = await coll.distinct(
|
||||||
|
# "project_id",
|
||||||
|
# {"deleted_at": {"$exists": False}},
|
||||||
|
# )
|
||||||
|
# print('222222222222222222222')
|
||||||
|
#
|
||||||
|
# updated = 0
|
||||||
|
# for pid in project_ids:
|
||||||
|
# print('piiiiiidf',pid)
|
||||||
|
# records = await coll.find({
|
||||||
|
# "project_id": pid,
|
||||||
|
# "deleted_at": {"$exists": False},
|
||||||
|
# }).sort([("date_at", 1), ("_id", 1)]).to_list(None)
|
||||||
|
#
|
||||||
|
# total = 0
|
||||||
|
# for i, rec in enumerate(records, start=1):
|
||||||
|
# total += rec.get("real") or 0
|
||||||
|
# await coll.update_one(
|
||||||
|
# {"_id": rec["_id"]},
|
||||||
|
# {"$set": {"medium_progress": round(total / i, 1)}},
|
||||||
|
# )
|
||||||
|
# updated += 1
|
||||||
|
#
|
||||||
|
# return {"projects": len(project_ids), "updated": updated}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+72
-12
@@ -7,7 +7,7 @@ import requests
|
|||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
|
||||||
from app.config import TaskEnv
|
from app.config import TaskEnv
|
||||||
from app.models.project import ProjectModel, UpdateSts, ProjectSts, Design, ProjectStatusAgreement
|
from app.models.project import ProjectModel, UpdateSts, ProjectSts, Design, ProjectStatusAgreement, ListWithIds
|
||||||
from core.repositories.base import BaseRepository
|
from core.repositories.base import BaseRepository
|
||||||
from core.service.mongo_db import use_collection
|
from core.service.mongo_db import use_collection
|
||||||
from core.utils.table_engine import TableEngineRequestType, TableEngineExport
|
from core.utils.table_engine import TableEngineRequestType, TableEngineExport
|
||||||
@@ -66,14 +66,14 @@ class ProjectRepository(BaseRepository[ProjectModel]):
|
|||||||
|
|
||||||
async def create(self, coding: ProjectModel):
|
async def create(self, coding: ProjectModel):
|
||||||
coding.counter = 1
|
coding.counter = 1
|
||||||
last_project = await use_collection(COLLECTION).find({}).sort("$natural", -1).to_list(None)
|
last_project = await use_collection(COLLECTION).find({}).sort("counter", -1).to_list(None)
|
||||||
if last_project:
|
if last_project:
|
||||||
coding.counter = last_project[0]["counter"] + 1
|
coding.counter = last_project[0]["counter"] + 1
|
||||||
code = self.create_code(coding)
|
code = self.create_code(coding)
|
||||||
coding.design.code = 'D' + code
|
coding.design.code = code
|
||||||
coding.init_id().cu_at()
|
coding.init_id().cu_at()
|
||||||
if coding.monitor:
|
if coding.monitor:
|
||||||
coding.monitor.code = 'S' + code
|
coding.monitor.code = code
|
||||||
coding.has_monitor = True
|
coding.has_monitor = True
|
||||||
await self.create_report_price(coding)
|
await self.create_report_price(coding)
|
||||||
if coding.monitor.detail.date_create_project and coding.monitor.detail.first_time:
|
if coding.monitor.detail.date_create_project and coding.monitor.detail.first_time:
|
||||||
@@ -95,12 +95,12 @@ class ProjectRepository(BaseRepository[ProjectModel]):
|
|||||||
old_project = ProjectModel(**old_project_dict)
|
old_project = ProjectModel(**old_project_dict)
|
||||||
if update.monitor and not old_project.monitor:
|
if update.monitor and not old_project.monitor:
|
||||||
code = self.create_code(update)
|
code = self.create_code(update)
|
||||||
update.monitor.code = 'S' + code
|
update.monitor.code = code
|
||||||
if update.design.nature != old_project.design.nature or update.design.type != old_project.design.type:
|
if update.design.nature != old_project.design.nature or update.design.type != old_project.design.type:
|
||||||
code = self.create_code(update)
|
code = self.create_code(update)
|
||||||
update.design.code = 'D' + code
|
update.design.code = code
|
||||||
if update.monitor:
|
if update.monitor:
|
||||||
update.monitor.code = 'S' + code
|
update.monitor.code = code
|
||||||
if update.monitor:
|
if update.monitor:
|
||||||
update.has_monitor = True
|
update.has_monitor = True
|
||||||
await self.update_report_price(update)
|
await self.update_report_price(update)
|
||||||
@@ -175,7 +175,16 @@ class ProjectRepository(BaseRepository[ProjectModel]):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
async def list_project_design(self):
|
async def list_project_design(self):
|
||||||
project = await use_collection(COLLECTION).find({'monitor': {"$exists": 0}}).to_list(None)
|
project = await use_collection(COLLECTION).find({
|
||||||
|
'$or': [
|
||||||
|
{'has_monitor': False},
|
||||||
|
{'monitor': {'$exists': 0}},
|
||||||
|
{
|
||||||
|
'has_monitor': True,
|
||||||
|
'monitor.has_design': True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).to_list(None)
|
||||||
return project
|
return project
|
||||||
|
|
||||||
async def list_project_monitor(self):
|
async def list_project_monitor(self):
|
||||||
@@ -200,6 +209,13 @@ class ProjectRepository(BaseRepository[ProjectModel]):
|
|||||||
project = await use_collection(TaskEnv.CLN_PROJECT).find({}).to_list(None)
|
project = await use_collection(TaskEnv.CLN_PROJECT).find({}).to_list(None)
|
||||||
return project
|
return project
|
||||||
|
|
||||||
|
async def list_project_with_select(self):
|
||||||
|
project = await use_collection(TaskEnv.CLN_PROJECT).find({},{"_id":1,"design.title":1,"design.code":1}).to_list(None)
|
||||||
|
return project
|
||||||
|
async def list_project_with_ids(self,inp:ListWithIds):
|
||||||
|
projects = await use_collection(TaskEnv.CLN_PROJECT).find({"_id":{"$in":inp.ids}}).to_list(None)
|
||||||
|
return projects
|
||||||
|
|
||||||
async def set_sts_two_for_monitor(self, project_id: uuid.UUID):
|
async def set_sts_two_for_monitor(self, project_id: uuid.UUID):
|
||||||
project = await use_collection(TaskEnv.CLN_PROJECT).find_one({"_id": project_id})
|
project = await use_collection(TaskEnv.CLN_PROJECT).find_one({"_id": project_id})
|
||||||
if not ('sts' in project['monitor'] and project['monitor']['sts'] > 1):
|
if not ('sts' in project['monitor'] and project['monitor']['sts'] > 1):
|
||||||
@@ -224,25 +240,69 @@ class ProjectRepository(BaseRepository[ProjectModel]):
|
|||||||
|
|
||||||
return projects
|
return projects
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _has_design_sts_filter(te_input) -> bool:
|
||||||
|
if not te_input:
|
||||||
|
return False
|
||||||
|
f_list = getattr(te_input, 'f', None) if not isinstance(te_input, dict) else te_input.get('f')
|
||||||
|
if not f_list:
|
||||||
|
return False
|
||||||
|
for scope in f_list:
|
||||||
|
items = scope.get('items', []) if isinstance(scope, dict) else getattr(scope, 'items', [])
|
||||||
|
if items:
|
||||||
|
for item in items:
|
||||||
|
col = item.get('col') if isinstance(item, dict) else getattr(item, 'col', '')
|
||||||
|
if col == 'design.sts':
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
async def fetch_delete(self, _input: TableEngineRequestType) -> TableEngineExport[T]:
|
async def fetch_delete(self, _input: TableEngineRequestType) -> TableEngineExport[T]:
|
||||||
return await NewTableEngine.mongo(
|
extra_filter = [{'sts': 2}]
|
||||||
|
if self._has_design_sts_filter(_input.te if _input else None):
|
||||||
|
extra_filter.append({
|
||||||
|
'$or': [
|
||||||
|
{'has_monitor': False},
|
||||||
|
{'monitor': {'$exists': False}},
|
||||||
|
{'has_monitor': True, 'monitor.has_design': True}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
result = await NewTableEngine.mongo(
|
||||||
query_class=use_collection(self.COLLECTION),
|
query_class=use_collection(self.COLLECTION),
|
||||||
soft_deleted=True,
|
soft_deleted=True,
|
||||||
model=self.MODEL,
|
model=self.MODEL,
|
||||||
search_cols=['design.title'],
|
search_cols=['design.title'],
|
||||||
extra_filter=[{'sts': 2}],
|
extra_filter=extra_filter,
|
||||||
inputs=_input.te) \
|
inputs=_input.te) \
|
||||||
.to_dict()
|
.to_dict()
|
||||||
|
if result and result.rows:
|
||||||
|
for row in result.rows:
|
||||||
|
if row.monitor and row.monitor.has_design is False:
|
||||||
|
row.design.sts = None
|
||||||
|
return result
|
||||||
|
|
||||||
async def fetch(self, _input: TableEngineRequestType) -> TableEngineExport[T]:
|
async def fetch(self, _input: TableEngineRequestType) -> TableEngineExport[T]:
|
||||||
return await NewTableEngine.mongo(
|
extra_filter = [{'sts': 1}]
|
||||||
|
if self._has_design_sts_filter(_input.te if _input else None):
|
||||||
|
extra_filter.append({
|
||||||
|
'$or': [
|
||||||
|
{'has_monitor': False},
|
||||||
|
{'monitor': {'$exists': False}},
|
||||||
|
{'has_monitor': True, 'monitor.has_design': True}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
result = await NewTableEngine.mongo(
|
||||||
query_class=use_collection(self.COLLECTION),
|
query_class=use_collection(self.COLLECTION),
|
||||||
soft_deleted=True,
|
soft_deleted=True,
|
||||||
model=self.MODEL,
|
model=self.MODEL,
|
||||||
search_cols=['design.title'],
|
search_cols=['design.title'],
|
||||||
extra_filter=[{'sts': 1}],
|
extra_filter=extra_filter,
|
||||||
inputs=_input.te) \
|
inputs=_input.te) \
|
||||||
.to_dict()
|
.to_dict()
|
||||||
|
if result and result.rows:
|
||||||
|
for row in result.rows:
|
||||||
|
if row.monitor and row.monitor.has_design is False:
|
||||||
|
row.design.sts = None
|
||||||
|
return result
|
||||||
|
|
||||||
async def get_all(self):
|
async def get_all(self):
|
||||||
url = 'http://api.khanesaziceco.ir/api/api/project/table'
|
url = 'http://api.khanesaziceco.ir/api/api/project/table'
|
||||||
|
|||||||
+187
-9
@@ -3,20 +3,30 @@ from datetime import time
|
|||||||
|
|
||||||
from app.config import TaskEnv
|
from app.config import TaskEnv
|
||||||
from app.models.project import ProjectPriceReport
|
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
|
from core.service.mongo_db import use_collection
|
||||||
|
|
||||||
|
|
||||||
class ReportRepository():
|
class ReportRepository():
|
||||||
async def project_status(self, _inp: StatusReport, type):
|
async def project_status(self, _inp: StatusReport, type):
|
||||||
if _inp.state:
|
if _inp.state:
|
||||||
match = {f'{type}.sts': {'$exists': 1}, 'design.state': _inp.state}
|
match = {f'{type}.sts': {'$exists': 1}, 'design.state': _inp.state,'sts':1}
|
||||||
else:
|
else:
|
||||||
match = {f'{type}.sts': {'$exists': 1}}
|
match = {f'{type}.sts': {'$exists': 1},'sts':1}
|
||||||
if _inp.type_id:
|
if _inp.type_id:
|
||||||
match.update({'design.type_id': _inp.type_id})
|
match.update({'design.type_id': _inp.type_id})
|
||||||
if _inp.nature_id:
|
if _inp.nature_id:
|
||||||
match.update({'design.nature_id': _inp.nature_id})
|
match.update({'design.nature_id': _inp.nature_id})
|
||||||
|
if type == 'design':
|
||||||
|
match.update({
|
||||||
|
'$or': [
|
||||||
|
{'has_monitor': False},
|
||||||
|
{
|
||||||
|
'monitor.has_design': True,
|
||||||
|
'has_monitor': True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
if type == 'monitor' and _inp.monitor_type:
|
if type == 'monitor' and _inp.monitor_type:
|
||||||
match.update({'monitor.base_information.type': _inp.monitor_type})
|
match.update({'monitor.base_information.type': _inp.monitor_type})
|
||||||
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
|
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
|
||||||
@@ -140,6 +150,64 @@ class ReportRepository():
|
|||||||
]).to_list(None)
|
]).to_list(None)
|
||||||
return report
|
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):
|
async def list_donut(self, _inp: DonutList):
|
||||||
_filter = None
|
_filter = None
|
||||||
if _inp.type == 1:
|
if _inp.type == 1:
|
||||||
@@ -220,6 +288,13 @@ class ReportRepository():
|
|||||||
async def categorize_deviation(self):
|
async def categorize_deviation(self):
|
||||||
report = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate(
|
report = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate(
|
||||||
[{"$match": {"deviation": {"$exists": True, "$ne": None}}},
|
[{"$match": {"deviation": {"$exists": True, "$ne": None}}},
|
||||||
|
{"$lookup": {
|
||||||
|
"from": TaskEnv.CLN_PROJECT,
|
||||||
|
"localField": "project_id",
|
||||||
|
"foreignField": "_id",
|
||||||
|
"as": "project"
|
||||||
|
}},
|
||||||
|
{"$match": {"project.monitor.sts": 2}},
|
||||||
{"$group": {
|
{"$group": {
|
||||||
"_id": {
|
"_id": {
|
||||||
"$cond": [
|
"$cond": [
|
||||||
@@ -257,6 +332,28 @@ class ReportRepository():
|
|||||||
]).to_list(None)
|
]).to_list(None)
|
||||||
return report
|
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):
|
async def list_delay_donut(self, _select: str):
|
||||||
get_list = []
|
get_list = []
|
||||||
_map = {'1': 'financial.total', '2': 'force_major.total', '3': 'technical.total', '4': 'extra_new_work',
|
_map = {'1': 'financial.total', '2': 'force_major.total', '3': 'technical.total', '4': 'extra_new_work',
|
||||||
@@ -402,20 +499,55 @@ class ReportRepository():
|
|||||||
to_date = datetime.combine(_inp.to_date.date(), time.max)
|
to_date = datetime.combine(_inp.to_date.date(), time.max)
|
||||||
from_date = _inp.from_date.combine(_inp.from_date.date(), time.min)
|
from_date = _inp.from_date.combine(_inp.from_date.date(), time.min)
|
||||||
result = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate([
|
result = await use_collection(TaskEnv.CLN_MONITOR_PYSICAL).aggregate([
|
||||||
{"$match":{"date_at":{"$lte":to_date,"$gte":from_date}}},
|
|
||||||
{
|
{
|
||||||
"$sort": {'date_at': -1}
|
"$match": {
|
||||||
|
"date_at": {
|
||||||
|
"$lte": to_date,
|
||||||
|
"$gte": from_date
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{"$group":
|
{
|
||||||
{'_id': {"year": "$year", "month": "$month"},
|
"$lookup": {
|
||||||
'avg': {'$avg': "$real"}},
|
"from": TaskEnv.CLN_PROJECT,
|
||||||
}
|
"localField": "project_id",
|
||||||
|
"foreignField": "_id",
|
||||||
|
"as": "project"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"$match": {"project.monitor.sts": 2}},
|
||||||
|
{
|
||||||
|
"$group": {
|
||||||
|
"_id": {
|
||||||
|
"year": "$year",
|
||||||
|
"month": "$month"
|
||||||
|
},
|
||||||
|
"avg": {
|
||||||
|
"$avg": "$real"
|
||||||
|
},
|
||||||
|
"sort_date": {
|
||||||
|
"$max": "$date_at"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$sort": {
|
||||||
|
"sort_date": -1
|
||||||
|
}
|
||||||
|
}
|
||||||
]).to_list(None)
|
]).to_list(None)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def design_progress_status(self):
|
async def design_progress_status(self):
|
||||||
result = await use_collection("design_progress").aggregate([
|
result = await use_collection("design_progress").aggregate([
|
||||||
{'$match':{'complete_at':{"$exists":0},'parent_id':{"$exists":0}}},
|
{'$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":
|
{"$group":
|
||||||
{'_id': '$type',
|
{'_id': '$type',
|
||||||
'count': {'$sum': 1},
|
'count': {'$sum': 1},
|
||||||
@@ -428,6 +560,13 @@ class ReportRepository():
|
|||||||
async def design_progress_status_state(self):
|
async def design_progress_status_state(self):
|
||||||
result = await use_collection("design_progress").aggregate([
|
result = await use_collection("design_progress").aggregate([
|
||||||
{'$match':{'complete_at':{"$exists":0},'parent_id':{"$exists":0}}},
|
{'$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":
|
{"$group":
|
||||||
{'_id': {'state':"$state",'type':'$type'},
|
{'_id': {'state':"$state",'type':'$type'},
|
||||||
'count': {'$sum': 1},
|
'count': {'$sum': 1},
|
||||||
@@ -532,6 +671,45 @@ class ReportRepository():
|
|||||||
res['audit_program'] = result
|
res['audit_program'] = result
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
# فرآیند طراحی گانت چارت
|
||||||
|
async def design_chart(self, project_id: uuid):
|
||||||
|
list_design_progress = await use_collection('design_progress').find({"project_id": project_id}).sort('type', 1).to_list(None)
|
||||||
|
if not list_design_progress:
|
||||||
|
return {}
|
||||||
|
list_design_progress_ids = [doc["_id"] for doc in list_design_progress]
|
||||||
|
list_design_progress_record = await use_collection('design_progress_record').find({"design_progress_id": {"$in":list_design_progress_ids}}).to_list(None)
|
||||||
|
grouped_records = {}
|
||||||
|
for i in list_design_progress:
|
||||||
|
t = i["type"]
|
||||||
|
st = i.get("sub_type")
|
||||||
|
if st:
|
||||||
|
grouped_records.setdefault(t, {})[st] = {
|
||||||
|
"progress": i,
|
||||||
|
"records": []
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
grouped_records.setdefault(t, {
|
||||||
|
"progress": i,
|
||||||
|
"records": []
|
||||||
|
})
|
||||||
|
|
||||||
|
print(grouped_records)
|
||||||
|
for item in list_design_progress:
|
||||||
|
for record in list_design_progress_record:
|
||||||
|
if record["design_progress_id"] == item['_id']:
|
||||||
|
if 'sub_type' not in item:
|
||||||
|
grouped_records[item['type']]["records"].append(record)
|
||||||
|
else:
|
||||||
|
grouped_records[item['type']][item['sub_type']]["records"].append(record)
|
||||||
|
return grouped_records
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+8
-3
@@ -18,9 +18,9 @@ def design():
|
|||||||
def monitor():
|
def monitor():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@router.get('/progress1', tags=_tag_base)
|
@router.get('/progress/madarek', tags=_tag_base)
|
||||||
@shrink(repo.addProgress1)
|
@shrink(repo.madarek)
|
||||||
def addProgress1():
|
def madarek():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@router.get('/progress/physical', tags=_tag_base)
|
@router.get('/progress/physical', tags=_tag_base)
|
||||||
@@ -89,6 +89,11 @@ def addProgressTender():
|
|||||||
def changeStatus():
|
def changeStatus():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@router.get('/change/design/metri/sts', tags=_tag_base)
|
||||||
|
@shrink(repo.changeStatusWithMetri)
|
||||||
|
def changeStatusWithMetri():
|
||||||
|
pass
|
||||||
|
|
||||||
@router.get('/progress/monitor/physical', tags=_tag_base)
|
@router.get('/progress/monitor/physical', tags=_tag_base)
|
||||||
@shrink(repo.progressMonitorPhysical)
|
@shrink(repo.progressMonitorPhysical)
|
||||||
def progressMonitor():
|
def progressMonitor():
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ def create(coding: ThisModel = Body(...)):
|
|||||||
def last_record(last:LastRecord):
|
def last_record(last:LastRecord):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# @router.get('/progress/rediv', response_model=list[dict], tags=_tag_base, description='پیشرفت فیزیکی')
|
||||||
|
# @shrink(repo.recalc_medium_progress)
|
||||||
|
# def recalc_medium_progress():
|
||||||
|
# pass
|
||||||
|
|
||||||
@router.get('/list/{_id}', response_model=List[ThisModel], tags=_tag_base, description='پیشرفت فیزیکی')
|
@router.get('/list/{_id}', response_model=List[ThisModel], tags=_tag_base, description='پیشرفت فیزیکی')
|
||||||
@shrink(repo.list_by_project)
|
@shrink(repo.list_by_project)
|
||||||
def list_by_project(_id: UUID):
|
def list_by_project(_id: UUID):
|
||||||
|
|||||||
+10
-1
@@ -3,7 +3,7 @@ from uuid import UUID
|
|||||||
|
|
||||||
from fastapi import Body
|
from fastapi import Body
|
||||||
|
|
||||||
from app.models.project import ProjectModel, UpdateSts
|
from app.models.project import ProjectModel, UpdateSts, ListWithIds
|
||||||
from app.repositories.project import ProjectRepository
|
from app.repositories.project import ProjectRepository
|
||||||
from core.app import app
|
from core.app import app
|
||||||
from core.utils.router import generate_router, shrink
|
from core.utils.router import generate_router, shrink
|
||||||
@@ -32,6 +32,15 @@ def list_project_design():
|
|||||||
def list_project_monitor():
|
def list_project_monitor():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@router.post('/list/ids', response_model=ThisModel, tags=_tag_base)
|
||||||
|
@shrink(repo.list_project_with_ids)
|
||||||
|
def list_project_with_ids(inp:ListWithIds):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@router.get('/list/all', response_model=List[ThisModel], tags=_tag_base)
|
||||||
|
@shrink(repo.list_project_with_select)
|
||||||
|
def list_project_with_select():
|
||||||
|
pass
|
||||||
@router.get('/list/project', response_model=List[ThisModel], tags=_tag_base)
|
@router.get('/list/project', response_model=List[ThisModel], tags=_tag_base)
|
||||||
@shrink(repo.list_project)
|
@shrink(repo.list_project)
|
||||||
def list_project():
|
def list_project():
|
||||||
|
|||||||
+19
-3
@@ -2,7 +2,7 @@ import uuid
|
|||||||
|
|
||||||
from fastapi import Body
|
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 app.repositories.report import ReportRepository
|
||||||
from core.app import app
|
from core.app import app
|
||||||
from core.utils.router import generate_router, shrink
|
from core.utils.router import generate_router, shrink
|
||||||
@@ -62,15 +62,25 @@ def sum_add_time_end_project():
|
|||||||
@shrink(repo.delay_donut_all)
|
@shrink(repo.delay_donut_all)
|
||||||
def delay_donut_all():
|
def delay_donut_all():
|
||||||
pass
|
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)
|
@router.get('/donut/delay/{_select}', tags=_tag_base)
|
||||||
@shrink(repo.list_delay_donut)
|
@shrink(repo.list_delay_donut)
|
||||||
def list_delay_donut(_select):
|
def list_delay_donut(_select):
|
||||||
pass
|
pass
|
||||||
#تفکیک پروژه ها بر حسب زیربنا و تفکیک ماهیت پروژه و تفکیک بر حسب نوع پروژه
|
#تفکیک پروژه ها بر حسب زیربنا و تفکیک ماهیت پروژه و تفکیک بر حسب نوع پروژه
|
||||||
@router.get('/donut/{_select}', tags=_tag_base)
|
@router.post('/donut/{_select}', tags=_tag_base)
|
||||||
@shrink(repo.donut)
|
@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
|
pass
|
||||||
|
|
||||||
@router.post('/list-donut', tags=_tag_base)
|
@router.post('/list-donut', tags=_tag_base)
|
||||||
@@ -139,4 +149,10 @@ def status_agreement_progress():
|
|||||||
def get_extra_project(project_id: uuid.UUID):
|
def get_extra_project(project_id: uuid.UUID):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# فرآیند طراحی گانت چارت
|
||||||
|
@router.get('/design/chart/{project_id}', tags=_tag_base)
|
||||||
|
@shrink(repo.design_chart)
|
||||||
|
def design_chart(project_id: uuid.UUID):
|
||||||
|
pass
|
||||||
|
|
||||||
app.include_router(router)
|
app.include_router(router)
|
||||||
+3
-3
@@ -4,7 +4,7 @@ auth:
|
|||||||
algorithm: 'HS256'
|
algorithm: 'HS256'
|
||||||
access_token_expire_minutes: 43201
|
access_token_expire_minutes: 43201
|
||||||
refresh_token_expire_minutes: 43200
|
refresh_token_expire_minutes: 43200
|
||||||
url: 'https://auth.hacoupian.net/v2/auth/validate-token'
|
url: 'http://pm.khanesaziceco.ir/api/api/me'
|
||||||
cache_prefix_key: 'auth_key_'
|
cache_prefix_key: 'auth_key_'
|
||||||
cache_ttl: 360
|
cache_ttl: 360
|
||||||
|
|
||||||
@@ -68,11 +68,11 @@ database:
|
|||||||
db: 'omde'
|
db: 'omde'
|
||||||
|
|
||||||
limiter_redis:
|
limiter_redis:
|
||||||
url: 'redis://192.168.15.76:6379'
|
url: 'redis://172.16.1.194:6379'
|
||||||
db: ''
|
db: ''
|
||||||
|
|
||||||
auth_redis:
|
auth_redis:
|
||||||
url: 'redis://192.168.15.231:6379'
|
url: 'redis://172.16.1.194:6379'
|
||||||
db: '1'
|
db: '1'
|
||||||
|
|
||||||
neo4j:
|
neo4j:
|
||||||
|
|||||||
@@ -23,9 +23,8 @@ async def validate_token(_input: ValidateTokenInput):
|
|||||||
_cache_auth = await redis_get(f'{conf.auth.cache_prefix_key}{_cache_key}', conf.database.get('auth_redis'))
|
_cache_auth = await redis_get(f'{conf.auth.cache_prefix_key}{_cache_key}', conf.database.get('auth_redis'))
|
||||||
if not _cache_auth:
|
if not _cache_auth:
|
||||||
client = httpx.AsyncClient()
|
client = httpx.AsyncClient()
|
||||||
headers = {'Content-Type': 'application/json', }
|
headers = {'Content-Type': 'application/json', 'Authorization':'Bearer '+_input.token}
|
||||||
|
result = await client.request('GET', conf.auth.url, json=_input.dict(), headers=headers)
|
||||||
result = await client.request('POST', conf.auth.url, json=_input.dict(), headers=headers)
|
|
||||||
export = result.text
|
export = result.text
|
||||||
if 'application/json' in result.headers['content-type']:
|
if 'application/json' in result.headers['content-type']:
|
||||||
export = result.json()
|
export = result.json()
|
||||||
@@ -35,6 +34,7 @@ async def validate_token(_input: ValidateTokenInput):
|
|||||||
|
|
||||||
if 'v2' in conf.auth.url:
|
if 'v2' in conf.auth.url:
|
||||||
export = export.get('data')
|
export = export.get('data')
|
||||||
|
print(export)
|
||||||
|
|
||||||
await redis_set(f'{conf.auth.cache_prefix_key}{_cache_key}', export, conf.database.get('auth_redis'),
|
await redis_set(f'{conf.auth.cache_prefix_key}{_cache_key}', export, conf.database.get('auth_redis'),
|
||||||
ex=conf.auth.cache_ttl)
|
ex=conf.auth.cache_ttl)
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ from core.models.base import BaseModel
|
|||||||
|
|
||||||
|
|
||||||
class UserModel(BaseModel):
|
class UserModel(BaseModel):
|
||||||
id: Optional[Union[uuid.UUID, str]] = Field(alias='_id')
|
id: Optional[Union[uuid.UUID, str, int]] = Field(alias='_id')
|
||||||
username: Optional[str]
|
username: Optional[str]
|
||||||
mobile: Optional[str]
|
mobile: Optional[str]
|
||||||
name: Optional[str]
|
name: Optional[str]
|
||||||
first_name: Optional[str]
|
fname: Optional[str]
|
||||||
last_name: Optional[str]
|
lname: Optional[str]
|
||||||
is_su: Optional[bool]
|
is_su: Optional[bool]
|
||||||
unit: Optional[str]
|
unit: Optional[str]
|
||||||
avatar: Optional[str]
|
avatar: Optional[str]
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ from .utils.Models import TableEngineExport
|
|||||||
|
|
||||||
class NewTableEngine:
|
class NewTableEngine:
|
||||||
def __init__(self, query_class, model, inputs, mode, engine: AbstractEngine, extra_filter,
|
def __init__(self, query_class, model, inputs, mode, engine: AbstractEngine, extra_filter,
|
||||||
default_sort_by, joins, search_cols, options=None, soft_deleted=False, unselect={}, return_query=False):
|
default_sort_by, joins, search_cols, options=None, soft_deleted=False, unselect={}, return_query=False,
|
||||||
|
collation={'locale': 'fa'}):
|
||||||
self.model = model
|
self.model = model
|
||||||
self.query_class = query_class
|
self.query_class = query_class
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
@@ -29,6 +30,7 @@ class NewTableEngine:
|
|||||||
self.search_cols = search_cols
|
self.search_cols = search_cols
|
||||||
self.unselect = unselect
|
self.unselect = unselect
|
||||||
self.return_query = return_query
|
self.return_query = return_query
|
||||||
|
self.collation = collation
|
||||||
self.engine = engine(self)
|
self.engine = engine(self)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -38,10 +40,12 @@ class NewTableEngine:
|
|||||||
mode: WorkingMode = WorkingMode.Development,
|
mode: WorkingMode = WorkingMode.Development,
|
||||||
extra_filter=None,
|
extra_filter=None,
|
||||||
soft_deleted=False,
|
soft_deleted=False,
|
||||||
default_sort_by=None, joins=None, search_cols=[] ,unselect={}, return_query=False):
|
default_sort_by=None, joins=None, search_cols=[] ,unselect={}, return_query=False,
|
||||||
|
collation={'locale': 'fa'}):
|
||||||
return NewTableEngine(query_class, model, inputs, mode, engine=MongoEngine, extra_filter=extra_filter,
|
return NewTableEngine(query_class, model, inputs, mode, engine=MongoEngine, extra_filter=extra_filter,
|
||||||
default_sort_by=default_sort_by, joins=joins, search_cols=search_cols,
|
default_sort_by=default_sort_by, joins=joins, search_cols=search_cols,
|
||||||
soft_deleted=soft_deleted,unselect=unselect, return_query=return_query)
|
soft_deleted=soft_deleted,unselect=unselect, return_query=return_query,
|
||||||
|
collation=collation)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def mssql(query_class, model, inputs, mode: WorkingMode = WorkingMode.Development, extra_filter=None,
|
def mssql(query_class, model, inputs, mode: WorkingMode = WorkingMode.Development, extra_filter=None,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class AbstractEngineClass(abc.ABC):
|
|||||||
self.soft_deleted = table_engine.soft_deleted
|
self.soft_deleted = table_engine.soft_deleted
|
||||||
self.unselect = table_engine.unselect
|
self.unselect = table_engine.unselect
|
||||||
self.return_query = table_engine.return_query
|
self.return_query = table_engine.return_query
|
||||||
|
self.collation = {'locale': 'fa'}
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def exe(self):
|
def exe(self):
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ class MongoEngine(AbstractEngineClass):
|
|||||||
else:
|
else:
|
||||||
tmp = tmp.sort(sort_by)
|
tmp = tmp.sort(sort_by)
|
||||||
|
|
||||||
|
is_natural = isinstance(sort_by, dict) and sort_by.get('key_or_list') == '$natural'
|
||||||
|
if getattr(self, 'collation', None) and not is_natural:
|
||||||
|
tmp = tmp.collation(self.collation)
|
||||||
|
|
||||||
if self.input.e and self.input.e.ot:
|
if self.input.e and self.input.e.ot:
|
||||||
res = await tmp.to_list(None)
|
res = await tmp.to_list(None)
|
||||||
self.input.e.d = await self.generate_output(res)
|
self.input.e.d = await self.generate_output(res)
|
||||||
|
|||||||
Reference in New Issue
Block a user