feat(root):add mysql

This commit is contained in:
shahzeydyfah
2026-02-17 23:52:14 +03:30
parent abb1c01753
commit 189df529d9
4 changed files with 126 additions and 6 deletions
+63 -4
View File
@@ -17,6 +17,7 @@ from celery import shared_task
from .AbstractEngine import AbstractEngineClass
from ..utils.Models import FilterItem, FilterScope, OutPutType
from ..utils.excel_value_maps import EXCEL_VALUE_MAP_REGISTRY
from app.repositories.mysql_const_repo import MySQLConstRepository
# def zero_time_data(date, is_max=False):
@@ -39,6 +40,7 @@ class MongoEngine(AbstractEngineClass):
rows = []
stack = []
filters = {}
_const_cache: dict = None # کش const ها از MySQL
async def exe(self):
_f = self.filters = self.set_filters()
@@ -54,7 +56,7 @@ class MongoEngine(AbstractEngineClass):
if self.input.e and self.input.e.ot:
res = await tmp.to_list(None)
self.input.e.d = self.generate_output(res)
self.input.e.d = await self.generate_output(res)
return {'query': _f, 'sort': self.set_sort(), 'path': self.input.e.d}
self.rows = tmp.limit(self.input.get_limit()).skip(self.input.skip())
@@ -257,11 +259,11 @@ class MongoEngine(AbstractEngineClass):
def set_joins(self):
pass
def generate_output(self, _f):
async def generate_output(self, _f):
print(self.input.e.ot)
if self.input.e.ot == OutPutType.EXEL:
file_name = str(uuid.uuid4().hex) + '.xlsx'
return self.output_generator(_f, file_name=file_name, cols=self.input.e.c)
return await self.output_generator(_f, file_name=file_name, cols=self.input.e.c)
elif self.input.e.ot == OutPutType.JSON:
pass
elif self.input.e.ot == OutPutType.PDF:
@@ -275,7 +277,7 @@ class MongoEngine(AbstractEngineClass):
os.makedirs(temp_dir, exist_ok=True)
return temp_dir
def output_generator(self,query, file_name, cols):
async def output_generator(self, query, file_name, cols):
datas = query
file_dir = os.path.join(self._excel_temp_dir(), file_name)
head_cols = list(str(string.ascii_uppercase))
@@ -293,10 +295,15 @@ class MongoEngine(AbstractEngineClass):
# ساختن value_maps از vk (نام مپ) با استفاده از رجیستری
value_maps = self._build_value_maps()
# بارگذاری const ها برای فیلدهای خاص
const_maps = await self._load_const_maps(headers)
for row_index, item in enumerate(datas, start=1):
for col_index, col in enumerate(headers):
val = self.get_nested_value(item, col)
val = self._apply_value_map(col, val, value_maps)
val = await self._apply_const_map(col, val, const_maps)
worksheet.write(row_index, col_index, val)
workbook.close()
return file_name
@@ -328,6 +335,58 @@ class MongoEngine(AbstractEngineClass):
return mapping[str(key)]
return val
async def _load_const_maps(self, headers: List[str]) -> dict:
"""
شناسایی فیلدهای خاص (مثلاً nature_id, type_id, budget_id) و بارگذاری const ها از MySQL.
Returns: dict به صورت {col_key: {id: title_fa}} مثلاً {"design.nature_id": {2: "طبیعت 2", ...}}
"""
# لیست فیلدهای خاص که باید از const خوانده شوند
const_field_names = ['nature_id', 'type_id', 'budget_id'] # می‌تونی اضافه کنی
const_maps = {}
const_keys_to_load = set()
const_column_map = {} # {col_key: const_key} مثلاً {"design.nature_id": "nature"}
# شناسایی ستون‌هایی که باید const بخونن
for col_key in headers:
col_name = col_key.split('.')[-1] # آخرین بخش (nature_id)
if col_name in const_field_names:
const_key = col_name.replace('_id', '') # nature_id -> nature
const_keys_to_load.add(const_key)
const_column_map[col_key] = const_key
# بارگذاری const ها از MySQL
if const_keys_to_load:
repo = MySQLConstRepository()
for col_key, const_key in const_column_map.items():
consts_for_key = await repo.get_by_key(const_key)
if consts_for_key:
const_maps[col_key] = consts_for_key
return const_maps
async def _apply_const_map(self, col_key: str, val, const_maps: dict):
"""اگر این ستون در const_maps باشد، id را به title_fa تبدیل می‌کند."""
if not const_maps or col_key not in const_maps:
return val
mapping = const_maps[col_key]
if not isinstance(mapping, dict):
return val
if val is None:
return mapping.get(None, val)
# تبدیل val به int برای جستجو در mapping
key = val if isinstance(val, (int, float)) else (int(val) if isinstance(val, str) and str(val).strip().isdigit() else val)
if key in mapping:
return mapping[key]
if isinstance(key, int) and str(key) in mapping:
return mapping[str(key)]
return val
def get_nested_value(self, data, path, default='-'):
"""
دریافت مقدار از دیکشنری تو در تو با مسیر dot notation