修复:收紧入库数据范围校验
This commit is contained in:
@@ -51,6 +51,15 @@ class OperationDao:
|
||||
conditions.append(column < end_at)
|
||||
return conditions
|
||||
|
||||
@staticmethod
|
||||
def _inbound_scope_conditions(
|
||||
warehouse_ids: list[int] | None,
|
||||
) -> list[ColumnElement[bool]]:
|
||||
if warehouse_ids is None:
|
||||
return []
|
||||
scoped_warehouse_ids = sorted(set(warehouse_ids))
|
||||
return [BizInboundOrder.warehouse_id.in_(scoped_warehouse_ids) if scoped_warehouse_ids else false()]
|
||||
|
||||
@staticmethod
|
||||
async def _paginate(
|
||||
db: AsyncSession,
|
||||
@@ -98,8 +107,9 @@ class OperationDao:
|
||||
model: type[Any],
|
||||
id_column: InstrumentedAttribute,
|
||||
record_id: int,
|
||||
*extra_conditions: ColumnElement[bool],
|
||||
) -> Any | None:
|
||||
result = await db.execute(select(model).where(id_column == record_id))
|
||||
result = await db.execute(select(model).where(id_column == record_id, *extra_conditions))
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
@classmethod
|
||||
@@ -112,8 +122,15 @@ class OperationDao:
|
||||
item_model: type[Any],
|
||||
item_order_id_column: InstrumentedAttribute,
|
||||
item_id_column: InstrumentedAttribute,
|
||||
*order_conditions: ColumnElement[bool],
|
||||
) -> Any | None:
|
||||
order = await cls._get_by_id(db, order_model, order_id_column, order_id)
|
||||
order = await cls._get_by_id(
|
||||
db,
|
||||
order_model,
|
||||
order_id_column,
|
||||
order_id,
|
||||
*order_conditions,
|
||||
)
|
||||
if order is None:
|
||||
return None
|
||||
|
||||
@@ -185,12 +202,14 @@ class OperationDao:
|
||||
cls,
|
||||
db: AsyncSession,
|
||||
inbound_id: int,
|
||||
warehouse_ids: list[int] | None = None,
|
||||
) -> BizInboundOrder | None:
|
||||
inbound = await cls._get_for_update(
|
||||
db,
|
||||
BizInboundOrder,
|
||||
BizInboundOrder.inbound_id,
|
||||
inbound_id,
|
||||
*cls._inbound_scope_conditions(warehouse_ids),
|
||||
)
|
||||
if inbound is None:
|
||||
return None
|
||||
@@ -336,12 +355,7 @@ class OperationDao:
|
||||
is_page: bool = True,
|
||||
warehouse_ids: list[int] | None = None,
|
||||
) -> PageModel | list[dict[str, Any]]:
|
||||
conditions = []
|
||||
if warehouse_ids is not None:
|
||||
scoped_warehouse_ids = sorted(set(warehouse_ids))
|
||||
conditions.append(
|
||||
BizInboundOrder.warehouse_id.in_(scoped_warehouse_ids) if scoped_warehouse_ids else false()
|
||||
)
|
||||
conditions = cls._inbound_scope_conditions(warehouse_ids)
|
||||
if query_object.inbound_no:
|
||||
conditions.append(BizInboundOrder.inbound_no.like(f'%{query_object.inbound_no}%'))
|
||||
if query_object.warehouse_id:
|
||||
@@ -363,6 +377,7 @@ class OperationDao:
|
||||
cls,
|
||||
db: AsyncSession,
|
||||
inbound_id: int,
|
||||
warehouse_ids: list[int] | None = None,
|
||||
) -> BizInboundOrder | None:
|
||||
return await cls._get_order_detail(
|
||||
db,
|
||||
@@ -372,6 +387,7 @@ class OperationDao:
|
||||
BizInboundItem,
|
||||
BizInboundItem.inbound_id,
|
||||
BizInboundItem.inbound_item_id,
|
||||
*cls._inbound_scope_conditions(warehouse_ids),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -2,7 +2,7 @@ import hashlib
|
||||
import json
|
||||
import secrets
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from typing import Any, NoReturn
|
||||
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
@@ -81,18 +81,27 @@ class InboundService:
|
||||
user_id, _ = cls._current_identity(current_user)
|
||||
return sorted(set(await AccessDao.list_user_warehouse_ids(query_db, user_id)))
|
||||
|
||||
@classmethod
|
||||
def _raise_inbound_not_accessible(
|
||||
cls,
|
||||
current_user: CurrentUserModel,
|
||||
) -> NoReturn:
|
||||
if cls._is_admin(current_user):
|
||||
raise ServiceException(message='入库单不存在')
|
||||
raise PermissionException(data='', message='无权访问该入库单')
|
||||
|
||||
@staticmethod
|
||||
async def _validate_active_warehouse(
|
||||
query_db: AsyncSession,
|
||||
warehouse_id: int,
|
||||
current_user: CurrentUserModel,
|
||||
) -> Any:
|
||||
await AccessService.assert_warehouse_access(query_db, current_user, warehouse_id)
|
||||
warehouse = await MasterDao.get_warehouse(query_db, warehouse_id)
|
||||
if warehouse is None:
|
||||
raise ServiceException(message='目标仓库不存在')
|
||||
if warehouse.status != '0':
|
||||
raise ServiceException(message='目标仓库已停用')
|
||||
await AccessService.assert_warehouse_access(query_db, current_user, warehouse_id)
|
||||
return warehouse
|
||||
|
||||
@staticmethod
|
||||
@@ -188,10 +197,14 @@ class InboundService:
|
||||
inbound_id: int,
|
||||
current_user: CurrentUserModel,
|
||||
) -> InboundModel:
|
||||
inbound = await OperationDao.get_inbound_by_id(query_db, inbound_id)
|
||||
warehouse_ids = await cls._warehouse_scope(query_db, current_user)
|
||||
inbound = await OperationDao.get_inbound_by_id(
|
||||
query_db,
|
||||
inbound_id,
|
||||
warehouse_ids=warehouse_ids,
|
||||
)
|
||||
if inbound is None:
|
||||
raise ServiceException(message='入库单不存在')
|
||||
await AccessService.assert_warehouse_access(query_db, current_user, inbound.warehouse_id)
|
||||
cls._raise_inbound_not_accessible(current_user)
|
||||
return InboundModel.model_validate(inbound)
|
||||
|
||||
@classmethod
|
||||
@@ -318,14 +331,14 @@ class InboundService:
|
||||
) -> CrudResponseModel:
|
||||
try:
|
||||
_, user_name = cls._current_identity(current_user)
|
||||
inbound = await OperationDao.get_inbound_for_update(query_db, page_object.inbound_id)
|
||||
if inbound is None:
|
||||
raise ServiceException(message='入库单不存在')
|
||||
await AccessService.assert_warehouse_access(
|
||||
warehouse_ids = await cls._warehouse_scope(query_db, current_user)
|
||||
inbound = await OperationDao.get_inbound_for_update(
|
||||
query_db,
|
||||
current_user,
|
||||
inbound.warehouse_id,
|
||||
page_object.inbound_id,
|
||||
warehouse_ids=warehouse_ids,
|
||||
)
|
||||
if inbound is None:
|
||||
cls._raise_inbound_not_accessible(current_user)
|
||||
if inbound.status != DocumentStatus.DRAFT.value:
|
||||
raise ServiceException(message='已确认入库单不允许编辑')
|
||||
await cls._validate_active_warehouse(
|
||||
@@ -369,15 +382,15 @@ class InboundService:
|
||||
raise ServiceException(message='入库单ID不能重复')
|
||||
|
||||
ordered_ids = sorted(inbound_ids)
|
||||
warehouse_ids = await cls._warehouse_scope(query_db, current_user)
|
||||
for inbound_id in ordered_ids:
|
||||
inbound = await OperationDao.get_inbound_for_update(query_db, inbound_id)
|
||||
if inbound is None:
|
||||
raise ServiceException(message='入库单不存在')
|
||||
await AccessService.assert_warehouse_access(
|
||||
inbound = await OperationDao.get_inbound_for_update(
|
||||
query_db,
|
||||
current_user,
|
||||
inbound.warehouse_id,
|
||||
inbound_id,
|
||||
warehouse_ids=warehouse_ids,
|
||||
)
|
||||
if inbound is None:
|
||||
cls._raise_inbound_not_accessible(current_user)
|
||||
if inbound.status != DocumentStatus.DRAFT.value:
|
||||
raise ServiceException(message='已确认入库单不允许删除')
|
||||
|
||||
@@ -448,14 +461,14 @@ class InboundService:
|
||||
) -> CrudResponseModel:
|
||||
try:
|
||||
user_id, user_name = cls._current_identity(current_user)
|
||||
inbound = await OperationDao.get_inbound_by_id(query_db, inbound_id)
|
||||
if inbound is None:
|
||||
raise ServiceException(message='入库单不存在')
|
||||
await AccessService.assert_warehouse_access(
|
||||
warehouse_ids = await cls._warehouse_scope(query_db, current_user)
|
||||
inbound = await OperationDao.get_inbound_by_id(
|
||||
query_db,
|
||||
current_user,
|
||||
inbound.warehouse_id,
|
||||
inbound_id,
|
||||
warehouse_ids=warehouse_ids,
|
||||
)
|
||||
if inbound is None:
|
||||
cls._raise_inbound_not_accessible(current_user)
|
||||
|
||||
request_hash = cls._build_confirm_request_hash(inbound_id)
|
||||
idempotency_key = page_object.idempotency_key
|
||||
@@ -477,14 +490,13 @@ class InboundService:
|
||||
):
|
||||
raise ServiceException(message='确认入库失败,幂等键已被其他请求使用')
|
||||
|
||||
locked_inbound = await OperationDao.get_inbound_for_update(query_db, inbound_id)
|
||||
if locked_inbound is None:
|
||||
raise ServiceException(message='入库单不存在')
|
||||
await AccessService.assert_warehouse_access(
|
||||
locked_inbound = await OperationDao.get_inbound_for_update(
|
||||
query_db,
|
||||
current_user,
|
||||
locked_inbound.warehouse_id,
|
||||
inbound_id,
|
||||
warehouse_ids=warehouse_ids,
|
||||
)
|
||||
if locked_inbound is None:
|
||||
cls._raise_inbound_not_accessible(current_user)
|
||||
if locked_inbound.status == DocumentStatus.CONFIRMED.value:
|
||||
if cls._is_exact_confirmed(
|
||||
locked_inbound,
|
||||
|
||||
Reference in New Issue
Block a user