96 lines
3.1 KiB
Python
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()
|