提交
This commit is contained in:
1 parent
e6b4b9a8d7
commit
6272d107dc
29 files changed
+5840
-4504
No files matched your search
+119
-3
@@ -1,5 +1,6 @@
|
||||
"""市场物料库 API"""
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
@@ -7,6 +8,7 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.sample_reception import _get_current_user_id, _get_tenant_no, _page_payload
|
||||
from app.core.database import get_db
|
||||
from app.core.utils import parse_datetime
|
||||
from app.core.menu_guard import require_admin_or_super_admin, require_menu_code
|
||||
from app.core.response import error_response, success_response
|
||||
from app.crud import material as mat_svc
|
||||
@@ -48,6 +50,7 @@ class StockInBody(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
qty: float = Field(..., gt=0)
|
||||
remark: Optional[str] = None
|
||||
stock_in_time: Optional[str] = Field(None, alias="stockInTime")
|
||||
|
||||
|
||||
class StockOutBody(BaseModel):
|
||||
@@ -56,6 +59,37 @@ class StockOutBody(BaseModel):
|
||||
receiver: Optional[str] = None
|
||||
purpose: Optional[str] = None
|
||||
remark: Optional[str] = None
|
||||
stock_out_time: Optional[str] = Field(None, alias="stockOutTime")
|
||||
|
||||
|
||||
class BatchStockInItem(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
material_id: str = Field(..., alias="materialId")
|
||||
qty: float = Field(..., gt=0)
|
||||
remark: Optional[str] = None
|
||||
|
||||
|
||||
class BatchStockInBody(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
items: List[BatchStockInItem] = Field(..., min_length=1)
|
||||
remark: Optional[str] = None
|
||||
stock_in_time: Optional[str] = Field(None, alias="stockInTime")
|
||||
|
||||
|
||||
class BatchStockOutItem(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
material_id: str = Field(..., alias="materialId")
|
||||
qty: float = Field(..., gt=0)
|
||||
remark: Optional[str] = None
|
||||
|
||||
|
||||
class BatchStockOutBody(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
items: List[BatchStockOutItem] = Field(..., min_length=1)
|
||||
receiver: Optional[str] = None
|
||||
purpose: Optional[str] = None
|
||||
remark: Optional[str] = None
|
||||
stock_out_time: Optional[str] = Field(None, alias="stockOutTime")
|
||||
|
||||
|
||||
# ---------- 物料 CRUD ----------
|
||||
@@ -154,6 +188,76 @@ async def delete_material(
|
||||
return error_response(str(e))
|
||||
|
||||
|
||||
@router.post("/materials/batch-stock-in")
|
||||
async def batch_stock_in_material(
|
||||
body: BatchStockInBody,
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("biz:material:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
operate_time = datetime.now()
|
||||
if body.stock_in_time:
|
||||
rt = parse_datetime(body.stock_in_time)
|
||||
if not rt:
|
||||
return error_response("入库时间格式无效")
|
||||
operate_time = rt
|
||||
items = [
|
||||
{"material_id": x.material_id, "qty": x.qty, "remark": x.remark}
|
||||
for x in body.items
|
||||
]
|
||||
count = mat_svc.batch_stock_in(
|
||||
db,
|
||||
items=items,
|
||||
remark=body.remark,
|
||||
tenant_no=tenant_no,
|
||||
user_id=user_id,
|
||||
operate_time=operate_time,
|
||||
)
|
||||
return success_response({"count": count}, message=f"批量入库成功,共 {count} 项")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
|
||||
|
||||
@router.post("/materials/batch-stock-out")
|
||||
async def batch_stock_out_material(
|
||||
body: BatchStockOutBody,
|
||||
db: Session = Depends(get_db),
|
||||
user: dict = Depends(require_menu_code("biz:material:list")),
|
||||
):
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
operate_time = datetime.now()
|
||||
if body.stock_out_time:
|
||||
rt = parse_datetime(body.stock_out_time)
|
||||
if not rt:
|
||||
return error_response("出库时间格式无效")
|
||||
operate_time = rt
|
||||
items = [
|
||||
{"material_id": x.material_id, "qty": x.qty, "remark": x.remark}
|
||||
for x in body.items
|
||||
]
|
||||
count = mat_svc.batch_stock_out(
|
||||
db,
|
||||
items=items,
|
||||
receiver=body.receiver,
|
||||
purpose=body.purpose,
|
||||
remark=body.remark,
|
||||
tenant_no=tenant_no,
|
||||
user_id=user_id,
|
||||
operate_time=operate_time,
|
||||
)
|
||||
return success_response({"count": count}, message=f"批量出库成功,共 {count} 项")
|
||||
except ValueError as e:
|
||||
return error_response(str(e))
|
||||
except Exception as e:
|
||||
return error_response(str(e))
|
||||
|
||||
|
||||
@router.post("/materials/{material_id}/stock-in")
|
||||
async def stock_in_material(
|
||||
material_id: str,
|
||||
@@ -164,9 +268,15 @@ async def stock_in_material(
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
operate_time = datetime.now()
|
||||
if body.stock_in_time:
|
||||
rt = parse_datetime(body.stock_in_time)
|
||||
if not rt:
|
||||
return error_response("入库时间格式无效")
|
||||
operate_time = rt
|
||||
obj = mat_svc.stock_in(
|
||||
db, material_id, qty=body.qty, remark=body.remark,
|
||||
tenant_no=tenant_no, user_id=user_id,
|
||||
tenant_no=tenant_no, user_id=user_id, operate_time=operate_time,
|
||||
)
|
||||
return success_response(obj, message="入库成功")
|
||||
except ValueError as e:
|
||||
@@ -185,10 +295,16 @@ async def stock_out_material(
|
||||
try:
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
user_id = _get_current_user_id(user)
|
||||
operate_time = datetime.now()
|
||||
if body.stock_out_time:
|
||||
rt = parse_datetime(body.stock_out_time)
|
||||
if not rt:
|
||||
return error_response("出库时间格式无效")
|
||||
operate_time = rt
|
||||
obj = mat_svc.stock_out(
|
||||
db, material_id, qty=body.qty, receiver=body.receiver,
|
||||
purpose=body.purpose, remark=body.remark,
|
||||
tenant_no=tenant_no, user_id=user_id,
|
||||
tenant_no=tenant_no, user_id=user_id, operate_time=operate_time,
|
||||
)
|
||||
return success_response(obj, message="出库成功")
|
||||
except ValueError as e:
|
||||
|
||||
Reference in new issue
Block a user