feat(root):add mysql
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
"""
|
||||
مدل ORM برای جدول const در MySQL.
|
||||
"""
|
||||
from sqlalchemy import Column, Integer, String, Text
|
||||
from core.service.mysql_orm import Base
|
||||
|
||||
|
||||
class Const(Base):
|
||||
"""مدل جدول const"""
|
||||
__tablename__ = "const"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
key = Column(String(255), nullable=False, index=True)
|
||||
title_fa = Column(String(255), nullable=True)
|
||||
value = Column(Text, nullable=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Const(id={self.id}, key='{self.key}', title_fa='{self.title_fa}')>"
|
||||
|
||||
def to_dict(self):
|
||||
"""تبدیل به dict برای JSON response"""
|
||||
return {
|
||||
"id": self.id,
|
||||
"key": self.key,
|
||||
"title_fa": self.title_fa,
|
||||
"value": self.value,
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
"""
|
||||
Repository برای جدول const در MySQL - برای استفاده در خروجی اکسل.
|
||||
"""
|
||||
from typing import List, Dict, Optional
|
||||
from sqlalchemy import select
|
||||
from core.service.mysql_orm import get_mysql_session
|
||||
from app.models.mysql_const import Const
|
||||
|
||||
|
||||
class MySQLConstRepository:
|
||||
"""Repository برای خواندن دیتا از جدول const"""
|
||||
|
||||
async def get_by_keys(self, keys: List[str]) -> Dict[int, str]:
|
||||
"""
|
||||
گرفتن const ها با لیست key ها و برگرداندن dict به صورت {id: title_fa}
|
||||
مثال: get_by_keys(['nature', 'type']) -> {2: 'طبیعت 2', 9: 'نوع 9'}
|
||||
"""
|
||||
async with get_mysql_session() as session:
|
||||
result = await session.execute(
|
||||
select(Const).where(Const.key.in_(keys))
|
||||
)
|
||||
consts = result.scalars().all()
|
||||
return {c.id: c.title_fa or c.value or str(c.id) for c in consts}
|
||||
|
||||
async def get_by_key(self, key: str) -> Dict[int, str]:
|
||||
"""گرفتن const ها با یک key و برگرداندن dict به صورت {id: title_fa}"""
|
||||
return await self.get_by_keys([key])
|
||||
|
||||
async def get_all_consts_dict(self) -> Dict[int, str]:
|
||||
"""گرفتن همه const ها به صورت {id: title_fa} - برای کش کردن"""
|
||||
async with get_mysql_session() as session:
|
||||
result = await session.execute(select(Const))
|
||||
consts = result.scalars().all()
|
||||
return {c.id: c.title_fa or c.value or str(c.id) for c in consts}
|
||||
+2
-2
@@ -5,8 +5,8 @@ from core.service.mongo_db import use_collection
|
||||
|
||||
|
||||
def get_auth_db():
|
||||
return conf.server.is_prod and conf.database.get('mongo').production.db or conf.database.get(
|
||||
'mongo').dev.db
|
||||
return conf.server.is_prod and conf.database.get('mongo_auth').production.db or conf.database.get(
|
||||
'mongo_auth').dev.db
|
||||
|
||||
|
||||
def use_auth_collection(collection: str) -> Collection:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user