оптимизация работы с БД

This commit is contained in:
2025-12-06 13:48:42 +03:00
parent f07843de5a
commit 54bf21d52d
8 changed files with 80 additions and 63 deletions
+17 -17
View File
@@ -22,47 +22,47 @@ class CRUD:
is_lst = isinstance(db_data, list) is_lst = isinstance(db_data, list)
async with SessionLocal() as db: async with SessionLocal() as db:
if is_lst: if is_lst:
logger.info(f"Создаю {len(db_data)} записей") logger.debug(f"Создаю {len(db_data)} записей")
try: try:
db.add_all(db_data) db.add_all(db_data)
except InvalidRequestError: except InvalidRequestError:
for data in db_data: for data in db_data:
await db.merge(data) await db.merge(data)
else: else:
logger.info("Создаю запись") logger.debug("Создаю запись")
db.add(db_data) db.add(db_data)
await db.commit() await db.commit()
if refresh: if refresh:
if is_lst: if is_lst:
logger.info(f"Обновляю {len(db_data)} записей") logger.debug(f"Обновляю {len(db_data)} записей")
for data in db_data: for data in db_data:
await db.refresh(data) await db.refresh(data)
else: else:
logger.info("Обновляю запись") logger.debug("Обновляю запись")
await db.refresh(db_data) await db.refresh(db_data)
logger.info("Запись создана") logger.debug("Запись создана")
return db_data if refresh else None return db_data if refresh else None
except Exception as e: except Exception as e:
logger.error(f"Ошибка создания: {str(e)}", exc_info=True) logger.error(f"Ошибка создания: {str(e)}", exc_debug=True)
return None return None
async def read(query, all: bool = False): async def read(query, all: bool = False):
try: try:
async with SessionLocal() as db: async with SessionLocal() as db:
logger.info(f"Чтение записей. Все: {all}") logger.debug(f"Чтение записей. Все: {all}")
results = await db.execute(query) results = await db.execute(query)
logger.info(f"Чтение завершено") logger.debug(f"Чтение завершено")
return ( return (
results.unique().scalars().all() results.unique().scalars().all()
if all if all
else results.unique().scalars().first() else results.unique().scalars().first()
) )
except Exception as e: except Exception as e:
logger.error(f"Ошибка чтения: {str(e)}", exc_info=True) logger.error(f"Ошибка чтения: {str(e)}", exc_debug=True)
return None return None
async def delete(db_data) -> bool: async def delete(db_data) -> bool:
def itemInfo(instance): def itemdebug(instance):
from sqlalchemy import inspect from sqlalchemy import inspect
state = inspect(instance) state = inspect(instance)
@@ -78,7 +78,7 @@ class CRUD:
return {"key": pKey, "value": pValue, "class": instance.__class__} return {"key": pKey, "value": pValue, "class": instance.__class__}
async def deleteFromDB(data, db): async def deleteFromDB(data, db):
itemData = itemInfo(data) itemData = itemdebug(data)
query = delete(itemData["class"]).where( query = delete(itemData["class"]).where(
getattr(itemData["class"], itemData["key"]) == itemData["value"] getattr(itemData["class"], itemData["key"]) == itemData["value"]
) )
@@ -87,18 +87,18 @@ class CRUD:
async with SessionLocal() as db: async with SessionLocal() as db:
try: try:
if isinstance(db_data, list): if isinstance(db_data, list):
logger.info(f"Удаляю записей: {len(db_data)}") logger.debug(f"Удаляю записей: {len(db_data)}")
for data in db_data: for data in db_data:
await deleteFromDB(data, db) await deleteFromDB(data, db)
else: else:
logger.info("Удаляю запись") logger.debug("Удаляю запись")
await deleteFromDB(db_data, db) await deleteFromDB(db_data, db)
await db.commit() await db.commit()
logger.info("Запись удалена") logger.debug("Запись удалена")
return True return True
except Exception as e: except Exception as e:
await db.rollback() await db.rollback()
logger.error(f"Ошибка удаления: {str(e)}", exc_info=True) logger.error(f"Ошибка удаления: {str(e)}", exc_debug=True)
return False return False
async def update(db_data, id, **kwargs): async def update(db_data, id, **kwargs):
@@ -107,9 +107,9 @@ class CRUD:
query = update(db_data).where(db_data.id == id).values(**kwargs) query = update(db_data).where(db_data.id == id).values(**kwargs)
item = await db.execute(query) item = await db.execute(query)
await db.commit() await db.commit()
logger.info("Запись обновлена") logger.debug("Запись обновлена")
return await db.get(db_data, id) return await db.get(db_data, id)
except Exception as e: except Exception as e:
await db.rollback() await db.rollback()
logger.error(f"Ошибка обновления: {str(e)}", exc_info=True) logger.error(f"Ошибка обновления: {str(e)}", exc_debug=True)
return None return None
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+58 -36
View File
@@ -6,6 +6,7 @@ from db.handlers.user import UserHandler
from db.handlers.access import AccessLevelHandler from db.handlers.access import AccessLevelHandler
from db.handlers.records import StocksRecordsHandler from db.handlers.records import StocksRecordsHandler
from db.schemas.records import StocksRecords
from utils import logger from utils import logger
@@ -47,7 +48,7 @@ class StocksActions:
reason=reason, reason=reason,
quantity=quantity, quantity=quantity,
price=price, price=price,
return_record_id=True, return_record=True,
) )
logger.info( logger.info(
f"Оприходование инструмента {toolkit_id} на складе {toolbox_id} прошло {'успешно' if recorded else 'не успешно'}" f"Оприходование инструмента {toolkit_id} на складе {toolbox_id} прошло {'успешно' if recorded else 'не успешно'}"
@@ -124,6 +125,9 @@ class StocksActions:
) )
if not target_toolbox_id: if not target_toolbox_id:
logger.warning(
f"Производится списание инструмента {toolkit_id} со склада {source_toolbox_id} в количестве {takeQuantity} по цене {stock['price']}"
)
continue continue
existing = await StockHandler.getByToolboxIdAndToolkitIdAndQPrice( existing = await StockHandler.getByToolboxIdAndToolkitIdAndQPrice(
@@ -165,23 +169,23 @@ class StocksActions:
f"Изменение остатков инструмента {toolkit_id} на склад {target_toolbox_id} по цене {stock['price']} успешно завершено" f"Изменение остатков инструмента {toolkit_id} на склад {target_toolbox_id} по цене {stock['price']} успешно завершено"
) )
recorded = await StocksRecordsHandler.add( # recorded = await StocksRecordsHandler.add(
action=action, # action=action,
source_stock_id=stock["id"], # source_stock_id=stock["id"],
target_stock_id=targetStock.get("id"), # target_stock_id=targetStock.get("id"),
source_toolbox_id=source_toolbox_id, # source_toolbox_id=source_toolbox_id,
target_toolbox_id=target_toolbox_id, # target_toolbox_id=target_toolbox_id,
toolkit_id=toolkit_id, # toolkit_id=toolkit_id,
init_user_id=user_id, # init_user_id=user_id,
reason=reason, # reason=reason,
quantity=quantity, # quantity=quantity,
price=stock["price"], # price=stock["price"],
) # )
if not recorded: # if not recorded:
logger.error( # logger.error(
f"Ошибка создания записи о {action} инструмента {toolkit_id} со склада {source_toolbox_id} на склад {target_toolbox_id}" # f"Ошибка создания записи о {action} инструмента {toolkit_id} со склада {source_toolbox_id} на склад {target_toolbox_id}"
) # )
return False # return False
logger.info( logger.info(
f"{action} инструмента {toolkit_id} со склада {source_toolbox_id} на склад {target_toolbox_id} прошло успешно" f"{action} инструмента {toolkit_id} со склада {source_toolbox_id} на склад {target_toolbox_id} прошло успешно"
@@ -197,7 +201,7 @@ class StocksActions:
reason: str, reason: str,
user_id: int, user_id: int,
price: int = 0, price: int = 0,
return_record_id: bool = False, return_record: bool = False,
): ):
logger.info( logger.info(
f"Запрос на {action} инструмента {toolkit_id} со склада {source_toolbox_id} в количестве {quantity} по цене {price} ..." f"Запрос на {action} инструмента {toolkit_id} со склада {source_toolbox_id} в количестве {quantity} по цене {price} ..."
@@ -213,18 +217,28 @@ class StocksActions:
reason=reason, reason=reason,
quantity=quantity, quantity=quantity,
price=price, price=price,
return_record_id=return_record_id, return_record=return_record,
) )
logger.info( logger.info(
f"Запрос на {action} инструмента {toolkit_id} со склада {source_toolbox_id} в количестве {quantity} по цене {price} {'успешно завершен' if recorded else 'завершен с ошибкой'}" f"Запрос на {action} инструмента {toolkit_id} со склада {source_toolbox_id} в количестве {quantity} по цене {price} {'успешно завершен' if recorded else 'завершен с ошибкой'}"
) )
return recorded return recorded
async def movingDecision(record_id: int, user_id: int, accepted: bool = True): async def movingDecision(
record_id: int,
user_id: int,
accepted: bool = True,
record: StocksRecords = None,
):
logger.info( logger.info(
f"{'Принятие' if accepted else 'Отклонение'} записи о движении инструмента {record_id} ..." f"{'Принятие' if accepted else 'Отклонение'} записи {record_id if not record else record.id} о движении инструмента {'' if not record else record.toolkit_id} ..."
) )
movingRecord = await StocksRecordsHandler.getById(record_id, True) movingRecord = (
await StocksRecordsHandler.getById(record_id, True)
if not record
else record
)
if not movingRecord: if not movingRecord:
logger.error(f"Запись {record_id} не найдена") logger.error(f"Запись {record_id} не найдена")
return False return False
@@ -235,7 +249,7 @@ class StocksActions:
return False return False
if not accepted: if not accepted:
return await StocksRecordsHandler.decide( return await StocksRecordsHandler.decide(
record_id, movingRecord,
user_id, user_id,
movingRecord.source_stock_id, movingRecord.source_stock_id,
movingRecord.quantity, movingRecord.quantity,
@@ -264,7 +278,7 @@ class StocksActions:
return False return False
accept = await StocksRecordsHandler.decide( accept = await StocksRecordsHandler.decide(
record_id, movingRecord,
user_id, user_id,
stocksMovements[0].get("id"), stocksMovements[0].get("id"),
stocksMovements[0].get("quantity"), stocksMovements[0].get("quantity"),
@@ -288,12 +302,12 @@ class StocksActions:
reason=movingRecord.reason, reason=movingRecord.reason,
quantity=stock.get("quantity"), quantity=stock.get("quantity"),
price=stock.get("price"), price=stock.get("price"),
return_record_id=True, return_record=True,
) )
if not recorded: if not recorded:
return False return False
accept = await StocksRecordsHandler.decide( accept = await StocksRecordsHandler.decide(
record_id=recorded, record=recorded,
decision_user_id=user_id, decision_user_id=user_id,
source_stock_id=stock.get("id"), source_stock_id=stock.get("id"),
quantity=stock.get("quantity"), quantity=stock.get("quantity"),
@@ -329,7 +343,7 @@ class StocksActions:
user_id=user_id, user_id=user_id,
reason=reason, reason=reason,
price=price, price=price,
return_record_id=True, return_record=True,
) )
if not takeRequest: if not takeRequest:
logger.error( logger.error(
@@ -340,16 +354,16 @@ class StocksActions:
f"Формирование запроса на получение инструмента {toolkit_id} успешно завершено" f"Формирование запроса на получение инструмента {toolkit_id} успешно завершено"
) )
logger.info( logger.info(
f"Принятие запроса {takeRequest} на получение инструмента {toolkit_id} ..." f"Принятие запроса {takeRequest.id} на получение инструмента {toolkit_id} ..."
) )
accepted = await StocksActions.movingDecision(takeRequest, user_id) accepted = await StocksActions.movingDecision(None, user_id, record=takeRequest)
if not accepted: if not accepted:
logger.error( logger.error(
f"Принятие запроса {takeRequest} на получение инструмента {toolkit_id} не удалось" f"Принятие запроса {takeRequest.id} на получение инструмента {toolkit_id} не удалось"
) )
return False return False
logger.info( logger.info(
f"Принятие запроса {takeRequest} на получение инструмента {toolkit_id} успешно завершено" f"Принятие запроса {takeRequest.id} на получение инструмента {toolkit_id} успешно завершено"
) )
return True return True
@@ -498,7 +512,7 @@ class StocksActions:
quantity=random.randint(3, 5), quantity=random.randint(3, 5),
reason=f"{action} инструмента {toolkit.get('title')}. После выполнения заказа", reason=f"{action} инструмента {toolkit.get('title')}. После выполнения заказа",
user_id=user.get("id"), user_id=user.get("id"),
return_record_id=True, return_record=True,
) )
if not success: if not success:
logger.error( logger.error(
@@ -522,6 +536,7 @@ class StocksActions:
"manager": {"accept": [], "reject": [], "ignore": []}, "manager": {"accept": [], "reject": [], "ignore": []},
"storekeeper": {"accept": [], "reject": [], "ignore": []}, "storekeeper": {"accept": [], "reject": [], "ignore": []},
} }
logger.info("Разбивка списоков запросов ...")
for recordsList in requestsDict.values(): for recordsList in requestsDict.values():
managerList, storekeeperList = ( managerList, storekeeperList = (
recordsList[: len(recordsList) // 2], recordsList[: len(recordsList) // 2],
@@ -550,9 +565,12 @@ class StocksActions:
storekeeperList[len(storekeeperList) // 3 * 2 :], storekeeperList[len(storekeeperList) // 3 * 2 :],
) )
logger.warning("Применение решений ...")
for role in decisionsDict.keys(): for role in decisionsDict.keys():
logger.warning(f"Принятие записей пользователем {role} ...")
user_id = usersDict.get(role) user_id = usersDict.get(role)
for decision in decisionsDict.get(role).keys(): for decision in decisionsDict.get(role).keys():
logger.warning(f"Принятие решения {decision} пользователем {role} ...")
match decision: match decision:
case "accept": case "accept":
accepted = True accepted = True
@@ -560,15 +578,19 @@ class StocksActions:
accepted = False accepted = False
case "ignore": case "ignore":
continue continue
for record_id in decisionsDict.get(role).get(decision): for record in decisionsDict.get(role).get(decision):
logger.info(
f"{'Принятие' if accepted else 'Отклонение'} записи {record.id} пользователем {role} ... "
)
success = await StocksActions.movingDecision( success = await StocksActions.movingDecision(
record_id=record_id, record_id=None,
user_id=user_id, user_id=user_id,
accepted=accepted, accepted=accepted,
record=record,
) )
if not success: if not success:
logger.error( logger.error(
f"Принятие записи {record_id} пользователем {role} не удалось" f"{'Принятие' if accepted else 'Отклонение'} записи {record.id} пользователем {role} не удалось"
) )
return False return False
+5 -9
View File
@@ -20,7 +20,7 @@ class StocksRecordsHandler:
price: float, price: float,
source_toolbox_id: int = None, source_toolbox_id: int = None,
target_toolbox_id: int = None, target_toolbox_id: int = None,
return_record_id: bool = False, return_record: bool = False,
): ):
recordData = { recordData = {
"action": action, "action": action,
@@ -40,13 +40,13 @@ class StocksRecordsHandler:
record = StocksRecords(**recordData) record = StocksRecords(**recordData)
await record.save() await record.save()
logger.info(f"Запись успешно создана, id: {record.id}") logger.info(f"Запись успешно создана, id: {record.id}")
return True if not return_record_id else record.id return True if not return_record else record
except Exception as e: except Exception as e:
logger.error(f"Ошибка создания записи: {str(e)}") logger.error(f"Ошибка создания записи: {str(e)}")
return False return False
async def decide( async def decide(
record_id: int, record: StocksRecords,
decision_user_id: int, decision_user_id: int,
source_stock_id: int, source_stock_id: int,
quantity: int, quantity: int,
@@ -55,12 +55,8 @@ class StocksRecordsHandler:
): ):
try: try:
logger.info( logger.info(
f"{'Принятие' if accept else 'Отклонение'} записи {record_id} от {decision_user_id}" f"{'Принятие' if accept else 'Отклонение'} записи {record.id} от {decision_user_id}"
) )
record = await StocksRecordsHandler.getById(record_id, record=True)
if not record:
logger.error(f"Запись {record_id} не найдена")
return False
record.decision_user_id = decision_user_id record.decision_user_id = decision_user_id
record.decided_at = datetime.now() record.decided_at = datetime.now()
record.source_stock_id = source_stock_id record.source_stock_id = source_stock_id
@@ -69,7 +65,7 @@ class StocksRecordsHandler:
record.accepted = accept record.accepted = accept
await record.save() await record.save()
logger.info( logger.info(
f"Запись {record_id} успешно {'принята' if accept else 'отклонена'} {decision_user_id} в {record.decided_at.strftime('%Y-%m-%d %H:%M:%S')}" f"Запись {record.id} успешно {'принята' if accept else 'отклонена'} {decision_user_id} в {record.decided_at.strftime('%Y-%m-%d %H:%M:%S')}"
) )
return True return True
except Exception as e: except Exception as e:
-1
View File
@@ -197,7 +197,6 @@ class UserHandler:
acessLevels = { acessLevels = {
accessLevel["title"]: accessLevel["id"] for accessLevel in accessLevelsList accessLevel["title"]: accessLevel["id"] for accessLevel in accessLevelsList
} }
logger.info(acessLevels)
password = "Alex0172" password = "Alex0172"
baseUsers = { baseUsers = {
"admin": { "admin": {