feat: backup command — filter scan CSV by state and date range

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 15:57:36 +08:00
parent b135a49de5
commit cb7d9212e0
3 changed files with 132 additions and 0 deletions

44
src/order_bak/backup.py Normal file
View File

@@ -0,0 +1,44 @@
import csv
from collections import defaultdict
from datetime import datetime
from pathlib import Path
from order_bak.csv_utils import CSV_COLUMNS, _parse_row
def backup_orders(
scan_path: Path,
backup_dir: Path,
start: datetime,
end: datetime,
) -> int:
backup_dir.mkdir(parents=True, exist_ok=True)
by_date: dict[str, list[dict]] = defaultdict(list)
with open(scan_path, newline="") as f:
reader = csv.DictReader(f)
for raw_row in reader:
entity = _parse_row(raw_row)
if entity["state"] != 1:
continue
order_time = entity["OrderTime"]
if order_time is None:
continue
if order_time < start or order_time >= end:
continue
date_key = order_time.strftime("%Y-%m-%d")
by_date[date_key].append(raw_row)
total = 0
for date_key, rows in sorted(by_date.items()):
csv_path = backup_dir / f"{date_key}.csv"
with open(csv_path, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=CSV_COLUMNS)
writer.writeheader()
writer.writerows(rows)
total += len(rows)
print(f" {date_key}: {len(rows)} orders")
print(f"Backup complete: {total} orders across {len(by_date)} days")
return total

View File

@@ -1,3 +1,4 @@
from datetime import timezone
from pathlib import Path
import click
@@ -27,5 +28,34 @@ def scan(ctx):
)
@main.command()
@click.option("--start", required=True, type=click.DateTime(formats=["%Y-%m-%d"]), help="Start date (UTC, inclusive)")
@click.option("--end", required=True, type=click.DateTime(formats=["%Y-%m-%d"]), help="End date (UTC, exclusive)")
@click.option("--scan", "scan_path", default=None, type=click.Path(), help="Path to scan CSV (default: latest in scan_dir)")
@click.pass_context
def backup(ctx, start, end, scan_path):
cfg = load_config(ctx.obj["config_path"])
from order_bak.backup import backup_orders
if scan_path:
scan_file = Path(scan_path)
else:
scan_files = sorted(cfg.scan_dir.glob("scan-*.csv"))
if not scan_files:
click.echo("No scan files found in scan_dir")
raise SystemExit(1)
scan_file = scan_files[-1]
start_utc = start.replace(tzinfo=timezone.utc)
end_utc = end.replace(tzinfo=timezone.utc)
backup_orders(
scan_path=scan_file,
backup_dir=Path("./backups"),
start=start_utc,
end=end_utc,
)
if __name__ == "__main__":
main()