WFDASH-WEBAPP/scripts/verify_v5.py
SJCoetz 33591959c2 feat: add quote email intake and atomic numbering
This commit implements the full inbound quote email processing workflow and atomic quote numbering:
- Add PocketBase collections for monthly atomic quote counters, email attachments, and threaded replies
- Add idempotent migration script to set up new collections and add deduplication field to existing quotes table
- Implement `/api/v1/quotes/next-number` endpoint for properly formatted Q-YYYY-MM-NNN quote numbers
- Add MCP tools for idempotent quote creation, reply threading, and message ID lookup
- Add end-to-end and concurrent smoke tests for pipeline validation
- Update TypeScript types for new quote-related entities
- Update project documentation and package.json scripts
- Mark quote email intake as complete in the parity backlog
- Add n8n v2 workflows for automated email monitoring and error alerts
2026-06-22 13:58:24 +02:00

51 lines
2.3 KiB
Python

"""Verify v5 workflow correctness."""
import json
import re
from pathlib import Path
WF = Path("/Volumes/EXT/DEVELOPMENT/WFDASH_NEXTJS/n8n_workfows/WFDASH — Quote Email Monitor (v5 catch-and-create).json")
wf = json.loads(WF.read_text())
print("=== Verifying context-flow fixes ===")
for n in wf["nodes"]:
if n["name"] in ("Plan: Upload Attachments Early", "Collect Attachment IDs", "Parse PB Auth"):
code = n["parameters"]["jsCode"]
reads = re.findall(r"\$\(\s*['\"]([^'\"]+)['\"]", code)
print(f"\n{n['name']} reads from upstream nodes: {reads}")
if "binary:" in code or "binary " in code:
print(" preserves binary: yes")
else:
print(" preserves binary: NO")
print("\n=== Verifying Link Attachments to Quote ===")
for n in wf["nodes"]:
if n["name"] == "Link Attachments to Quote":
code = n["parameters"]["jsCode"]
print("Reads from upstream nodes:", re.findall(r"\$\(\s*['\"]([^'\"]+)['\"]", code))
print("Uses _attachment_record_ids:", "_attachment_record_ids" in code)
print("\n=== Connection sanity (Catch and Create branch) ===")
chain = ["PocketBase Admin Auth", "Plan: Upload Attachments Early", "Upload Attachment Early",
"Collect Attachment IDs", "Parse PB Auth"]
for i, src in enumerate(chain[:-1]):
nxt = chain[i + 1]
edges = wf["connections"].get(src, {}).get("main", [[]])
targets = [e.get("node") for e in (edges[0] if edges else [])]
ok = "✓" if nxt in targets else "✗"
print(f" {ok} {src} -> {targets} (expected {nxt})")
print("\n=== Connection sanity (Late link branch) ===")
chain2 = ["Create Quote Item", "Link Attachments to Quote", "PATCH Attachment (set quote)", "Mark has_attachments"]
for i, src in enumerate(chain2[:-1]):
nxt = chain2[i + 1]
edges = wf["connections"].get(src, {}).get("main", [[]])
targets = [e.get("node") for e in (edges[0] if edges else [])]
ok = "✓" if nxt in targets else "✗"
print(f" {ok} {src} -> {targets} (expected {nxt})")
print("\n=== Old broken nodes disabled & detached ===")
for n in wf["nodes"]:
if n["name"].startswith("DISABLED"):
in_conns = n["name"] in wf["connections"]
print(f" {'✓' if n.get('disabled') else '✗'} {n['name']} (disabled flag set)")
print(f" {'✓' if not in_conns else '✗'} not wired in connections map")