#!/usr/bin/env python3 """ 修正 MOMO 商品與促銷商品網址中的壞連結(如 javascript:void(0)、EC404、非商品頁) 將可修正者改為: 1) 以 i_code 組出正確商品網址 2) 無法修正時清空網址 (避免連到錯頁) """ import argparse import logging import os import sys BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, BASE_DIR) from database.manager import DatabaseManager from database.models import Product from database.edm_models import PromoProduct from utils.momo_url_utils import normalize_momo_product_url logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", ) logger = logging.getLogger(__name__) def _sanitize_records(records, label, commit=False): updated = 0 skipped = 0 cleared = 0 unchanged = 0 for record in records: old_url = getattr(record, "url", None) if not old_url: unchanged += 1 continue normalized = normalize_momo_product_url(old_url, getattr(record, "i_code", None)) if normalized == old_url: unchanged += 1 continue if normalized is None: if commit: record.url = None cleared += 1 logger.info( "清空 %s 不可修正 URL | id=%s | i_code=%s | old=%s", label, getattr(record, "id", "n/a"), getattr(record, "i_code", ""), old_url, ) else: if commit: record.url = normalized updated += 1 logger.info( "修正 %s URL | id=%s | i_code=%s | old=%s | new=%s", label, getattr(record, "id", "n/a"), getattr(record, "i_code", ""), old_url, normalized, ) logger.info( "%s 結果 | unchanged=%s, updated=%s, cleared=%s", label, unchanged, updated, cleared, ) return {"unchanged": unchanged, "updated": updated, "cleared": cleared} def main(commit=False): db = DatabaseManager() session = db.get_session() try: product_rows = session.query(Product).all() promo_rows = session.query(PromoProduct).all() product_result = _sanitize_records(product_rows, "products", commit=commit) promo_result = _sanitize_records(promo_rows, "promo_products", commit=commit) if commit: session.commit() logger.info("變更已提交") else: session.rollback() logger.info("Dry-run 模式:未提交變更") logger.info( "整體結果 | products: %s | promo_products: %s", product_result, promo_result, ) except Exception as exc: if commit: session.rollback() logger.exception("清理網址失敗: %s", exc) raise finally: session.close() if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--commit", action="store_true", help="實際寫回資料庫(不加此參數則為 dry-run)", ) args = parser.parse_args() main(commit=args.commit)