from __future__ import annotations import argparse import json import sys from datetime import datetime from pathlib import Path from typing import Any sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import scripts.retry_failed_wehago_accounts_direct as direct import scripts.wehago_data_download_2022_work as wehago import scripts.wehago_ledger_api_download as api_download from runtime_config import DB_PATH from scripts.redownload_and_fix_hanmac_ledger_account import import_account_file ROOT = Path(__file__).resolve().parents[1] REPORT_DIR = ROOT / "reports" / "wehago_account_fixes" YEARS = (2018, 2019, 2020, 2021) GISU_BY_YEAR = {2018: 23, 2019: 24, 2020: 25, 2021: 26} ACCOUNTS = ( wehago.Account("114", "단기대여금"), wehago.Account("137", "주.종단기채권"), wehago.Account("179", "장기대여금"), wehago.Account("260", "단기차입금"), wehago.Account("290", "주.종단기차입금"), wehago.Account("901", "이자수익"), wehago.Account("931", "이자비용"), wehago.Account("116", "미수수익"), wehago.Account("136", "선납세금"), ) def parse_codes(raw: str) -> tuple[str, ...]: return tuple(part.strip() for part in raw.split(",") if part.strip()) def fetch_cookies(debugger_address: str, run_dir: Path) -> dict[str, str]: wehago.CHROME_DEBUGGER_ADDRESS = debugger_address wehago.DOWNLOAD_DIR = run_dir driver = wehago.build_driver(run_dir) try: return direct.cookie_map(driver) finally: driver.quit() def main() -> int: parser = argparse.ArgumentParser( description="한맥기술 2018~2021년 계열사 대여/차입 검토 계정별원장을 WEHAGO API로 내려받아 DB에 적재합니다." ) parser.add_argument("--years", default=",".join(str(year) for year in YEARS)) parser.add_argument("--accounts", default=",".join(account.code for account in ACCOUNTS)) parser.add_argument("--db", type=Path, default=DB_PATH) parser.add_argument("--debugger-address", default="127.0.0.1:9225") parser.add_argument("--output-dir", type=Path) parser.add_argument("--skip-import", action="store_true") args = parser.parse_args() selected_years = tuple(int(year) for year in parse_codes(args.years)) selected_codes = set(parse_codes(args.accounts)) accounts = tuple(account for account in ACCOUNTS if account.code in selected_codes) unknown_years = sorted(set(selected_years) - set(GISU_BY_YEAR)) if unknown_years: raise ValueError(f"지원하지 않는 연도입니다: {unknown_years}") if not accounts: raise ValueError("다운로드할 계정이 없습니다.") run_dir = args.output_dir or (REPORT_DIR / f"legacy_related_accounts_{datetime.now():%Y%m%d_%H%M%S}") run_dir.mkdir(parents=True, exist_ok=True) direct.DIRECT_GISU_BY_YEAR.update(GISU_BY_YEAR) cookies = fetch_cookies(args.debugger_address, run_dir) summary: dict[str, Any] = { "run_dir": str(run_dir), "years": list(selected_years), "accounts": [{"account_code": account.code, "account_name": account.name} for account in accounts], "downloaded": [], "failures": [], } for year in selected_years: year_dir = run_dir / str(year) year_dir.mkdir(parents=True, exist_ok=True) progress_accounts: list[dict[str, Any]] = [] progress_failures: list[dict[str, str]] = [] for account in accounts: item = {"year": year, "account_code": account.code, "account_name": account.name} try: rows = direct.fetch_ledger_rows(year, account, cookies) api_download.validate_api_rows(account, rows) target = year_dir / account.safe_filename api_download.write_api_rows(target, account, rows) item.update({"path": str(target), "api_response_rows": len(rows)}) progress_accounts.append( { "account_code": account.code, "account_name": account.name, "api_request_code": f"{account.code}00", "api_response_rows": len(rows), "path": str(target), } ) if not args.skip_import: result = import_account_file( args.db, target, year, account, year_dir, skip_rebuild=True, no_backup=True, skip_cache_clear=True, ) item.update( { "deleted_rows": result["deleted_rows"], "inserted_rows": result["inserted_rows"], } ) summary["downloaded"].append(item) print( f"OK {year} {account.code} {account.name}: rows={item.get('api_response_rows')} " f"inserted={item.get('inserted_rows', '-')}", flush=True, ) except Exception as exc: failure = { "year": str(year), "account_code": account.code, "account_name": account.name, "reason": f"{type(exc).__name__}: {exc}", } summary["failures"].append(failure) progress_failures.append(failure) print(f"FAIL {year} {account.code} {account.name}: {failure['reason']}", flush=True) api_download.write_progress( year_dir, { "status": "completed_with_failures" if progress_failures else "completed", "completed": len(progress_accounts), "total": len(accounts), "accounts": progress_accounts, "failures": progress_failures, }, ) (run_dir / "legacy_related_accounts_result.json").write_text( json.dumps(summary, ensure_ascii=False, indent=2), encoding="utf-8", ) print(json.dumps(summary, ensure_ascii=False, indent=2)) return 1 if summary["failures"] else 0 if __name__ == "__main__": raise SystemExit(main())