Files
FCCS/fccs_verify.py

96 lines
3.1 KiB
Python

"""
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()