Compare commits

..
9 Commits
18 changed files with 1104 additions and 698 deletions
+1 -1
View File
@@ -50,7 +50,7 @@ class SubRecord(pydantic.BaseModel):
class Record(BaseModel):
id: Optional[uuid.UUID] = Field(alias='_id')
title: str = Field(description='عنوان در این فیلد قرار میگیرد')
send: SubRecord = Field(description='اطلاعات ارسال در این فیلد ذخیره می شود')
send: Optional[SubRecord] = Field(description='اطلاعات ارسال در این فیلد ذخیره می شود')
receive: Optional[SubRecord] = Field(description='اطلاعات دریافت در این فیلد ذخیره می شود')
class RecordModel(Record):
+3
View File
@@ -151,5 +151,8 @@ class ProjectStatusAgreement(BaseModel):
project_id: Optional[uuid.UUID] = Field(description="کد شناسایی پروژه در این فیلد قرار می گیرد")
status:str
class ListWithIds(pydantic.BaseModel):
ids: list[uuid.UUID]
+5 -1
View File
@@ -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
to_date:datetime.datetime
+4 -3
View File
@@ -87,6 +87,7 @@ class ContractRepository(BaseRepository):
{'$match':query['query']},
{'$group': {"_id": None, 'count': {'$sum': 1},'sum':{"$sum":"$amount"}}}
]).to_list(None)
return count[0]
else:
return []
print(count)
if len(count)>0:
return count[0]
return []
+740 -652
View File
File diff suppressed because it is too large Load Diff
@@ -139,6 +139,34 @@ class PhysicalProgressRepository(BaseRepository):
else:
await use_collection(COLLECTION).update_one({"_id": _i_model.id},{"$set": _update})
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
View File
@@ -7,7 +7,7 @@ import requests
from fastapi import HTTPException
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.service.mongo_db import use_collection
from core.utils.table_engine import TableEngineRequestType, TableEngineExport
@@ -66,14 +66,14 @@ class ProjectRepository(BaseRepository[ProjectModel]):
async def create(self, coding: ProjectModel):
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:
coding.counter = last_project[0]["counter"] + 1
code = self.create_code(coding)
coding.design.code = 'D' + code
coding.design.code = code
coding.init_id().cu_at()
if coding.monitor:
coding.monitor.code = 'S' + code
coding.monitor.code = code
coding.has_monitor = True
await self.create_report_price(coding)
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)
if update.monitor and not old_project.monitor:
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:
code = self.create_code(update)
update.design.code = 'D' + code
update.design.code = code
if update.monitor:
update.monitor.code = 'S' + code
update.monitor.code = code
if update.monitor:
update.has_monitor = True
await self.update_report_price(update)
@@ -175,7 +175,16 @@ class ProjectRepository(BaseRepository[ProjectModel]):
return True
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
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)
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):
project = await use_collection(TaskEnv.CLN_PROJECT).find_one({"_id": project_id})
if not ('sts' in project['monitor'] and project['monitor']['sts'] > 1):
@@ -224,25 +240,69 @@ class ProjectRepository(BaseRepository[ProjectModel]):
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]:
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),
soft_deleted=True,
model=self.MODEL,
search_cols=['design.title'],
extra_filter=[{'sts': 2}],
extra_filter=extra_filter,
inputs=_input.te) \
.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]:
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),
soft_deleted=True,
model=self.MODEL,
search_cols=['design.title'],
extra_filter=[{'sts': 1}],
extra_filter=extra_filter,
inputs=_input.te) \
.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):
url = 'http://api.khanesaziceco.ir/api/api/project/table'
+187 -9
View File
@@ -3,20 +3,30 @@ 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
class ReportRepository():
async def project_status(self, _inp: StatusReport, type):
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:
match = {f'{type}.sts': {'$exists': 1}}
match = {f'{type}.sts': {'$exists': 1},'sts':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 == 'design':
match.update({
'$or': [
{'has_monitor': False},
{
'monitor.has_design': True,
'has_monitor': True
}
]
})
if type == 'monitor' and _inp.monitor_type:
match.update({'monitor.base_information.type': _inp.monitor_type})
report = await use_collection(TaskEnv.CLN_PROJECT).aggregate([
@@ -140,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:
@@ -220,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": [
@@ -257,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',
@@ -402,20 +499,55 @@ class ReportRepository():
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}
"$match": {
"date_at": {
"$lte": to_date,
"$gte": from_date
}
}
},
{"$group":
{'_id': {"year": "$year", "month": "$month"},
'avg': {'$avg': "$real"}},
}
{
"$lookup": {
"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)
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},
@@ -428,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},
@@ -532,6 +671,45 @@ class ReportRepository():
res['audit_program'] = result
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
View File
@@ -18,9 +18,9 @@ def design():
def monitor():
pass
@router.get('/progress1', tags=_tag_base)
@shrink(repo.addProgress1)
def addProgress1():
@router.get('/progress/madarek', tags=_tag_base)
@shrink(repo.madarek)
def madarek():
pass
@router.get('/progress/physical', tags=_tag_base)
@@ -89,6 +89,11 @@ def addProgressTender():
def changeStatus():
pass
@router.get('/change/design/metri/sts', tags=_tag_base)
@shrink(repo.changeStatusWithMetri)
def changeStatusWithMetri():
pass
@router.get('/progress/monitor/physical', tags=_tag_base)
@shrink(repo.progressMonitorPhysical)
def progressMonitor():
+5
View File
@@ -25,6 +25,11 @@ def create(coding: ThisModel = Body(...)):
def last_record(last:LastRecord):
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='پیشرفت فیزیکی')
@shrink(repo.list_by_project)
def list_by_project(_id: UUID):
+10 -1
View File
@@ -3,7 +3,7 @@ from uuid import UUID
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 core.app import app
from core.utils.router import generate_router, shrink
@@ -32,6 +32,15 @@ def list_project_design():
def list_project_monitor():
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)
@shrink(repo.list_project)
def list_project():
+20 -4
View File
@@ -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)
@@ -139,4 +149,10 @@ def status_agreement_progress():
def get_extra_project(project_id: uuid.UUID):
pass
app.include_router(router)
# فرآیند طراحی گانت چارت
@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)
+3 -3
View File
@@ -4,7 +4,7 @@ auth:
algorithm: 'HS256'
access_token_expire_minutes: 43201
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_ttl: 360
@@ -68,11 +68,11 @@ database:
db: 'omde'
limiter_redis:
url: 'redis://192.168.15.76:6379'
url: 'redis://172.16.1.194:6379'
db: ''
auth_redis:
url: 'redis://192.168.15.231:6379'
url: 'redis://172.16.1.194:6379'
db: '1'
neo4j:
+3 -3
View File
@@ -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'))
if not _cache_auth:
client = httpx.AsyncClient()
headers = {'Content-Type': 'application/json', }
result = await client.request('POST', conf.auth.url, json=_input.dict(), headers=headers)
headers = {'Content-Type': 'application/json', 'Authorization':'Bearer '+_input.token}
result = await client.request('GET', conf.auth.url, json=_input.dict(), headers=headers)
export = result.text
if 'application/json' in result.headers['content-type']:
export = result.json()
@@ -35,6 +34,7 @@ async def validate_token(_input: ValidateTokenInput):
if 'v2' in conf.auth.url:
export = export.get('data')
print(export)
await redis_set(f'{conf.auth.cache_prefix_key}{_cache_key}', export, conf.database.get('auth_redis'),
ex=conf.auth.cache_ttl)
+3 -3
View File
@@ -8,12 +8,12 @@ from core.models.base import 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]
mobile: Optional[str]
name: Optional[str]
first_name: Optional[str]
last_name: Optional[str]
fname: Optional[str]
lname: Optional[str]
is_su: Optional[bool]
unit: Optional[str]
avatar: Optional[str]
+7 -3
View File
@@ -10,7 +10,8 @@ from .utils.Models import TableEngineExport
class NewTableEngine:
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.query_class = query_class
self.mode = mode
@@ -29,6 +30,7 @@ class NewTableEngine:
self.search_cols = search_cols
self.unselect = unselect
self.return_query = return_query
self.collation = collation
self.engine = engine(self)
@staticmethod
@@ -38,10 +40,12 @@ class NewTableEngine:
mode: WorkingMode = WorkingMode.Development,
extra_filter=None,
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,
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
def mssql(query_class, model, inputs, mode: WorkingMode = WorkingMode.Development, extra_filter=None,
+1
View File
@@ -17,6 +17,7 @@ class AbstractEngineClass(abc.ABC):
self.soft_deleted = table_engine.soft_deleted
self.unselect = table_engine.unselect
self.return_query = table_engine.return_query
self.collation = {'locale': 'fa'}
@abc.abstractmethod
def exe(self):
+4
View File
@@ -54,6 +54,10 @@ class MongoEngine(AbstractEngineClass):
else:
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:
res = await tmp.to_list(None)
self.input.e.d = await self.generate_output(res)