""" Utility: Check whether specific drawers actually finished exporting. Interactive — prompts for one or more drawer IDs, then for each drawer compares its manifest (the documents FCCS said it would export, captured during Step 2) against the files actually sitting in the export folder, and reports any missing documents. Handles two quirks of the FCCS export (see fccs_config.evaluate_drawer): 1. Page-splitting: a single manifest document (e.g. "Donations") is exported as one file if it's a single page, or as "Donations Page 1", "Donations Page 2", ... for a multi-page document. All of those count as that one document being present. 2. Filename sanitization: FCCS strips characters that are illegal in Windows filenames (: / \\ ? * " < > |) from document titles, so comparison is done on a normalized key so these still match. fccs_verify.py applies this same logic in batch across every drawer; this tool is for spot-checking specific drawers (e.g. ones the log marked failed). USAGE ----- python fccs_check.py Drawer ID(s): 08097 18430 """ import os import re import sys from fccs_config import ( parse_args, load_config, evaluate_drawer, index_files_by_drawer, ) def report_drawer(drawer_id, files, manifest_dir, out): """Evaluate one drawer and print a human-readable completeness report.""" r = evaluate_drawer(drawer_id, files, manifest_dir) out("") if not r["has_manifest"]: out(f"[{drawer_id}] NO MANIFEST at {r['manifest_path']} — cannot verify " "(was this drawer exported by the tool?)") return expected = r["expected"] missing = r["missing"] out(f"[{drawer_id}] manifest lists {len(expected)} document(s); " f"{r['file_count']} file(s) in export folder.") if missing: out(f" INCOMPLETE — {len(missing)} document(s) missing from export:") for m in missing: out(f" - {m}") else: out(f" COMPLETE — all {len(expected)} manifest document(s) present.") if r["extras"]: out(f" Note: {len(r['extras'])} exported document(s) not in the manifest:") for e in r["extras"]: out(f" - {e}") if r["unparsed"]: out(f" Note: {r['unparsed']} file(s) had no recognizable date anchor " "and were skipped.") def main(): args = parse_args() cfg = load_config(args.config) export_dir = cfg.get("paths", "export_dir") manifest_dir = cfg.get("paths", "manifest_dir") if not os.path.isdir(export_dir): print(f"ERROR: export directory not found: {export_dir}") sys.exit(1) files_by_drawer = index_files_by_drawer(export_dir) print("FCCS export completeness check") print(f" export folder : {export_dir}") print(f" manifests : {manifest_dir}") print("Enter drawer ID(s) separated by spaces or commas (blank to quit).") while True: try: raw = input("\nDrawer ID(s): ").strip() except EOFError: break if not raw: break ids = [i for i in re.split(r"[\s,]+", raw) if i] for drawer_id in ids: report_drawer(drawer_id, files_by_drawer.get(drawer_id, []), manifest_dir, print) if __name__ == "__main__": main()