from collections.abc import Awaitable, Callable from typing import Any, Literal from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from common.vo import PageModel from module_business.dao.master_summary_dao import MasterSummaryDao from module_business.domain.test_batch_scope import TestBatchScope from module_business.entity.vo.master_summary_vo import ( CustomerDetailModel, CustomerListItemModel, LineListItemModel, MasterParentOptionModel, PalletDetailModel, PalletListItemModel, SiteListItemModel, StrainListItemModel, TunnelListItemModel, WarehouseListItemModel, ) from module_business.entity.vo.master_vo import CustomerModel, PalletModel SummaryResource = Literal['strain', 'customer', 'site', 'line', 'tunnel', 'warehouse', 'pallet'] _SummaryLoader = Callable[[AsyncSession, list[int], TestBatchScope], Awaitable[dict[int, dict[str, Any]]]] _ENRICHERS: dict[SummaryResource, tuple[str, _SummaryLoader, type[BaseModel]]] = { 'strain': ('strain_id', MasterSummaryDao.get_strain_summaries, StrainListItemModel), 'customer': ('customer_id', MasterSummaryDao.get_customer_summaries, CustomerListItemModel), 'site': ('site_id', MasterSummaryDao.get_site_summaries, SiteListItemModel), 'line': ('line_id', MasterSummaryDao.get_line_summaries, LineListItemModel), 'tunnel': ('tunnel_id', MasterSummaryDao.get_tunnel_summaries, TunnelListItemModel), 'warehouse': ('warehouse_id', MasterSummaryDao.get_warehouse_summaries, WarehouseListItemModel), 'pallet': ('pallet_id', MasterSummaryDao.get_pallet_summaries, PalletListItemModel), } class MasterSummaryService: """为基础资料页面补充只读汇总。导出与写入仍使用原主数据模型。""" @classmethod async def enrich_page( cls, db: AsyncSession, resource: SummaryResource, page: PageModel, scope: TestBatchScope, ) -> PageModel: id_field, loader, item_model = _ENRICHERS[resource] rows = list(page.rows) summaries = await loader(db, [getattr(row, id_field) for row in rows], scope) enriched = [ item_model.model_validate({**row.model_dump(), **summaries.get(getattr(row, id_field), {})}) for row in rows ] return page.model_copy(update={'rows': enriched}) @classmethod async def customer_detail( cls, db: AsyncSession, customer: CustomerModel, scope: TestBatchScope, ) -> CustomerDetailModel: sites = await MasterSummaryDao.get_customer_site_tree(db, customer.customer_id, scope) return CustomerDetailModel.model_validate({**customer.model_dump(), 'sites': sites}) @classmethod async def pallet_detail( cls, db: AsyncSession, pallet: PalletModel, scope: TestBatchScope, ) -> PalletDetailModel: summaries = await MasterSummaryDao.get_pallet_summaries(db, [pallet.pallet_id], scope) events = await MasterSummaryDao.get_pallet_recent_events(db, pallet.pallet_id, scope) return PalletDetailModel.model_validate( {**pallet.model_dump(), **summaries.get(pallet.pallet_id, {}), 'recent_events': events} ) @classmethod async def customer_options(cls, db: AsyncSession, scope: TestBatchScope) -> list[MasterParentOptionModel]: rows = await MasterSummaryDao.list_customer_options(db, scope) return [MasterParentOptionModel.model_validate(row) for row in rows] @classmethod async def site_options(cls, db: AsyncSession, scope: TestBatchScope) -> list[MasterParentOptionModel]: rows = await MasterSummaryDao.list_site_options(db, scope) return [MasterParentOptionModel.model_validate(row) for row in rows]