cargos.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from __future__ import annotations
  2. from fastapi import APIRouter, Depends, HTTPException, Query, status
  3. from sqlalchemy import func
  4. from sqlmodel import select
  5. from sqlmodel.ext.asyncio.session import AsyncSession
  6. from app.db.session import get_async_session
  7. from app.models.master_data import Cargo
  8. from app.schemas.master_data import CargoCreate, CargoRead, CargoUpdate
  9. router = APIRouter(prefix="/master-data/cargos", tags=["cargos"])
  10. def _base_query():
  11. return select(Cargo).where(Cargo.is_deleted == 0)
  12. @router.get("/", response_model=list[CargoRead])
  13. async def list_cargos(
  14. q: str | None = Query(default=None, description="模糊搜索货物名称"),
  15. session: AsyncSession = Depends(get_async_session),
  16. ) -> list[Cargo]:
  17. query = _base_query().order_by(Cargo.created_at.desc())
  18. if q:
  19. query = query.where(func.lower(Cargo.name).contains(q.lower()))
  20. result = await session.exec(query)
  21. return result.all()
  22. @router.post("/", response_model=CargoRead, status_code=status.HTTP_201_CREATED)
  23. async def create_cargo(
  24. payload: CargoCreate,
  25. session: AsyncSession = Depends(get_async_session),
  26. ) -> Cargo:
  27. from datetime import datetime
  28. await _ensure_unique_name(payload.name, session)
  29. cargo = Cargo(
  30. name=payload.name.strip(),
  31. remarks=payload.remarks,
  32. created_at=datetime.now().isoformat()
  33. )
  34. session.add(cargo)
  35. await session.commit()
  36. await session.refresh(cargo)
  37. return cargo
  38. @router.put("/{cargo_id}", response_model=CargoRead)
  39. async def update_cargo(
  40. cargo_id: int,
  41. payload: CargoUpdate,
  42. session: AsyncSession = Depends(get_async_session),
  43. ) -> Cargo:
  44. cargo = await _get_cargo(cargo_id, session)
  45. if payload.name and payload.name.strip().lower() != cargo.name.lower():
  46. await _ensure_unique_name(payload.name, session)
  47. cargo.name = payload.name.strip()
  48. if payload.remarks is not None:
  49. cargo.remarks = payload.remarks
  50. await session.commit()
  51. await session.refresh(cargo)
  52. return cargo
  53. @router.patch("/{cargo_id}", response_model=CargoRead)
  54. async def patch_cargo(
  55. cargo_id: int,
  56. payload: CargoUpdate,
  57. session: AsyncSession = Depends(get_async_session),
  58. ) -> Cargo:
  59. cargo = await _get_cargo(cargo_id, session)
  60. if payload.name and payload.name.strip().lower() != cargo.name.lower():
  61. await _ensure_unique_name(payload.name, session)
  62. cargo.name = payload.name.strip()
  63. if payload.remarks is not None:
  64. cargo.remarks = payload.remarks
  65. await session.commit()
  66. await session.refresh(cargo)
  67. return cargo
  68. @router.delete(
  69. "/{cargo_id}",
  70. status_code=status.HTTP_204_NO_CONTENT,
  71. )
  72. async def delete_cargo(
  73. cargo_id: int,
  74. session: AsyncSession = Depends(get_async_session),
  75. ) -> None:
  76. cargo = await _get_cargo(cargo_id, session)
  77. cargo.is_deleted = 1
  78. await session.commit()
  79. async def _get_cargo(cargo_id: int, session: AsyncSession) -> Cargo:
  80. result = await session.exec(_base_query().where(Cargo.id == cargo_id))
  81. cargo = result.one_or_none()
  82. if cargo is None:
  83. raise HTTPException(
  84. status_code=status.HTTP_404_NOT_FOUND,
  85. detail=f"Cargo {cargo_id} not found",
  86. )
  87. return cargo
  88. async def _ensure_unique_name(name: str, session: AsyncSession) -> None:
  89. normalized = name.strip().lower()
  90. result = await session.exec(
  91. _base_query().where(func.lower(Cargo.name) == normalized),
  92. )
  93. if result.first():
  94. raise HTTPException(
  95. status_code=status.HTTP_409_CONFLICT,
  96. detail="Cargo name already exists",
  97. )