""" Step 4 (optional): Verify exported files against manifests. Batch check across EVERY drawer that has a manifest: compares each drawer's manifest (captured during Step 2) against the files in the export directory and reports which drawers are complete vs missing documents. Matching is document-level and identical to fccs_check.py (via fccs_config.evaluate_drawer): it accounts for page-splitting (a document exported as 'Name Page 1', 'Name Page 2', ... counts as present) and for filename sanitization (titles with characters illegal in filenames still match). Use fccs_check.py to spot-check individual drawers interactively. """ import os import sys from fccs_config import ( parse_args, load_config, make_logger, evaluate_drawer, index_files_by_drawer, ) def main(): args = parse_args() cfg = load_config(args.config) log = make_logger(cfg.get("paths", "verify_report")) export_dir = cfg.get("paths", "export_dir") manifest_dir = cfg.get("paths", "manifest_dir") if not os.path.isdir(manifest_dir): log(f"ERROR: manifest directory not found: {manifest_dir}") log("Run fccs_export.py first to generate manifests.") sys.exit(1) if not os.path.isdir(export_dir): log(f"ERROR: export directory not found: {export_dir}") sys.exit(1) drawer_ids = sorted( os.path.splitext(f)[0] for f in os.listdir(manifest_dir) if f.endswith(".txt") ) if not drawer_ids: log("No manifest files found.") sys.exit(1) files_by_drawer = index_files_by_drawer(export_dir) log("=" * 60) log("Export Verification Report") log("=" * 60) log(f"Manifests loaded : {len(drawer_ids)} drawers") log("") complete_ids = [] incomplete = [] # (drawer_id, missing_list) for drawer_id in drawer_ids: r = evaluate_drawer(drawer_id, files_by_drawer.get(drawer_id, []), manifest_dir) n_expected = len(r["expected"]) missing = r["missing"] if not missing: complete_ids.append(drawer_id) log(f" {drawer_id}: OK ({n_expected} docs, {r['file_count']} files)") else: incomplete.append((drawer_id, missing)) log(f" {drawer_id}: INCOMPLETE — {len(missing)}/{n_expected} " f"document(s) missing:") for m in missing: log(f" - {m}") # Exported files whose drawer has no manifest at all. orphan_drawers = sorted(set(files_by_drawer) - set(drawer_ids)) orphan_count = sum(len(files_by_drawer[d]) for d in orphan_drawers) log("") log("-" * 60) log(f"Complete drawers : {len(complete_ids)}") log(f"Incomplete drawers : {len(incomplete)}") if incomplete: log(f" Incomplete IDs: {', '.join(d for d, _ in incomplete)}") if orphan_drawers: log(f"No manifest for : {', '.join(orphan_drawers)} " f"({orphan_count} files)") if not incomplete and not orphan_drawers: log("All drawers complete.") log("=" * 60) if __name__ == "__main__": main()