Files
ShiErFeng/shierfeng-fastapi-backend/module_business/service/report_service.py
T

213 lines
7.3 KiB
Python

from typing import Any, TypeVar
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from common.vo import PageModel
from exceptions.exception import ServiceException
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_business.dao.access_dao import AccessDao
from module_business.dao.report_dao import ReportDao
from module_business.domain.test_batch_scope import TestBatchScope
from module_business.entity.vo.report_vo import (
ConsumptionReportModel,
ConsumptionReportQueryModel,
FillingReportModel,
FillingReportQueryModel,
PalletInventoryReportModel,
PalletInventoryReportQueryModel,
PalletTraceReportModel,
PalletTraceReportQueryModel,
ReturnReportModel,
ReturnReportQueryModel,
ShipmentReportModel,
ShipmentReportQueryModel,
)
RowModelT = TypeVar('RowModelT', bound=BaseModel)
class ReportService:
"""六类只读业务报表服务。"""
@staticmethod
def _is_admin(current_user: CurrentUserModel) -> bool:
return bool(current_user.user and current_user.user.admin)
@classmethod
def _user_id(cls, current_user: CurrentUserModel) -> int:
if current_user.user is None or current_user.user.user_id is None:
raise ServiceException(message='当前用户信息无效')
return current_user.user.user_id
@classmethod
async def _warehouse_scope(
cls,
query_db: AsyncSession,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> list[int] | None:
if cls._is_admin(current_user):
return None
warehouse_ids = await AccessDao.list_user_warehouse_ids(query_db, cls._user_id(current_user), test_scope)
return sorted(set(warehouse_ids))
@classmethod
async def _site_scope(
cls,
query_db: AsyncSession,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> list[int] | None:
if cls._is_admin(current_user):
return None
site_ids = await AccessDao.list_user_site_ids(query_db, cls._user_id(current_user), test_scope)
return sorted(set(site_ids))
@classmethod
async def _scopes(
cls,
query_db: AsyncSession,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> tuple[list[int] | None, list[int] | None]:
if cls._is_admin(current_user):
return None, None
return (
await cls._warehouse_scope(query_db, current_user, test_scope),
await cls._site_scope(query_db, current_user, test_scope),
)
@staticmethod
def _empty_page(query_object: Any) -> PageModel:
return PageModel(
rows=[],
pageNum=query_object.page_num,
pageSize=query_object.page_size,
total=0,
hasNext=False,
)
@staticmethod
def _convert_page(page: PageModel, row_model: type[RowModelT]) -> PageModel[RowModelT]:
rows = [row_model.model_validate(row) for row in page.rows]
return page.model_copy(update={'rows': rows})
@classmethod
async def get_pallet_inventory_list_services(
cls,
query_db: AsyncSession,
query_object: PalletInventoryReportQueryModel,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> PageModel[PalletInventoryReportModel]:
warehouse_ids, site_ids = await cls._scopes(query_db, current_user, test_scope)
if warehouse_ids == [] and site_ids == []:
return cls._empty_page(query_object)
page = await ReportDao.get_pallet_inventory_list(
query_db,
query_object,
test_scope,
warehouse_ids=warehouse_ids,
site_ids=site_ids,
)
return cls._convert_page(page, PalletInventoryReportModel)
@classmethod
async def get_filling_report_list_services(
cls,
query_db: AsyncSession,
query_object: FillingReportQueryModel,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> PageModel[FillingReportModel]:
warehouse_ids = await cls._warehouse_scope(query_db, current_user, test_scope)
if warehouse_ids == []:
return cls._empty_page(query_object)
page = await ReportDao.get_filling_report_list(
query_db,
query_object,
test_scope,
warehouse_ids=warehouse_ids,
)
return cls._convert_page(page, FillingReportModel)
@classmethod
async def get_shipment_report_list_services(
cls,
query_db: AsyncSession,
query_object: ShipmentReportQueryModel,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> PageModel[ShipmentReportModel]:
warehouse_ids, site_ids = await cls._scopes(query_db, current_user, test_scope)
if warehouse_ids == [] or site_ids == []:
return cls._empty_page(query_object)
page = await ReportDao.get_shipment_report_list(
query_db,
query_object,
test_scope,
warehouse_ids=warehouse_ids,
site_ids=site_ids,
)
return cls._convert_page(page, ShipmentReportModel)
@classmethod
async def get_consumption_report_list_services(
cls,
query_db: AsyncSession,
query_object: ConsumptionReportQueryModel,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> PageModel[ConsumptionReportModel]:
site_ids = await cls._site_scope(query_db, current_user, test_scope)
if site_ids == []:
return cls._empty_page(query_object)
page = await ReportDao.get_consumption_report_list(
query_db,
query_object,
test_scope,
site_ids=site_ids,
)
return cls._convert_page(page, ConsumptionReportModel)
@classmethod
async def get_return_report_list_services(
cls,
query_db: AsyncSession,
query_object: ReturnReportQueryModel,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> PageModel[ReturnReportModel]:
warehouse_ids, site_ids = await cls._scopes(query_db, current_user, test_scope)
if warehouse_ids == [] and site_ids == []:
return cls._empty_page(query_object)
page = await ReportDao.get_return_report_list(
query_db,
query_object,
test_scope,
site_ids=site_ids,
warehouse_ids=warehouse_ids,
)
return cls._convert_page(page, ReturnReportModel)
@classmethod
async def get_pallet_trace_list_services(
cls,
query_db: AsyncSession,
query_object: PalletTraceReportQueryModel,
current_user: CurrentUserModel,
test_scope: TestBatchScope,
) -> PageModel[PalletTraceReportModel]:
warehouse_ids, site_ids = await cls._scopes(query_db, current_user, test_scope)
if warehouse_ids == [] and site_ids == []:
return cls._empty_page(query_object)
page = await ReportDao.get_pallet_trace_list(
query_db,
query_object,
test_scope,
warehouse_ids=warehouse_ids,
site_ids=site_ids,
)
return cls._convert_page(page, PalletTraceReportModel)