from sqlalchemy import select, delete, or_ from sqlalchemy.orm import Session, selectinload from models.patch import Patches, Crops, Records from schemas.patch import PatchCreate, PatchUpdate, PatchResponse, CropResponse def create_patch(db: Session, data: PatchCreate) -> bool: patch = Patches(**data.model_dump()) db.add(patch) db.commit() db.refresh(patch) return True def get_patches(db: Session, keyword: str | None = None) -> list[PatchResponse]: stmt = select(Patches) if keyword: like_pattern = f"%{keyword}%" stmt = stmt.where( or_( Patches.name.ilike(like_pattern), Patches.location.ilike(like_pattern), ) ) patches = db.execute(stmt).scalars().all() result = [] for p in patches: crop = db.execute( select(Crops).where(Crops.patch_id == p.id) ).scalar_one_or_none() data = PatchResponse.model_validate(p) if crop: latest_record = db.execute( select(Records) .where(Records.crop_id == crop.id) .order_by(Records.date.desc()) .limit(1) ).scalar_one_or_none() crop_data = CropResponse.from_orm(crop) crop_data.images = latest_record.images if latest_record else [] data.crop = crop_data else: data.crop = None result.append(data) return result def get_patch(db: Session, patch_id: int) -> PatchResponse | None: patch = db.execute( select(Patches).where(Patches.id == patch_id) ).scalar_one_or_none() if not patch: return None crop = db.execute( select(Crops).where(Crops.patch_id == patch_id) ).scalar_one_or_none() data = PatchResponse.model_validate(patch) data.crop = CropResponse.from_orm(crop) if crop else None return data def update_patch(db: Session, patch_id: int, data: PatchUpdate) -> bool: result = db.execute(select(Patches).where(Patches.id == patch_id)) patch = result.scalar_one_or_none() if not patch: return False for k, v in data.model_dump(exclude_unset=True).items(): setattr(patch, k, v) db.commit() db.refresh(patch) return True def delete_patch(db: Session, patch_id: int) -> bool: result = db.execute(select(Patches).where(Patches.id == patch_id)) patch = result.scalar_one_or_none() if not patch: return False # 先查作物 crop_result = db.execute(select(Crops).where(Crops.patch_id == patch_id)) crop = crop_result.scalar_one_or_none() # 有作物就先删记录,再删作物 if crop: db.execute(delete(Records).where(Records.crop_id == crop.id)) db.delete(crop) # 最后删菜地 db.delete(patch) db.commit() return True