여러 줄 주석이 설명보다 경위(예전·실측·지적)를 적고 있어 읽는 사람이 결론을 찾기 어려웠다. - ts·tsx·js·mjs·css·py 478개: 여러 줄 주석은 첫 문장 한 줄로, 과거형·날짜 문장은 삭제 - 주석 위치는 TypeScript 파서·파이썬 tokenize/ast 로 찾는다 — 문자열 안의 # · /* 는 건드리지 않는다 - eslint·ts·noqa·type: ignore 같은 지시 주석은 그대로 둔다 파이썬 275개 정리 전후 AST 동일, TS 298개 주석 뺀 토큰 동일(빈 JSX 주석 10곳만 차이). site·frontend·admin tsc, site vitest 105 passed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
110 lines
4.6 KiB
Python
110 lines
4.6 KiB
Python
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 area_contents
|
|
from common.enums import ErrorType, LocalContentType, STORY_KINDS
|
|
from common.utils.gtime import GTime
|
|
|
|
|
|
class LocalContentCRUD:
|
|
async def list(self, db, status: int | None = None, region_code: str | None = None):
|
|
"""축제·관광지·맛집·날씨 전 종류."""
|
|
conds = [area_contents.deleted == False] # noqa: E712
|
|
if status is not None:
|
|
conds.append(area_contents.status == status)
|
|
if region_code:
|
|
conds.append(area_contents.region_code == region_code)
|
|
return await DB_SESSION_MNG.execute(
|
|
db, select(area_contents).where(and_(*conds)).order_by(area_contents.collected_at.desc())
|
|
)
|
|
|
|
async def insert(self, db, row):
|
|
return await DB_SESSION_MNG.insert(db, row)
|
|
|
|
async def publish(self, db, ids: list, user_id):
|
|
return await DB_SESSION_MNG.add_with_rowcount(
|
|
db,
|
|
update(area_contents).where(
|
|
area_contents.local_content_id.in_(ids), area_contents.deleted == False # noqa: E712
|
|
).values(status=2, published_at=GTime.UTC(), published_by=user_id, updated_at=GTime.UTC()),
|
|
)
|
|
|
|
async def update(self, db, content_id, data: dict):
|
|
return await DB_SESSION_MNG.add_with_rowcount(
|
|
db,
|
|
update(area_contents).where(
|
|
area_contents.local_content_id == content_id, area_contents.deleted == False # noqa: E712
|
|
).values(**data, updated_at=GTime.UTC()),
|
|
)
|
|
|
|
async def end(self, db, content_id):
|
|
return await self.update(db, content_id, {"status": 3})
|
|
|
|
async def upsert_kind(self, db, values: dict):
|
|
"""지역 이야기 한 종류(가요·인물·…)의 삽입/갱신."""
|
|
stmt = pg_insert(area_contents).values(**values)
|
|
stmt = stmt.on_conflict_do_update(
|
|
index_elements=[area_contents.region_code, area_contents.kind],
|
|
# 조건은 인덱스와 **글자 그대로** 같아야 한다.
|
|
index_where=and_(
|
|
area_contents.deleted == False, # noqa: E712
|
|
area_contents.kind.isnot(None),
|
|
area_contents.external_id.is_(None),
|
|
),
|
|
set_={
|
|
"title": stmt.excluded.title,
|
|
"body": stmt.excluded.body,
|
|
"content_type": stmt.excluded.content_type,
|
|
"source": stmt.excluded.source,
|
|
"status": stmt.excluded.status,
|
|
"collected_at": stmt.excluded.collected_at,
|
|
"published_at": stmt.excluded.published_at,
|
|
"updated_at": GTime.UTC(),
|
|
},
|
|
)
|
|
return await DB_SESSION_MNG.add(db, stmt)
|
|
|
|
async def list_kinds(self, db, region_code: str):
|
|
"""지역의 **이야기** 행(종류당 1행)."""
|
|
return await DB_SESSION_MNG.execute(
|
|
db,
|
|
select(area_contents).where(
|
|
area_contents.region_code == region_code,
|
|
area_contents.kind.in_(STORY_KINDS),
|
|
area_contents.deleted == False, # noqa: E712
|
|
),
|
|
)
|
|
|
|
async def get_weather(self, db, region_code: str):
|
|
err, rows = await DB_SESSION_MNG.execute(
|
|
db,
|
|
select(area_contents).where(
|
|
area_contents.region_code == region_code,
|
|
area_contents.content_type == LocalContentType.WEATHER.value,
|
|
area_contents.external_id.is_(None),
|
|
area_contents.deleted == False, # noqa: E712
|
|
).limit(1),
|
|
)
|
|
return err, rows[0] if rows else None
|
|
|
|
async def upsert_weather(self, db, values: dict):
|
|
stmt = pg_insert(area_contents).values(**values)
|
|
stmt = stmt.on_conflict_do_update(
|
|
index_elements=[area_contents.region_code, area_contents.content_type],
|
|
index_where=and_(
|
|
area_contents.deleted == False, # noqa: E712
|
|
area_contents.external_id.is_(None),
|
|
area_contents.kind.is_(None),
|
|
),
|
|
set_={
|
|
"source": stmt.excluded.source,
|
|
"body": stmt.excluded.body,
|
|
"status": stmt.excluded.status,
|
|
"collected_at": stmt.excluded.collected_at,
|
|
"expires_at": stmt.excluded.expires_at,
|
|
"updated_at": stmt.excluded.updated_at,
|
|
},
|
|
)
|
|
return await DB_SESSION_MNG.add(db, stmt)
|