o2o-site-AEO/solution/backend/scripts/verify_yanolja_test_place.py
Mina Choi 11d30bb3d1 [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제
여러 줄 주석이 설명보다 경위(예전·실측·지적)를 적고 있어 읽는 사람이 결론을 찾기 어려웠다.

- 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>
2026-09-28 16:05:19 +09:00

132 lines
5.2 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""테스트 place에 야놀자 크롤링으로 넣은 객실 fact/사진을 **수동으로 검수·승인**해서, 실제 미리보기 렌더러(site_payload.to_site_payload → UnitsSection)에 뜨는지 확인하는 1회성 스크립트."""
from __future__ import annotations
import argparse
import asyncio
import json
import os
import sys
import uuid
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ.setdefault("APP_ENV", "local")
from sqlalchemy import select # noqa: E402
from common.database.db_session_manager import DB_SESSION_MNG # noqa: E402
from common.database.model.models import places, place_facts, place_photos # noqa: E402
from common.enums import DBWRType, ErrorType, FactStatus, MediaStatus # noqa: E402
from common.models.gmodel import UserInfo # noqa: E402
from common.utils.gtime import GTime # noqa: E402
from crud.fact_crud import FactCRUD # noqa: E402
from crud.media_crud import MediaCRUD # noqa: E402
from crud.place_crud import PlaceCRUD # noqa: E402
from crud.site_crud import SiteCRUD # noqa: E402
from crud.job_crud import JobQueue # noqa: E402
from router.v1.fact.protocol import Req_TransitionFact # noqa: E402
from services.fact_service import FactService # noqa: E402
from services.site_service import SiteService # noqa: E402
# 검수 전 상태(우리가 이번에 넣은 값들)만 건드린다.
_PENDING_FACT_STATUSES = (FactStatus.UNVERIFIED.value, FactStatus.PENDING_OWNER.value)
async def _load_place(place_id: str):
stmt = select(places).where(places.place_id == uuid.UUID(place_id), places.deleted == False) # noqa: E712
err, row = await DB_SESSION_MNG.execute_lambda(
places.DBType(), DBWRType.DB_READ.value, lambda s: DB_SESSION_MNG.execute(s, stmt)
)
if err != ErrorType.SUCCESS or not row:
return None
return row[0]
async def _unit_scope_facts(place_id: str):
stmt = select(place_facts).where(
place_facts.place_id == uuid.UUID(place_id),
place_facts.deleted == False, # noqa: E712
place_facts.unit_id.is_not(None),
place_facts.status.in_(_PENDING_FACT_STATUSES),
)
err, rows = await DB_SESSION_MNG.execute_lambda(
place_facts.DBType(), DBWRType.DB_READ.value, lambda s: DB_SESSION_MNG.execute(s, stmt)
)
return rows if err == ErrorType.SUCCESS else []
async def _unit_scope_pending_photos(place_id: str):
stmt = select(place_photos).where(
place_photos.place_id == uuid.UUID(place_id),
place_photos.deleted == False, # noqa: E712
place_photos.unit_id.is_not(None),
place_photos.status == MediaStatus.PENDING_REVIEW.value,
)
err, rows = await DB_SESSION_MNG.execute_lambda(
place_photos.DBType(), DBWRType.DB_READ.value, lambda s: DB_SESSION_MNG.execute(s, stmt)
)
return rows if err == ErrorType.SUCCESS else []
async def run(place_id: str) -> None:
place = await _load_place(place_id)
if place is None:
raise SystemExit(f"place를 찾을 수 없습니다: {place_id}")
actor = UserInfo(user_id=str(place.owner_user_id), id="yanolja_test_verify", role=1)
fact_service = FactService(FactCRUD(), PlaceCRUD())
media_crud = MediaCRUD()
facts = await _unit_scope_facts(place_id)
print(f"[검수 대상 fact] {len(facts)}건")
verified = 0
for f in facts:
res = await fact_service.transition(
actor, place_id, str(f.fact_id), Req_TransitionFact(status=FactStatus.VERIFIED)
)
if res.result.success:
verified += 1
else:
print(f" ! {f.key}({f.fact_id}) 전이 실패: {res.result.desc}")
print(f" -> VERIFIED 처리 {verified}/{len(facts)}건")
photos = await _unit_scope_pending_photos(place_id)
print(f"[승인 대상 사진] {len(photos)}건")
approved = 0
now = GTime.UTC()
for p in photos:
alt_text = p.label or "객실 사진"
run_err, _rowcount = await DB_SESSION_MNG.execute_lambda_claim(
place_photos.DBType(),
lambda s, m=p.media_id, a=alt_text: media_crud.apply_vision(
s, m, p.label, a, None, MediaStatus.APPROVED.value, now
),
)
if run_err == ErrorType.SUCCESS:
approved += 1
print(f" -> APPROVED 처리 {approved}/{len(photos)}건 (alt_text 채움)")
site_service = SiteService(SiteCRUD(), PlaceCRUD(), JobQueue())
payload = await site_service.preview_payload(actor, place_id)
units = (payload or {}).get("units", [])
print(f"\n[/preview 재확인] units {len(units)}개")
for u in units:
print(f" - {u.get('name')}: fact {len(u.get('facts', []))}개, media {len(u.get('mediaIds', []))}장")
if not units:
print(" (여전히 비어 있습니다 — payload 구조나 상태값을 다시 확인하세요)")
print(json.dumps(payload, ensure_ascii=False, default=str)[:2000])
await DB_SESSION_MNG.dispose_all()
def main() -> None:
parser = argparse.ArgumentParser(description="테스트 place의 야놀자 객실 데이터를 검수·승인해서 미리보기에 반영")
parser.add_argument("--place-id", required=True)
args = parser.parse_args()
asyncio.run(run(args.place_id))
if __name__ == "__main__":
main()