545 lines
19 KiB
Python
545 lines
19 KiB
Python
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel
|
|
from sqlalchemy import ColumnElement, Select, select, update
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy.orm.attributes import InstrumentedAttribute
|
|
|
|
from common.vo import PageModel
|
|
from module_admin.entity.do.user_do import SysUser
|
|
from module_business.domain.test_batch_scope import TestBatchScope, batch_scope_condition
|
|
from module_business.entity.do.master_do import (
|
|
BizCustomer,
|
|
BizCustomerSite,
|
|
BizPallet,
|
|
BizProductionLine,
|
|
BizStrain,
|
|
BizUserSite,
|
|
BizUserWarehouse,
|
|
BizWarehouse,
|
|
)
|
|
from module_business.entity.do.operation_do import BizPalletInventory
|
|
from module_business.entity.vo.master_vo import (
|
|
CustomerModel,
|
|
CustomerPageQueryModel,
|
|
LineModel,
|
|
LinePageQueryModel,
|
|
PalletEditModel,
|
|
PalletPageQueryModel,
|
|
SiteModel,
|
|
SitePageQueryModel,
|
|
StrainModel,
|
|
StrainPageQueryModel,
|
|
WarehouseModel,
|
|
WarehousePageQueryModel,
|
|
)
|
|
from utils.page_util import PageUtil
|
|
|
|
|
|
class MasterDao:
|
|
"""菌种、客户、现场、产线和仓库主数据数据库操作层。"""
|
|
|
|
@staticmethod
|
|
async def _paginate(
|
|
db: AsyncSession,
|
|
statement: Select,
|
|
query_object: BaseModel,
|
|
is_page: bool,
|
|
) -> PageModel | list[dict[str, Any]]:
|
|
return await PageUtil.paginate(
|
|
db,
|
|
statement,
|
|
query_object.page_num,
|
|
query_object.page_size,
|
|
is_page,
|
|
exclude_fields={'test_batch_id'},
|
|
)
|
|
|
|
@staticmethod
|
|
async def _get(
|
|
db: AsyncSession,
|
|
model: type[Any],
|
|
id_column: InstrumentedAttribute,
|
|
resource_id: int,
|
|
scope_predicate: ColumnElement[bool],
|
|
*,
|
|
for_update: bool = False,
|
|
) -> Any | None:
|
|
statement = select(model).where(id_column == resource_id, scope_predicate)
|
|
if for_update:
|
|
statement = statement.with_for_update().execution_options(populate_existing=True)
|
|
result = await db.execute(statement)
|
|
return result.scalar_one_or_none()
|
|
|
|
@staticmethod
|
|
async def _find(
|
|
db: AsyncSession,
|
|
model: type[Any],
|
|
code_column: InstrumentedAttribute,
|
|
code: str,
|
|
*scope_predicates: ColumnElement[bool],
|
|
) -> Any | None:
|
|
result = await db.execute(select(model).where(code_column == code, *scope_predicates))
|
|
return result.scalar_one_or_none()
|
|
|
|
@staticmethod
|
|
async def _add(
|
|
db: AsyncSession,
|
|
model: type[Any],
|
|
id_field: str,
|
|
page_object: BaseModel,
|
|
test_batch_id: int | None,
|
|
) -> Any:
|
|
payload = page_object.model_dump(exclude={id_field, 'can_remove', 'test_batch_id'})
|
|
payload['test_batch_id'] = test_batch_id
|
|
record = model(**payload)
|
|
db.add(record)
|
|
await db.flush()
|
|
return record
|
|
|
|
@staticmethod
|
|
async def _update(
|
|
db: AsyncSession,
|
|
model: type[Any],
|
|
id_column: InstrumentedAttribute,
|
|
id_field: str,
|
|
page_object: BaseModel,
|
|
scope: TestBatchScope,
|
|
) -> None:
|
|
payload = page_object.model_dump(
|
|
exclude_unset=True,
|
|
exclude={'can_remove', 'create_by', 'create_time', 'test_batch_id'},
|
|
)
|
|
resource_id = payload.pop(id_field)
|
|
await db.execute(
|
|
update(model)
|
|
.where(
|
|
id_column == resource_id,
|
|
batch_scope_condition(model.test_batch_id, scope),
|
|
)
|
|
.values(**payload)
|
|
)
|
|
|
|
@classmethod
|
|
async def list_strain(
|
|
cls,
|
|
db: AsyncSession,
|
|
query_object: StrainPageQueryModel,
|
|
scope: TestBatchScope,
|
|
is_page: bool = True,
|
|
) -> PageModel | list[dict[str, Any]]:
|
|
conditions = [batch_scope_condition(BizStrain.test_batch_id, scope)]
|
|
if query_object.strain_code:
|
|
conditions.append(BizStrain.strain_code.like(f'%{query_object.strain_code}%'))
|
|
if query_object.strain_name:
|
|
conditions.append(BizStrain.strain_name.like(f'%{query_object.strain_name}%'))
|
|
if query_object.status:
|
|
conditions.append(BizStrain.status == query_object.status)
|
|
statement = select(BizStrain).where(*conditions).order_by(BizStrain.strain_id)
|
|
return await cls._paginate(db, statement, query_object, is_page)
|
|
|
|
@classmethod
|
|
async def get_strain(
|
|
cls,
|
|
db: AsyncSession,
|
|
strain_id: int,
|
|
scope: TestBatchScope,
|
|
*,
|
|
for_update: bool = False,
|
|
) -> BizStrain | None:
|
|
return await cls._get(
|
|
db,
|
|
BizStrain,
|
|
BizStrain.strain_id,
|
|
strain_id,
|
|
batch_scope_condition(BizStrain.test_batch_id, scope),
|
|
for_update=for_update,
|
|
)
|
|
|
|
@classmethod
|
|
async def find_strain_by_code(cls, db: AsyncSession, strain_code: str) -> BizStrain | None:
|
|
return await cls._find(db, BizStrain, BizStrain.strain_code, strain_code)
|
|
|
|
@classmethod
|
|
async def add_strain(cls, db: AsyncSession, strain: StrainModel, test_batch_id: int | None) -> BizStrain:
|
|
return await cls._add(db, BizStrain, 'strain_id', strain, test_batch_id)
|
|
|
|
@classmethod
|
|
async def update_strain(cls, db: AsyncSession, strain: StrainModel, scope: TestBatchScope) -> None:
|
|
await cls._update(db, BizStrain, BizStrain.strain_id, 'strain_id', strain, scope)
|
|
|
|
@classmethod
|
|
async def list_customer(
|
|
cls,
|
|
db: AsyncSession,
|
|
query_object: CustomerPageQueryModel,
|
|
scope: TestBatchScope,
|
|
is_page: bool = True,
|
|
) -> PageModel | list[dict[str, Any]]:
|
|
conditions = [batch_scope_condition(BizCustomer.test_batch_id, scope)]
|
|
if query_object.customer_code:
|
|
conditions.append(BizCustomer.customer_code.like(f'%{query_object.customer_code}%'))
|
|
if query_object.customer_name:
|
|
conditions.append(BizCustomer.customer_name.like(f'%{query_object.customer_name}%'))
|
|
if query_object.status:
|
|
conditions.append(BizCustomer.status == query_object.status)
|
|
statement = select(BizCustomer).where(*conditions).order_by(BizCustomer.customer_id)
|
|
return await cls._paginate(db, statement, query_object, is_page)
|
|
|
|
@classmethod
|
|
async def get_customer(
|
|
cls,
|
|
db: AsyncSession,
|
|
customer_id: int,
|
|
scope: TestBatchScope,
|
|
*,
|
|
for_update: bool = False,
|
|
) -> BizCustomer | None:
|
|
return await cls._get(
|
|
db,
|
|
BizCustomer,
|
|
BizCustomer.customer_id,
|
|
customer_id,
|
|
batch_scope_condition(BizCustomer.test_batch_id, scope),
|
|
for_update=for_update,
|
|
)
|
|
|
|
@classmethod
|
|
async def find_customer_by_code(cls, db: AsyncSession, customer_code: str) -> BizCustomer | None:
|
|
return await cls._find(db, BizCustomer, BizCustomer.customer_code, customer_code)
|
|
|
|
@classmethod
|
|
async def add_customer(cls, db: AsyncSession, customer: CustomerModel, test_batch_id: int | None) -> BizCustomer:
|
|
return await cls._add(db, BizCustomer, 'customer_id', customer, test_batch_id)
|
|
|
|
@classmethod
|
|
async def update_customer(cls, db: AsyncSession, customer: CustomerModel, scope: TestBatchScope) -> None:
|
|
await cls._update(db, BizCustomer, BizCustomer.customer_id, 'customer_id', customer, scope)
|
|
|
|
@classmethod
|
|
async def list_site(
|
|
cls,
|
|
db: AsyncSession,
|
|
query_object: SitePageQueryModel,
|
|
scope: TestBatchScope,
|
|
is_page: bool = True,
|
|
) -> PageModel | list[dict[str, Any]]:
|
|
conditions = [batch_scope_condition(BizCustomerSite.test_batch_id, scope)]
|
|
if query_object.customer_id:
|
|
conditions.append(BizCustomerSite.customer_id == query_object.customer_id)
|
|
if query_object.site_code:
|
|
conditions.append(BizCustomerSite.site_code.like(f'%{query_object.site_code}%'))
|
|
if query_object.site_name:
|
|
conditions.append(BizCustomerSite.site_name.like(f'%{query_object.site_name}%'))
|
|
if query_object.status:
|
|
conditions.append(BizCustomerSite.status == query_object.status)
|
|
statement = select(BizCustomerSite).where(*conditions).order_by(BizCustomerSite.site_id)
|
|
return await cls._paginate(db, statement, query_object, is_page)
|
|
|
|
@classmethod
|
|
async def get_site(
|
|
cls,
|
|
db: AsyncSession,
|
|
site_id: int,
|
|
scope: TestBatchScope,
|
|
*,
|
|
for_update: bool = False,
|
|
) -> BizCustomerSite | None:
|
|
return await cls._get(
|
|
db,
|
|
BizCustomerSite,
|
|
BizCustomerSite.site_id,
|
|
site_id,
|
|
batch_scope_condition(BizCustomerSite.test_batch_id, scope),
|
|
for_update=for_update,
|
|
)
|
|
|
|
@classmethod
|
|
async def find_site_by_code(
|
|
cls,
|
|
db: AsyncSession,
|
|
site_code: str,
|
|
customer_id: int,
|
|
) -> BizCustomerSite | None:
|
|
return await cls._find(
|
|
db,
|
|
BizCustomerSite,
|
|
BizCustomerSite.site_code,
|
|
site_code,
|
|
BizCustomerSite.customer_id == customer_id,
|
|
)
|
|
|
|
@classmethod
|
|
async def add_site(cls, db: AsyncSession, site: SiteModel, test_batch_id: int | None) -> BizCustomerSite:
|
|
return await cls._add(db, BizCustomerSite, 'site_id', site, test_batch_id)
|
|
|
|
@classmethod
|
|
async def update_site(cls, db: AsyncSession, site: SiteModel, scope: TestBatchScope) -> None:
|
|
await cls._update(db, BizCustomerSite, BizCustomerSite.site_id, 'site_id', site, scope)
|
|
|
|
@classmethod
|
|
async def list_line(
|
|
cls,
|
|
db: AsyncSession,
|
|
query_object: LinePageQueryModel,
|
|
scope: TestBatchScope,
|
|
is_page: bool = True,
|
|
) -> PageModel | list[dict[str, Any]]:
|
|
conditions = [batch_scope_condition(BizProductionLine.test_batch_id, scope)]
|
|
if query_object.site_id:
|
|
conditions.append(BizProductionLine.site_id == query_object.site_id)
|
|
if query_object.line_code:
|
|
conditions.append(BizProductionLine.line_code.like(f'%{query_object.line_code}%'))
|
|
if query_object.line_name:
|
|
conditions.append(BizProductionLine.line_name.like(f'%{query_object.line_name}%'))
|
|
if query_object.status:
|
|
conditions.append(BizProductionLine.status == query_object.status)
|
|
statement = select(BizProductionLine).where(*conditions).order_by(BizProductionLine.line_id)
|
|
return await cls._paginate(db, statement, query_object, is_page)
|
|
|
|
@classmethod
|
|
async def get_line(
|
|
cls,
|
|
db: AsyncSession,
|
|
line_id: int,
|
|
scope: TestBatchScope,
|
|
*,
|
|
for_update: bool = False,
|
|
) -> BizProductionLine | None:
|
|
return await cls._get(
|
|
db,
|
|
BizProductionLine,
|
|
BizProductionLine.line_id,
|
|
line_id,
|
|
batch_scope_condition(BizProductionLine.test_batch_id, scope),
|
|
for_update=for_update,
|
|
)
|
|
|
|
@classmethod
|
|
async def find_line_by_code(
|
|
cls,
|
|
db: AsyncSession,
|
|
line_code: str,
|
|
site_id: int,
|
|
) -> BizProductionLine | None:
|
|
return await cls._find(
|
|
db,
|
|
BizProductionLine,
|
|
BizProductionLine.line_code,
|
|
line_code,
|
|
BizProductionLine.site_id == site_id,
|
|
)
|
|
|
|
@classmethod
|
|
async def add_line(cls, db: AsyncSession, line: LineModel, test_batch_id: int | None) -> BizProductionLine:
|
|
return await cls._add(db, BizProductionLine, 'line_id', line, test_batch_id)
|
|
|
|
@classmethod
|
|
async def update_line(cls, db: AsyncSession, line: LineModel, scope: TestBatchScope) -> None:
|
|
await cls._update(db, BizProductionLine, BizProductionLine.line_id, 'line_id', line, scope)
|
|
|
|
@classmethod
|
|
async def list_warehouse(
|
|
cls,
|
|
db: AsyncSession,
|
|
query_object: WarehousePageQueryModel,
|
|
scope: TestBatchScope,
|
|
is_page: bool = True,
|
|
) -> PageModel | list[dict[str, Any]]:
|
|
conditions = [batch_scope_condition(BizWarehouse.test_batch_id, scope)]
|
|
if query_object.warehouse_code:
|
|
conditions.append(BizWarehouse.warehouse_code.like(f'%{query_object.warehouse_code}%'))
|
|
if query_object.warehouse_name:
|
|
conditions.append(BizWarehouse.warehouse_name.like(f'%{query_object.warehouse_name}%'))
|
|
if query_object.status:
|
|
conditions.append(BizWarehouse.status == query_object.status)
|
|
statement = select(BizWarehouse).where(*conditions).order_by(BizWarehouse.warehouse_id)
|
|
return await cls._paginate(db, statement, query_object, is_page)
|
|
|
|
@classmethod
|
|
async def get_warehouse(
|
|
cls,
|
|
db: AsyncSession,
|
|
warehouse_id: int,
|
|
scope: TestBatchScope,
|
|
*,
|
|
for_update: bool = False,
|
|
) -> BizWarehouse | None:
|
|
return await cls._get(
|
|
db,
|
|
BizWarehouse,
|
|
BizWarehouse.warehouse_id,
|
|
warehouse_id,
|
|
batch_scope_condition(BizWarehouse.test_batch_id, scope),
|
|
for_update=for_update,
|
|
)
|
|
|
|
@classmethod
|
|
async def find_warehouse_by_code(cls, db: AsyncSession, warehouse_code: str) -> BizWarehouse | None:
|
|
return await cls._find(db, BizWarehouse, BizWarehouse.warehouse_code, warehouse_code)
|
|
|
|
@classmethod
|
|
async def add_warehouse(
|
|
cls, db: AsyncSession, warehouse: WarehouseModel, test_batch_id: int | None
|
|
) -> BizWarehouse:
|
|
return await cls._add(db, BizWarehouse, 'warehouse_id', warehouse, test_batch_id)
|
|
|
|
@classmethod
|
|
async def update_warehouse(cls, db: AsyncSession, warehouse: WarehouseModel, scope: TestBatchScope) -> None:
|
|
await cls._update(db, BizWarehouse, BizWarehouse.warehouse_id, 'warehouse_id', warehouse, scope)
|
|
|
|
@classmethod
|
|
async def list_pallet(
|
|
cls,
|
|
db: AsyncSession,
|
|
query_object: PalletPageQueryModel,
|
|
scope: TestBatchScope,
|
|
is_page: bool = True,
|
|
) -> PageModel | list[dict[str, Any]]:
|
|
conditions = [batch_scope_condition(BizPallet.test_batch_id, scope)]
|
|
if query_object.pallet_code:
|
|
conditions.append(BizPallet.pallet_code.like(f'%{query_object.pallet_code}%'))
|
|
if query_object.asset_status:
|
|
conditions.append(BizPallet.asset_status == query_object.asset_status)
|
|
statement = select(BizPallet).where(*conditions).order_by(BizPallet.pallet_id)
|
|
return await cls._paginate(db, statement, query_object, is_page)
|
|
|
|
@classmethod
|
|
async def get_pallet(
|
|
cls,
|
|
db: AsyncSession,
|
|
pallet_id: int,
|
|
scope: TestBatchScope,
|
|
*,
|
|
for_update: bool = False,
|
|
) -> BizPallet | None:
|
|
return await cls._get(
|
|
db,
|
|
BizPallet,
|
|
BizPallet.pallet_id,
|
|
pallet_id,
|
|
batch_scope_condition(BizPallet.test_batch_id, scope),
|
|
for_update=for_update,
|
|
)
|
|
|
|
@classmethod
|
|
async def find_pallet_by_code(cls, db: AsyncSession, pallet_code: str) -> BizPallet | None:
|
|
return await cls._find(db, BizPallet, BizPallet.pallet_code, pallet_code)
|
|
|
|
@classmethod
|
|
async def add_pallet(cls, db: AsyncSession, pallet: BizPallet) -> BizPallet:
|
|
db.add(pallet)
|
|
await db.flush()
|
|
return pallet
|
|
|
|
@classmethod
|
|
async def update_pallet(
|
|
cls,
|
|
db: AsyncSession,
|
|
pallet: PalletEditModel,
|
|
scope: TestBatchScope,
|
|
update_by: str,
|
|
update_time: datetime,
|
|
) -> None:
|
|
await db.execute(
|
|
update(BizPallet)
|
|
.where(
|
|
BizPallet.pallet_id == pallet.pallet_id,
|
|
batch_scope_condition(BizPallet.test_batch_id, scope),
|
|
)
|
|
.values(
|
|
capacity_packages=pallet.capacity_packages,
|
|
asset_status=pallet.asset_status,
|
|
remark=pallet.remark,
|
|
update_by=update_by,
|
|
update_time=update_time,
|
|
)
|
|
)
|
|
|
|
@classmethod
|
|
async def get_pallet_inventory(
|
|
cls,
|
|
db: AsyncSession,
|
|
pallet_id: int,
|
|
scope: TestBatchScope,
|
|
*,
|
|
for_update: bool = False,
|
|
) -> BizPalletInventory | None:
|
|
statement = select(BizPalletInventory).where(
|
|
BizPalletInventory.pallet_id == pallet_id,
|
|
batch_scope_condition(BizPalletInventory.test_batch_id, scope),
|
|
)
|
|
if for_update:
|
|
statement = statement.with_for_update().execution_options(populate_existing=True)
|
|
result = await db.execute(statement)
|
|
return result.scalar_one_or_none()
|
|
|
|
@classmethod
|
|
async def add_pallet_inventory(
|
|
cls,
|
|
db: AsyncSession,
|
|
inventory: BizPalletInventory,
|
|
) -> BizPalletInventory:
|
|
db.add(inventory)
|
|
await db.flush()
|
|
return inventory
|
|
|
|
@classmethod
|
|
async def list_assignable_users(cls, db: AsyncSession) -> list[Any]:
|
|
result = await db.execute(
|
|
select(SysUser.user_id, SysUser.user_name, SysUser.nick_name)
|
|
.where(SysUser.status == '0', SysUser.del_flag == '0')
|
|
.order_by(SysUser.user_id)
|
|
)
|
|
return list(result.all())
|
|
|
|
@classmethod
|
|
async def list_assignable_users_by_ids(cls, db: AsyncSession, user_ids: list[int]) -> list[Any]:
|
|
if not user_ids:
|
|
return []
|
|
result = await db.execute(
|
|
select(SysUser.user_id, SysUser.user_name, SysUser.nick_name)
|
|
.where(
|
|
SysUser.user_id.in_(user_ids),
|
|
SysUser.status == '0',
|
|
SysUser.del_flag == '0',
|
|
)
|
|
.order_by(SysUser.user_id)
|
|
)
|
|
return list(result.all())
|
|
|
|
@classmethod
|
|
async def list_warehouse_assigned_user_ids(
|
|
cls,
|
|
db: AsyncSession,
|
|
warehouse_id: int,
|
|
scope: TestBatchScope,
|
|
) -> list[int]:
|
|
result = await db.execute(
|
|
select(BizUserWarehouse.user_id)
|
|
.join(BizWarehouse, BizWarehouse.warehouse_id == BizUserWarehouse.warehouse_id)
|
|
.where(
|
|
BizUserWarehouse.warehouse_id == warehouse_id,
|
|
batch_scope_condition(BizWarehouse.test_batch_id, scope),
|
|
)
|
|
)
|
|
return list(result.scalars().all())
|
|
|
|
@classmethod
|
|
async def list_site_assigned_user_ids(
|
|
cls,
|
|
db: AsyncSession,
|
|
site_id: int,
|
|
scope: TestBatchScope,
|
|
) -> list[int]:
|
|
result = await db.execute(
|
|
select(BizUserSite.user_id)
|
|
.join(BizCustomerSite, BizCustomerSite.site_id == BizUserSite.site_id)
|
|
.where(
|
|
BizUserSite.site_id == site_id,
|
|
batch_scope_condition(BizCustomerSite.test_batch_id, scope),
|
|
)
|
|
)
|
|
return list(result.scalars().all())
|