feat(scripts): backfill Customer.add_time from raw_json
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
"""Backfill Customer.add_time from raw_json.addTime (no re-scrape).
|
||||
|
||||
Iterates existing customer rows, parses raw_json.addTime (str or epoch) →
|
||||
add_time ms-epoch, updates in batches. Idempotent: skips rows where add_time
|
||||
is already set. WeChat rows have addTime; WhatsApp rows do not (createTime is
|
||||
owner-staff, not customer-add) — those stay NULL.
|
||||
"""
|
||||
import asyncio
|
||||
import time
|
||||
|
||||
from sqlalchemy import select, update
|
||||
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
|
||||
|
||||
from app.db import models # noqa: F401
|
||||
from app.db.models import Customer
|
||||
from app.scraper.wechat import _parse_add_time
|
||||
|
||||
BATCH = 200
|
||||
|
||||
|
||||
async def main(db_url: str = "sqlite+aiosqlite:///./smoke.db") -> None:
|
||||
engine = create_async_engine(db_url)
|
||||
sm = async_sessionmaker(engine, expire_on_commit=False)
|
||||
done = 0
|
||||
async with sm() as s:
|
||||
rows = (
|
||||
await s.execute(select(Customer.friend_id, Customer.raw_json, Customer.add_time))
|
||||
).all()
|
||||
for fid, raw, existing in rows:
|
||||
if existing or not raw:
|
||||
continue
|
||||
val = _parse_add_time(raw.get("addTime"))
|
||||
if val is None:
|
||||
continue
|
||||
await s.execute(
|
||||
update(Customer).where(Customer.friend_id == fid).values(add_time=val)
|
||||
)
|
||||
done += 1
|
||||
if done % BATCH == 0:
|
||||
await s.commit()
|
||||
print(f"[{time.strftime('%H:%M:%S')}] {done} updated...")
|
||||
await s.commit()
|
||||
print(f"DONE — {done} customers got add_time")
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user