diff --git a/docs/nh-broadband-install-packet.example.md b/docs/nh-broadband-install-packet.example.md index d72af08..3607e81 100644 --- a/docs/nh-broadband-install-packet.example.md +++ b/docs/nh-broadband-install-packet.example.md @@ -1,7 +1,7 @@ # NH Broadband Install Packet -**Packet ID:** nh-bb-20260415-113232 -**Generated:** 2026-04-15T11:32:32.781304+00:00 +**Packet ID:** nh-bb-20260417-015617 +**Generated:** 2026-04-17T01:56:17.706676+00:00 **Status:** pending_scheduling_call ## Contact @@ -19,6 +19,26 @@ residential-fiber +## Availability Check + +- Status: pending +- Checked at: pending +- Notes: Pending exact-address lookup on nhbroadband.com + +## Pricing + +- Monthly cost: pending live quote +- Install fee: pending live quote +- Quoted at: pending +- Notes: Pending live quote from NH Broadband + +## Appointment + +- Scheduled for: pending +- Window: pending +- Confirmation number: pending +- Installer access notes: Driveway condition note pending + ## Call Log - **2026-04-15T14:30:00Z** — no_answer @@ -35,3 +55,11 @@ residential-fiber - [ ] Post-install: run speed test (fast.com / speedtest.net) - [ ] Log final speeds and appointment outcome +## Post-Install Verification + +- Download: pending +- Upload: pending +- Latency: pending +- Tested at: pending +- Notes: Populate after installation completes + diff --git a/docs/nh-broadband-install-request.example.yaml b/docs/nh-broadband-install-request.example.yaml index 7c9aab8..fb639bd 100644 --- a/docs/nh-broadband-install-request.example.yaml +++ b/docs/nh-broadband-install-request.example.yaml @@ -11,6 +11,31 @@ service: desired_plan: residential-fiber +availability: + status: pending + checked_at: "" + notes: "Pending exact-address lookup on nhbroadband.com" + +pricing: + monthly_cost_usd: + install_fee_usd: + quoted_at: "" + notes: "Pending live quote from NH Broadband" + +appointment: + scheduled_for: "" + window: "" + confirmation_number: "" + installer_access_notes: "Driveway condition note pending" + +post_install: + speed_test: + download_mbps: + upload_mbps: + latency_ms: + tested_at: "" + notes: "Populate after installation completes" + call_log: - timestamp: "2026-04-15T14:30:00Z" outcome: no_answer diff --git a/scripts/plan_nh_broadband_install.py b/scripts/plan_nh_broadband_install.py index f0a3285..71376c7 100644 --- a/scripts/plan_nh_broadband_install.py +++ b/scripts/plan_nh_broadband_install.py @@ -17,6 +17,27 @@ def load_request(path: str | Path) -> dict[str, Any]: data.setdefault("service", {}) data.setdefault("call_log", []) data.setdefault("checklist", []) + data.setdefault("availability", {}) + data.setdefault("pricing", {}) + data.setdefault("appointment", {}) + data.setdefault("post_install", {}) + data["availability"].setdefault("status", "pending") + data["availability"].setdefault("checked_at", "") + data["availability"].setdefault("notes", "") + data["pricing"].setdefault("monthly_cost_usd", None) + data["pricing"].setdefault("install_fee_usd", None) + data["pricing"].setdefault("quoted_at", "") + data["pricing"].setdefault("notes", "") + data["appointment"].setdefault("scheduled_for", "") + data["appointment"].setdefault("window", "") + data["appointment"].setdefault("confirmation_number", "") + data["appointment"].setdefault("installer_access_notes", "") + data["post_install"].setdefault("speed_test", {}) + data["post_install"]["speed_test"].setdefault("download_mbps", None) + data["post_install"]["speed_test"].setdefault("upload_mbps", None) + data["post_install"]["speed_test"].setdefault("latency_ms", None) + data["post_install"]["speed_test"].setdefault("tested_at", "") + data["post_install"]["speed_test"].setdefault("notes", "") return data @@ -39,6 +60,19 @@ def build_packet(data: dict[str, Any]) -> dict[str, Any]: validate_request(data) contact = data["contact"] service = data["service"] + availability = data.get("availability", {}) + pricing = data.get("pricing", {}) + appointment = data.get("appointment", {}) + post_install = data.get("post_install", {}) + speed_test = post_install.get("speed_test", {}) + + status = "pending_scheduling_call" + if availability.get("status") == "unavailable": + status = "blocked_unavailable" + elif appointment.get("confirmation_number") or appointment.get("scheduled_for"): + status = "scheduled_install" + if speed_test.get("download_mbps") is not None: + status = "post_install_verified" return { "packet_id": f"nh-bb-{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M%S')}", @@ -55,18 +89,69 @@ def build_packet(data: dict[str, Any]) -> dict[str, Any]: "zip": service.get("zip", ""), }, "desired_plan": data.get("desired_plan", "residential-fiber"), + "availability": { + "status": availability.get("status", "pending"), + "checked_at": availability.get("checked_at", ""), + "notes": availability.get("notes", ""), + }, + "pricing": { + "monthly_cost_usd": pricing.get("monthly_cost_usd"), + "install_fee_usd": pricing.get("install_fee_usd"), + "quoted_at": pricing.get("quoted_at", ""), + "notes": pricing.get("notes", ""), + }, + "appointment": { + "scheduled_for": appointment.get("scheduled_for", ""), + "window": appointment.get("window", ""), + "confirmation_number": appointment.get("confirmation_number", ""), + "installer_access_notes": appointment.get("installer_access_notes", ""), + }, "call_log": data.get("call_log", []), "checklist": [ {"item": item, "done": False} if isinstance(item, str) else item for item in data["checklist"] ], - "status": "pending_scheduling_call", + "post_install": { + "speed_test": { + "download_mbps": speed_test.get("download_mbps"), + "upload_mbps": speed_test.get("upload_mbps"), + "latency_ms": speed_test.get("latency_ms"), + "tested_at": speed_test.get("tested_at", ""), + "notes": speed_test.get("notes", ""), + } + }, + "status": status, } def render_markdown(packet: dict[str, Any], data: dict[str, Any]) -> str: contact = packet["contact"] addr = packet["service_address"] + availability = packet["availability"] + pricing = packet["pricing"] + appointment = packet["appointment"] + speed_test = packet["post_install"]["speed_test"] + + monthly_cost = pricing["monthly_cost_usd"] + install_fee = pricing["install_fee_usd"] + monthly_line = f"${monthly_cost:.2f}" if isinstance(monthly_cost, (int, float)) else "pending live quote" + install_line = f"${install_fee:.2f}" if isinstance(install_fee, (int, float)) else "pending live quote" + download_line = ( + f"{speed_test['download_mbps']} Mbps" + if speed_test["download_mbps"] is not None else + "pending" + ) + upload_line = ( + f"{speed_test['upload_mbps']} Mbps" + if speed_test["upload_mbps"] is not None else + "pending" + ) + latency_line = ( + f"{speed_test['latency_ms']} ms" + if speed_test["latency_ms"] is not None else + "pending" + ) + lines = [ f"# NH Broadband Install Packet", "", @@ -89,6 +174,26 @@ def render_markdown(packet: dict[str, Any], data: dict[str, Any]) -> str: "", f"{packet['desired_plan']}", "", + "## Availability Check", + "", + f"- Status: {availability['status']}", + f"- Checked at: {availability['checked_at'] or 'pending'}", + f"- Notes: {availability['notes'] or 'pending exact-address lookup'}", + "", + "## Pricing", + "", + f"- Monthly cost: {monthly_line}", + f"- Install fee: {install_line}", + f"- Quoted at: {pricing['quoted_at'] or 'pending'}", + f"- Notes: {pricing['notes'] or 'pending live quote'}", + "", + "## Appointment", + "", + f"- Scheduled for: {appointment['scheduled_for'] or 'pending'}", + f"- Window: {appointment['window'] or 'pending'}", + f"- Confirmation number: {appointment['confirmation_number'] or 'pending'}", + f"- Installer access notes: {appointment['installer_access_notes'] or 'pending'}", + "", "## Call Log", "", ] @@ -112,7 +217,17 @@ def render_markdown(packet: dict[str, Any], data: dict[str, Any]) -> str: mark = "x" if item.get("done") else " " lines.append(f"- [{mark}] {item['item']}") - lines.append("") + lines.extend([ + "", + "## Post-Install Verification", + "", + f"- Download: {download_line}", + f"- Upload: {upload_line}", + f"- Latency: {latency_line}", + f"- Tested at: {speed_test['tested_at'] or 'pending'}", + f"- Notes: {speed_test['notes'] or 'pending'}", + "", + ]) return "\n".join(lines)