进销存系统重构

This commit is contained in:
2026-03-17 22:20:56 +08:00
parent abecbc827d
commit 95e7404902
8 changed files with 1258 additions and 178 deletions
+128 -2
View File
@@ -7,7 +7,7 @@
路由前缀: /api/inventory
"""
from fastapi import APIRouter, Depends, Query
from fastapi import APIRouter, Depends, Query, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import Optional, List
@@ -15,7 +15,7 @@ from typing import Optional, List
from database.database import get_db_session
from services.auth_service import get_current_active_user
from models.database import User, Product, Warehouse, Inventory
from .schemas import InventoryResponse
from .schemas import InventoryResponse, InventoryCreate, InventoryUpdate
router = APIRouter(prefix="/inventory", tags=["库存管理"])
@@ -64,3 +64,129 @@ async def list_inventory(
))
return inventory_list
@router.post("", response_model=InventoryResponse, status_code=201)
async def create_inventory(
payload: InventoryCreate,
db_session: AsyncSession = Depends(get_db_session),
current_user: User = Depends(get_current_active_user)
):
if payload.quantity < 0 or payload.locked_quantity < 0:
raise HTTPException(status_code=400, detail="库存数量不能为负数")
if payload.locked_quantity > payload.quantity:
raise HTTPException(status_code=400, detail="锁定数量不能大于库存数量")
product_result = await db_session.execute(
select(Product).where(Product.id == payload.product_id, Product.is_active == True)
)
product = product_result.scalar_one_or_none()
if not product:
raise HTTPException(status_code=404, detail="物料不存在")
if product.item_type != "material":
raise HTTPException(status_code=400, detail="库存仅支持物料")
warehouse_result = await db_session.execute(
select(Warehouse).where(Warehouse.id == payload.warehouse_id, Warehouse.is_active == True)
)
warehouse = warehouse_result.scalar_one_or_none()
if not warehouse:
raise HTTPException(status_code=404, detail="仓库不存在")
exists_result = await db_session.execute(
select(Inventory).where(
Inventory.product_id == payload.product_id,
Inventory.warehouse_id == payload.warehouse_id
)
)
if exists_result.scalar_one_or_none():
raise HTTPException(status_code=400, detail="该仓库已存在该物料库存记录")
inventory = Inventory(
product_id=payload.product_id,
warehouse_id=payload.warehouse_id,
quantity=payload.quantity,
locked_quantity=payload.locked_quantity,
batch_number=payload.batch_number,
location=payload.location
)
db_session.add(inventory)
await db_session.commit()
await db_session.refresh(inventory)
return InventoryResponse(
id=inventory.id,
product_id=product.id,
product_name=product.name,
product_sku=product.sku,
warehouse_id=warehouse.id,
warehouse_name=warehouse.name,
quantity=inventory.quantity,
locked_quantity=inventory.locked_quantity,
available_quantity=inventory.available_quantity
)
@router.put("/{inventory_id}", response_model=InventoryResponse)
async def update_inventory(
inventory_id: int,
payload: InventoryUpdate,
db_session: AsyncSession = Depends(get_db_session),
current_user: User = Depends(get_current_active_user)
):
result = await db_session.execute(
select(Inventory, Product, Warehouse)
.join(Product, Inventory.product_id == Product.id)
.join(Warehouse, Inventory.warehouse_id == Warehouse.id)
.where(Inventory.id == inventory_id)
.where(Product.item_type == "material")
)
row = result.first()
if not row:
raise HTTPException(status_code=404, detail="库存记录不存在")
inventory, product, warehouse = row
if payload.quantity is not None:
if payload.quantity < 0:
raise HTTPException(status_code=400, detail="库存数量不能为负数")
inventory.quantity = payload.quantity
if payload.locked_quantity is not None:
if payload.locked_quantity < 0:
raise HTTPException(status_code=400, detail="锁定数量不能为负数")
inventory.locked_quantity = payload.locked_quantity
if inventory.locked_quantity > inventory.quantity:
raise HTTPException(status_code=400, detail="锁定数量不能大于库存数量")
if payload.batch_number is not None:
inventory.batch_number = payload.batch_number
if payload.location is not None:
inventory.location = payload.location
await db_session.commit()
await db_session.refresh(inventory)
return InventoryResponse(
id=inventory.id,
product_id=product.id,
product_name=product.name,
product_sku=product.sku,
warehouse_id=warehouse.id,
warehouse_name=warehouse.name,
quantity=inventory.quantity,
locked_quantity=inventory.locked_quantity,
available_quantity=inventory.available_quantity
)
@router.delete("/{inventory_id}")
async def delete_inventory(
inventory_id: int,
db_session: AsyncSession = Depends(get_db_session),
current_user: User = Depends(get_current_active_user)
):
result = await db_session.execute(select(Inventory).where(Inventory.id == inventory_id))
inventory = result.scalar_one_or_none()
if not inventory:
raise HTTPException(status_code=404, detail="库存记录不存在")
await db_session.delete(inventory)
await db_session.commit()
return {"message": "库存记录已删除"}