- Add ProjectTransfer database model and migration - Implement project transfer service with immediate stock deduction on creation - Support 100% full delivery receipt logic across destination warehouses - Enforce canonical_specs_hash matching for cross-project stock merge - Add RBAC guards and status lock on received transfers (409 Conflict) - Register API router for transfers with on-the-way integration
75 lines
1.8 KiB
Python
75 lines
1.8 KiB
Python
from datetime import datetime
|
|
from decimal import Decimal
|
|
from uuid import UUID
|
|
|
|
from pydantic import Field
|
|
|
|
from app.schemas.common import APIModel
|
|
|
|
|
|
class WarehouseAllocationIn(APIModel):
|
|
warehouse_id: UUID
|
|
quantity: Decimal = Field(gt=0)
|
|
|
|
|
|
class ProjectTransferCreate(APIModel):
|
|
from_warehouse_id: UUID
|
|
to_project_id: UUID
|
|
material_id: UUID
|
|
brand_id: UUID | None = None
|
|
unit_id: int
|
|
quantity: Decimal = Field(gt=0)
|
|
specs: dict = Field(default_factory=dict)
|
|
note: str | None = None
|
|
transfer_date: datetime | None = None
|
|
|
|
|
|
class ProjectTransferUpdate(APIModel):
|
|
to_project_id: UUID | None = None
|
|
quantity: Decimal | None = Field(default=None, gt=0)
|
|
note: str | None = None
|
|
transfer_date: datetime | None = None
|
|
|
|
|
|
class ProjectTransferReceive(APIModel):
|
|
allocations: list[WarehouseAllocationIn] = Field(
|
|
min_length=1,
|
|
description="Warehouse allocations in destination project (sum must equal transfer quantity)",
|
|
)
|
|
received_at: datetime | None = None
|
|
note: str | None = None
|
|
|
|
|
|
class IdNameOut(APIModel):
|
|
id: UUID
|
|
name: str
|
|
|
|
|
|
class UnitBriefOut(APIModel):
|
|
id: int
|
|
code: str
|
|
name_fa: str | None = None
|
|
|
|
|
|
class ProjectTransferOut(APIModel):
|
|
id: UUID
|
|
from_project: IdNameOut
|
|
from_warehouse: IdNameOut
|
|
to_project: IdNameOut
|
|
to_warehouse: IdNameOut | None = None
|
|
material: IdNameOut
|
|
brand: IdNameOut | None = None
|
|
unit: UnitBriefOut
|
|
quantity: Decimal
|
|
specs: dict
|
|
specs_hash: str
|
|
note: str | None = None
|
|
status: str
|
|
transfer_date: datetime
|
|
transferred_by: str | None = None
|
|
received_at: datetime | None = None
|
|
received_by: str | None = None
|
|
receipt_allocations: list[dict] | None = None
|
|
created_at: datetime
|
|
updated_at: datetime
|