107 lines
2.8 KiB
Python
107 lines
2.8 KiB
Python
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
|