import uuid from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from app.models.object import InventoryObject from app.schemas.object import BoxRef, ObjectCreate, ObjectRead, ObjectUpdate from app.services.photos import build_photo_read, delete_photo from app.services.qrcodes import object_public_url def build_object_read(obj: InventoryObject) -> ObjectRead: return ObjectRead( id=obj.id, inventory_number=obj.inventory_number, name=obj.name, description=obj.description, box_id=obj.box_id, box=BoxRef.model_validate(obj.box) if obj.box else None, created_at=obj.created_at, updated_at=obj.updated_at, qr_code_url=object_public_url(obj.id), photos=[build_photo_read(p) for p in obj.photos], ) def _select_with_relations(): return select(InventoryObject).options( selectinload(InventoryObject.photos), selectinload(InventoryObject.box) ) async def list_objects(db: AsyncSession, search: str | None = None) -> list[InventoryObject]: stmt = _select_with_relations().order_by(InventoryObject.created_at.desc()) if search: like = f"%{search}%" stmt = stmt.where( (InventoryObject.inventory_number.ilike(like)) | (InventoryObject.name.ilike(like)) ) result = await db.execute(stmt) return list(result.scalars().all()) async def get_object(db: AsyncSession, object_id: uuid.UUID) -> InventoryObject | None: stmt = _select_with_relations().where(InventoryObject.id == object_id) result = await db.execute(stmt) return result.scalar_one_or_none() async def create_object(db: AsyncSession, data: ObjectCreate) -> InventoryObject: obj = InventoryObject(**data.model_dump()) db.add(obj) await db.commit() return await get_object(db, obj.id) async def update_object(db: AsyncSession, obj: InventoryObject, data: ObjectUpdate) -> InventoryObject: for field, value in data.model_dump(exclude_unset=True).items(): setattr(obj, field, value) await db.commit() return await get_object(db, obj.id) async def delete_object(db: AsyncSession, minio_client, obj: InventoryObject) -> None: for photo in list(obj.photos): await delete_photo(db, minio_client, photo) await db.delete(obj) await db.commit()