packetdial: add onboard-domain wrapper (GUI Add-a-Domain -> 3-call API flow)
onboard-domain runs POST /domains -> addresses/validate (gen E911 pidflo) -> addresses/create from one JSON body (domain fields + optional `emergency` block), gated --confirm. Reverse- engineered from the OITVOIP wizard screenshots; live-created the real client domain vwp.91912.service (Valley Wide Plastering) + E911 address, and proved the wrapper with a throwaway create->delete (no leftovers, vwp intact). Documented GUI->API mapping + the two manual gaps (voicemail user-defaults, email-send-from-address pending the packetdial.com mailbox) + the domain-type "no"-on-create quirk. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -565,3 +565,36 @@ class NetSapiensClient:
|
||||
return self.request(
|
||||
"GET", f"domains/{urllib.parse.quote(domain)}/transcriptions", params=filters or None
|
||||
)
|
||||
|
||||
# ======================================================================
|
||||
# ORCHESTRATION — onboard a new client domain (mirrors the GUI "Add a Domain"
|
||||
# wizard: Basic + Defaults + Limitations -> POST /domains; Emergency tab ->
|
||||
# validate (generates the pidflo) -> create E911 address). Live-proven against
|
||||
# vwp.91912.service 2026-06-22.
|
||||
# ======================================================================
|
||||
def onboard_domain(self, body: dict) -> dict:
|
||||
"""Create a domain and (optionally) its E911 address in one flow.
|
||||
|
||||
body = the POST /domains fields PLUS an optional "emergency" sub-object
|
||||
(the address fields). Returns {"domain":..., "address_validate":...,
|
||||
"address":...}. Requires body["domain"] (full, e.g. vwp.91912.service).
|
||||
"""
|
||||
body = dict(body)
|
||||
emergency = body.pop("emergency", None)
|
||||
body.setdefault("synchronous", "yes")
|
||||
domain = body.get("domain")
|
||||
if not domain:
|
||||
raise PacketDialError("onboard_domain: body must include 'domain' (e.g. acme.91912.service)")
|
||||
result = {"domain": self.create_domain(body)}
|
||||
if emergency:
|
||||
d = urllib.parse.quote(domain)
|
||||
v = self.request("POST", f"domains/{d}/addresses/validate", json_body=dict(emergency))
|
||||
vobj = v[0] if isinstance(v, list) and v else v
|
||||
addr = dict(emergency)
|
||||
addr["address-formatted-pidflo"] = vobj.get("address-formatted-pidflo")
|
||||
addr["emergency-address-id"] = vobj.get("emergency-address-id")
|
||||
result["address_validate"] = {"status": (vobj or {}).get("ValidationStatus")
|
||||
or (vobj.get("address-formatted-pidflo") or {}).get("ValidationStatus")
|
||||
if isinstance(vobj, dict) else None}
|
||||
result["address"] = self.create_address(domain, addr)
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user