提交
This commit is contained in:
1 parent
e6b4b9a8d7
commit
6272d107dc
29 files changed
+5840
-4504
No files matched your search
@@ -6,6 +6,7 @@ from typing import Any, List, Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.database import get_db
|
||||
@@ -121,14 +122,31 @@ def _row_to_dict_project_price(row: BizInsuranceProjectPrice) -> dict:
|
||||
|
||||
|
||||
def _list_insurance_companies(
|
||||
db: Session, *, page: int, page_size: int, keyword: Optional[str], tenant_no: str, user_info=None
|
||||
db: Session,
|
||||
*,
|
||||
page: int,
|
||||
page_size: int,
|
||||
keyword: Optional[str],
|
||||
status: Optional[str],
|
||||
tenant_no: str,
|
||||
user_info=None,
|
||||
):
|
||||
q = db.query(BizInsuranceCompany).filter(
|
||||
BizInsuranceCompany.tenant_no == tenant_no,
|
||||
BizInsuranceCompany.del_flag == 0,
|
||||
)
|
||||
if keyword:
|
||||
q = q.filter(BizInsuranceCompany.company_name.like(f"%{keyword}%"))
|
||||
kw = (keyword or "").strip()
|
||||
if kw:
|
||||
like = f"%{kw}%"
|
||||
q = q.filter(
|
||||
or_(
|
||||
BizInsuranceCompany.company_name.like(like),
|
||||
BizInsuranceCompany.contact_name.like(like),
|
||||
)
|
||||
)
|
||||
st = (status or "").strip()
|
||||
if st in ("0", "1"):
|
||||
q = q.filter(BizInsuranceCompany.status == st)
|
||||
if user_info:
|
||||
from app.core.data_scope import apply_data_scope
|
||||
q = apply_data_scope(q, BizInsuranceCompany, user_info, db, tenant_no)
|
||||
@@ -532,12 +550,19 @@ async def list_insurance_companies(
|
||||
page: int = Query(1, ge=1),
|
||||
pageSize: int = Query(10, ge=1, le=100, alias="pageSize"),
|
||||
keyword: Optional[str] = None,
|
||||
status: Optional[str] = None,
|
||||
user: dict = Depends(require_admin_or_super_admin),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
tenant_no = _get_tenant_no(db, user)
|
||||
items, total = _list_insurance_companies(
|
||||
db, page=page, page_size=pageSize, keyword=keyword, tenant_no=tenant_no, user_info=user
|
||||
db,
|
||||
page=page,
|
||||
page_size=pageSize,
|
||||
keyword=keyword,
|
||||
status=status,
|
||||
tenant_no=tenant_no,
|
||||
user_info=user,
|
||||
)
|
||||
tp = _total_pages(total, pageSize)
|
||||
return success_response(
|
||||
|
||||
+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