from sqlalchemy import and_, select, update from sqlalchemy.dialects.postgresql import insert as pg_insert from common.database.db_session_manager import DB_SESSION_MNG from common.database.model.models import place_contents from common.utils.gtime import GTime class PlaceContentCRUD: """업장 반경 주변정보(place_contents). 키는 place_id 다.""" async def list_by_place(self, db, place_id, *, include_hidden: bool = True): conds = [place_contents.place_id == place_id, place_contents.deleted == False] # noqa: E712 if not include_hidden: conds.append(place_contents.hidden == False) # noqa: E712 return await DB_SESSION_MNG.execute( db, select(place_contents).where(and_(*conds)) .order_by(place_contents.content_type.asc(), place_contents.has_image.desc(), place_contents.distance_m.asc()), ) async def upsert(self, db, values: dict): """(place_id, content_type, external_id) 로 삽입/갱신. ★ hidden 은 건드리지 않는다 — 운영자가 숨긴 것을 재수집이 되살리면 안 된다.""" stmt = pg_insert(place_contents).values(**values) stmt = stmt.on_conflict_do_update( index_elements=[place_contents.place_id, place_contents.content_type, place_contents.external_id], index_where=(place_contents.deleted == False), # noqa: E712 set_={ "title": stmt.excluded.title, "body": stmt.excluded.body, "distance_m": stmt.excluded.distance_m, "has_image": stmt.excluded.has_image, "display_end_at": stmt.excluded.display_end_at, "collected_at": stmt.excluded.collected_at, "updated_at": GTime.UTC(), }, ) return await DB_SESSION_MNG.add(db, stmt) async def soft_delete_missing(self, db, place_id, keep: set[tuple[int, str]]): """이번 응답에 없는 행을 소프트 삭제. keep = {(content_type, external_id)}.""" err, rows = await DB_SESSION_MNG.execute( db, select(place_contents.place_content_id, place_contents.content_type, place_contents.external_id) .where(place_contents.place_id == place_id, place_contents.deleted == False), # noqa: E712 ) gone = [r.place_content_id for r in (rows or []) if (int(r.content_type), r.external_id) not in keep] if not gone: return err, 0 return await DB_SESSION_MNG.add_with_rowcount( db, update(place_contents).where(place_contents.place_content_id.in_(gone)) .values(deleted=True, updated_at=GTime.UTC()), ) async def set_hidden(self, db, place_content_id, hidden: bool): return await DB_SESSION_MNG.add_with_rowcount( db, update(place_contents).where( place_contents.place_content_id == place_content_id, place_contents.deleted == False # noqa: E712 ).values(hidden=hidden, updated_at=GTime.UTC()), )