feat: align surgery API with schemas and extend client tooling
- Refactor app API and schemas; adjust surgery pipeline, repository, and session manager. - Improve consumption TSV logging and consumable vision integration; trim voice resolution. - Add Baidu Face 1:N search script, .env.example entries, and client API integration doc. - Update demo client, staging checklist, surgery interface doc, and related tests; add sample face image. Made-with: Cursor
This commit is contained in:
@@ -3,12 +3,14 @@ from __future__ import annotations
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
|
||||
|
||||
import app.db.models # noqa: F401
|
||||
from app.db.base import Base
|
||||
from app.db.models import SurgeryResultDetailRow
|
||||
from app.repositories.surgery_results import SurgeryResultRepository
|
||||
from app.schemas import SurgeryConsumptionDetail
|
||||
from app.schemas import SurgeryConsumptionStored
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -38,18 +40,18 @@ async def test_save_roundtrip(db_session: AsyncSession) -> None:
|
||||
repo = SurgeryResultRepository()
|
||||
ts = datetime(2026, 4, 21, 10, 0, tzinfo=timezone.utc)
|
||||
details = [
|
||||
SurgeryConsumptionDetail(
|
||||
SurgeryConsumptionStored(
|
||||
item_id="纱布",
|
||||
item_name="纱布",
|
||||
quantity=1,
|
||||
qty=1,
|
||||
doctor_id="D1",
|
||||
timestamp=ts,
|
||||
source="vision",
|
||||
),
|
||||
SurgeryConsumptionDetail(
|
||||
SurgeryConsumptionStored(
|
||||
item_id="纱布",
|
||||
item_name="纱布",
|
||||
quantity=1,
|
||||
qty=1,
|
||||
doctor_id="voice",
|
||||
timestamp=ts,
|
||||
source="voice",
|
||||
@@ -61,8 +63,17 @@ async def test_save_roundtrip(db_session: AsyncSession) -> None:
|
||||
loaded = await repo.load_final_details(db_session, "654321")
|
||||
assert loaded is not None
|
||||
assert len(loaded) == 2
|
||||
assert loaded[0].source == "vision"
|
||||
assert loaded[1].source == "voice"
|
||||
assert loaded[0].qty == 1 and loaded[0].item_id == "纱布"
|
||||
assert loaded[1].qty == 1
|
||||
async with db_session.begin():
|
||||
res = await db_session.execute(
|
||||
select(SurgeryResultDetailRow)
|
||||
.where(SurgeryResultDetailRow.surgery_id == "654321")
|
||||
.order_by(SurgeryResultDetailRow.id)
|
||||
)
|
||||
orm_rows = res.scalars().all()
|
||||
assert orm_rows[0].source == "vision"
|
||||
assert orm_rows[1].source == "voice"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -83,10 +94,10 @@ async def test_save_overwrites_previous_final_result(db_session: AsyncSession) -
|
||||
db_session,
|
||||
surgery_id="888888",
|
||||
details=[
|
||||
SurgeryConsumptionDetail(
|
||||
SurgeryConsumptionStored(
|
||||
item_id="旧",
|
||||
item_name="旧",
|
||||
quantity=1,
|
||||
qty=1,
|
||||
doctor_id="D1",
|
||||
timestamp=ts1,
|
||||
source="vision",
|
||||
@@ -98,10 +109,10 @@ async def test_save_overwrites_previous_final_result(db_session: AsyncSession) -
|
||||
db_session,
|
||||
surgery_id="888888",
|
||||
details=[
|
||||
SurgeryConsumptionDetail(
|
||||
SurgeryConsumptionStored(
|
||||
item_id="新",
|
||||
item_name="新",
|
||||
quantity=2,
|
||||
qty=2,
|
||||
doctor_id="D2",
|
||||
timestamp=ts2,
|
||||
source="voice",
|
||||
@@ -113,5 +124,4 @@ async def test_save_overwrites_previous_final_result(db_session: AsyncSession) -
|
||||
assert loaded is not None
|
||||
assert len(loaded) == 1
|
||||
assert loaded[0].item_id == "新"
|
||||
assert loaded[0].quantity == 2
|
||||
assert loaded[0].source == "voice"
|
||||
assert loaded[0].qty == 2
|
||||
|
||||
Reference in New Issue
Block a user