Журнал перемещений, упрощение и чистка

This commit is contained in:
2025-12-13 23:47:46 +03:00
parent de572396a6
commit a9e57b4a38
20 changed files with 961 additions and 101 deletions
+65 -9
View File
@@ -1,3 +1,4 @@
from datetime import date, datetime, timedelta
from fastapi import APIRouter, Depends, Request from fastapi import APIRouter, Depends, Request
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
@@ -7,6 +8,7 @@ from .user import router as user
from .stocks import router as stocks from .stocks import router as stocks
from .toolbox import router as toolbox from .toolbox import router as toolbox
from .toolkit import router as toolkit from .toolkit import router as toolkit
from .records import router as records
router = APIRouter() router = APIRouter()
@@ -15,6 +17,7 @@ router.include_router(user, prefix="/user", tags=["user"])
router.include_router(stocks, prefix="/stocks", tags=["stocks"]) router.include_router(stocks, prefix="/stocks", tags=["stocks"])
router.include_router(toolbox, prefix="/toolbox", tags=["toolbox"]) router.include_router(toolbox, prefix="/toolbox", tags=["toolbox"])
router.include_router(toolkit, prefix="/toolkit", tags=["toolkit"]) router.include_router(toolkit, prefix="/toolkit", tags=["toolkit"])
router.include_router(records, prefix="/records", tags=["records"])
@router.get("/") @router.get("/")
@@ -50,9 +53,16 @@ async def post_requests(
reqData = { reqData = {
"tab": request_data.get("body").get("tabId"), "tab": request_data.get("body").get("tabId"),
"userData": request_data.get("body").get("cookiesData").get("userData"),
"accessData": request_data.get("body").get("cookiesData").get("accessData"),
} }
if "cookiesData" in request_data.get("body"):
if "userData" in request_data.get("body").get("cookiesData"):
reqData["userData"] = (
request_data.get("body").get("cookiesData").get("userData")
)
if "accessData" in request_data.get("body").get("cookiesData"):
reqData["accessData"] = (
request_data.get("body").get("cookiesData").get("accessData")
)
resultData = {"status": "error", "data": {}} resultData = {"status": "error", "data": {}}
logger.info(f"Получение данных для вкладки {reqData.get('tab')}") logger.info(f"Получение данных для вкладки {reqData.get('tab')}")
match reqData.get("tab"): match reqData.get("tab"):
@@ -67,10 +77,23 @@ async def post_requests(
resultData["status"] = "ok" resultData["status"] = "ok"
resultData["data"] = toolbox resultData["data"] = toolbox
case "requests": case "requests":
requests = await StocksRecordsHandler.get(reqData.get("userData").get("id")) canDesign = reqData.get("accessData").get(
"refund_request_confirm", False
) or reqData.get("accessData").get("debit_request_confirm", False)
userId = reqData.get("userData").get("id")
requests = await StocksRecordsHandler.get(userId, canDesign)
users = await UserHandler.getAll()
toolboxes = await ToolboxHandler.getAll()
toolkitsIds = set([request.get("toolkit_id") for request in requests])
toolkits = await ToolkitHandler.getSeveral(list(toolkitsIds))
if isinstance(requests, list): if isinstance(requests, list):
resultData["status"] = "ok" resultData["status"] = "ok"
resultData["data"] = requests resultData["data"] = {
"requests": requests,
"users": users,
"toolboxes": toolboxes,
"toolkits": toolkits,
}
case "toolkits": case "toolkits":
toolkits = await ToolkitHandler.getAll() toolkits = await ToolkitHandler.getAll()
categories = await CategoryHandler.getAll() categories = await CategoryHandler.getAll()
@@ -80,12 +103,45 @@ async def post_requests(
"toolkits": toolkits, "toolkits": toolkits,
"categories": categories, "categories": categories,
} }
# logger.info(resultData)
case "jurnal_toolkits": case "jurnal_toolkits":
jurnal_toolkits = await StocksRecordsHandler.get() startDate = request_data.get("body").get(
if jurnal_toolkits: "startDate", date.today() - timedelta(days=7)
resultData["status"] = "ok" )
resultData["data"] = jurnal_toolkits if isinstance(startDate, str):
startDate = datetime.strptime(startDate, "%Y-%m-%d").date()
endDate = request_data.get("body").get("endDate", date.today())
if isinstance(endDate, str):
endDate = datetime.strptime(endDate, "%Y-%m-%d").date()
jurnal_toolkits = await StocksRecordsHandler.getLogs(startDate, endDate)
if isinstance(jurnal_toolkits, list):
if len(jurnal_toolkits) == 0:
resultData["status"] = "ok"
resultData["data"] = {
"requests": [],
"users": [],
"toolboxes": [],
"toolkits": [],
"startDate": startDate.strftime("%Y-%m-%d"),
"endDate": endDate.strftime("%Y-%m-%d"),
}
else:
users = await UserHandler.getAll()
toolboxes = await ToolboxHandler.getAll()
toolkitsIds = set(
[request.get("toolkit_id") for request in jurnal_toolkits]
)
toolkits = await ToolkitHandler.getSeveral(list(toolkitsIds))
resultData["status"] = "ok"
resultData["data"] = {
"requests": jurnal_toolkits,
"users": users,
"toolboxes": toolboxes,
"toolkits": toolkits,
"startDate": startDate.strftime("%Y-%m-%d"),
"endDate": endDate.strftime("%Y-%m-%d"),
}
case "jurnal_service": case "jurnal_service":
jurnal_service = await ServiceRecordsHandler.get() jurnal_service = await ServiceRecordsHandler.get()
if jurnal_service: if jurnal_service:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+21
View File
@@ -0,0 +1,21 @@
from fastapi import APIRouter, Depends
from db.handlers.actions import StocksActions
from utils import requestDict, logger
router = APIRouter()
@router.post("/")
async def post_requests(
reqData: dict = Depends(requestDict),
):
logger.info("Получение записи о перемещении инструмента")
request_id = reqData.get("body").get("request_id")
user_id = reqData.get("body").get("user_id")
accepted = reqData.get("body").get("accepted")
if request_id and user_id and accepted is not None:
result = await StocksActions.movingDecision(int(request_id), user_id, accepted)
if result:
return {"status": "ok"}
return {"status": "error"}
+1 -1
View File
@@ -15,7 +15,7 @@ router = APIRouter()
async def post_requests( async def post_requests(
request_data: dict = Depends(requestDict), request_data: dict = Depends(requestDict),
): ):
toolboxId = request_data.get("body").get("toolboxId") toolboxId = int(request_data.get("body").get("toolboxId"))
logger.info(f"Получение инструментов для тулбокса {toolboxId}") logger.info(f"Получение инструментов для тулбокса {toolboxId}")
response = {"status": "error", "data": []} response = {"status": "error", "data": []}
-2
View File
@@ -54,7 +54,6 @@ async def delete_toolbox(reqDict=Depends(requestDict)):
@router.post("/fill", summary="Заполнение ящика") @router.post("/fill", summary="Заполнение ящика")
async def fill_toolbox(reqDict=Depends(requestDict)): async def fill_toolbox(reqDict=Depends(requestDict)):
logger.info(f"Заполнение ящика") logger.info(f"Заполнение ящика")
logger.info(reqDict.get("body"))
response = {"status": "error"} response = {"status": "error"}
toolboxId = reqDict.get("body").get("toolboxId") toolboxId = reqDict.get("body").get("toolboxId")
userId = reqDict.get("body").get("userId") userId = reqDict.get("body").get("userId")
@@ -79,5 +78,4 @@ async def fill_toolbox(reqDict=Depends(requestDict)):
response["message"] = ( response["message"] = (
f"Оприходовано {successCount} записей из {len(items)}. Проверьте остатки и повторите попытку" f"Оприходовано {successCount} записей из {len(items)}. Проверьте остатки и повторите попытку"
) )
logger.info(response)
return response return response
-1
View File
@@ -25,7 +25,6 @@ async def get_toolkit(reqData: dict = Depends(requestDict)):
if toolkitId: if toolkitId:
toolkit = await ToolkitHandler.get(int(toolkitId)) toolkit = await ToolkitHandler.get(int(toolkitId))
if toolkit: if toolkit:
# logger.info(toolkit)
response["status"] = "ok" response["status"] = "ok"
response["data"] = toolkit response["data"] = toolkit
return response return response
+817 -55
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -120,6 +120,9 @@ class ClientManager {
// Очищаем cookie пользователя // Очищаем cookie пользователя
this.clearUserCookie(); this.clearUserCookie();
// Очищаем локальное хранилище
localStorage.clear();
// Переход на страницу выхода // Переход на страницу выхода
setTimeout(() => { setTimeout(() => {
window.location.href = '/user/login'; window.location.href = '/user/login';
Binary file not shown.
Binary file not shown.
Binary file not shown.
-5
View File
@@ -90,21 +90,16 @@ class AccessLevelHandler:
"admin": { "admin": {
"title": "Администратор", "title": "Администратор",
"description": "Администратор. Полный доступ", "description": "Администратор. Полный доступ",
"receiving_edit": True,
"refund_request_edit": True,
"refund_request_confirm": True, "refund_request_confirm": True,
"debit_request_edit": True,
"debit_request_confirm": True, "debit_request_confirm": True,
"tools_creation": True, "tools_creation": True,
"tools_registration": True, "tools_registration": True,
"tools_registration_edit": True,
"tools_edit": True, "tools_edit": True,
"tools_delete": True, "tools_delete": True,
"users_creation": True, "users_creation": True,
"users_edit": True, "users_edit": True,
"users_disabling": True, "users_disabling": True,
"users_view": True, "users_view": True,
"available_own_toolbox": False,
"view_all_toolboxes": True, "view_all_toolboxes": True,
"view_requests": True, "view_requests": True,
"view_services": True, "view_services": True,
+2 -2
View File
@@ -270,7 +270,7 @@ class StocksActions:
if not accept: if not accept:
return accept return accept
totalRecordsIds = [record_id] totalRecordsIds = [record_id] if not record else [record.id]
if len(stocksMovements) > 1: if len(stocksMovements) > 1:
for stock in stocksMovements[1:]: for stock in stocksMovements[1:]:
@@ -298,7 +298,7 @@ class StocksActions:
) )
if not accept: if not accept:
return False return False
totalRecordsIds.append(recorded) totalRecordsIds.append(recorded.id)
logger.info( logger.info(
f"Записи {', '.join(map(str, totalRecordsIds))} о {movingRecord.action} инструмента успешно приняты {user_id}" f"Записи {', '.join(map(str, totalRecordsIds))} о {movingRecord.action} инструмента успешно приняты {user_id}"
+52 -22
View File
@@ -1,4 +1,4 @@
from datetime import datetime, timedelta from datetime import date, datetime, time, timedelta
from sqlalchemy import select from sqlalchemy import select
@@ -142,39 +142,69 @@ class StocksRecordsHandler:
logger.error(f"Ошибка обновления записи: {str(e)}") logger.error(f"Ошибка обновления записи: {str(e)}")
return False return False
async def get(user_id: int = None, days: int = 30): async def getLogs(startDate: date, endDate: date):
from db import CRUD from db import CRUD
try: try:
if user_id: start_dt = datetime.combine(startDate, time.min)
userInfo = f"пользователя {user_id} " end_dt = datetime.combine(endDate, time.max)
decided = "не решенных "
daysLimit = "" query = (
query = select(StocksRecords).where( select(StocksRecords)
StocksRecords.init_user_id == user_id, .where(
StocksRecords.decision_user_id == None, StocksRecords.created_at.between(start_dt, end_dt),
StocksRecords.decision_user_id != None,
)
.order_by(StocksRecords.created_at.desc())
)
logger.debug("Получение записей за период %s - %s", startDate, endDate)
records = await CRUD.read(query, True)
logger.debug(
"%d записей за период %s - %s успешно получены",
len(records),
startDate,
endDate,
)
return [record.toDict() for record in records]
except Exception:
logger.exception("Ошибка получения записей")
return []
async def get(user_id: int, manager: bool):
from db import CRUD
try:
if manager:
query = (
select(StocksRecords)
.where(
StocksRecords.decision_user_id == None,
)
.order_by(StocksRecords.created_at.asc())
) )
else: else:
userInfo = "всех пользователей " query = (
decided = "" select(StocksRecords)
daysLimit = f"за последние {days} дн." .where(
query = select(StocksRecords).where( StocksRecords.init_user_id == user_id,
StocksRecords.created_at > datetime.now() - timedelta(days=days), StocksRecords.decision_user_id == None,
)
.order_by(StocksRecords.created_at.asc())
) )
logger.debug(f"Получение всех {decided}записей {userInfo}{daysLimit}") logger.debug(f"Получение всех записей без решения")
records = await CRUD.read(query, True) records = await CRUD.read(query, True)
logger.debug( logger.debug(f"{len(records)} записей без решения успешно получены")
f"{len(records)} {decided}записей {userInfo}{daysLimit} успешно получены"
)
if len(records) == 0:
return []
records.sort(key=lambda x: x.created_at, reverse=True)
recordsData = [record.toDict() for record in records] recordsData = [record.toDict() for record in records]
logger.debug(recordsData) logger.debug(recordsData)
return recordsData return recordsData
except Exception as e: except Exception as e:
logger.error(f"Ошибка получения записей: {str(e)}") logger.error(f"Ошибка получения записей: {str(e)}")
return False return []
async def getById(record_id: int, record: bool = False): async def getById(record_id: int, record: bool = False):
from db import CRUD from db import CRUD
Binary file not shown.
-4
View File
@@ -14,14 +14,10 @@ class AccessLevel(Base):
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now) updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
# permissions # permissions
receiving_edit = Column(Boolean, default=False)
refund_request_edit = Column(Boolean, default=False)
refund_request_confirm = Column(Boolean, default=False) refund_request_confirm = Column(Boolean, default=False)
debit_request_edit = Column(Boolean, default=False)
debit_request_confirm = Column(Boolean, default=False) debit_request_confirm = Column(Boolean, default=False)
tools_creation = Column(Boolean, default=False) tools_creation = Column(Boolean, default=False)
tools_registration = Column(Boolean, default=False) tools_registration = Column(Boolean, default=False)
tools_registration_edit = Column(Boolean, default=False)
tools_edit = Column(Boolean, default=False) tools_edit = Column(Boolean, default=False)
tools_delete = Column(Boolean, default=False) tools_delete = Column(Boolean, default=False)
users_creation = Column(Boolean, default=False) users_creation = Column(Boolean, default=False)