{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "41520e77",
   "metadata": {},
   "source": [
    "# 00 · Provision — Genesys CX Cloud TEI in Athena\n",
    "\n",
    "Source study: Forrester, *The Total Economic Impact™ Of CX Cloud* (Genesys +\n",
    "Salesforce, December 2025). Published headline: **NPV \\$10.78M · ROI 266%**.\n",
    "\n",
    "This notebook creates everything the study needs in the Athena sandbox:\n",
    "\n",
    "1. **Report template** *CX Cloud (Genesys + Salesforce) 2025* + **field definitions** — 4 benefits, 3 published costs, **plus the `genesys_ai_tokens` consumption line the published study omits**\n",
    "2. **Client selection** from the CRM (profile pulled, no re-entry)\n",
    "3. **Attachment** to a Proposal or Engagement\n",
    "4. **Seed values** + server-side **calculation**\n",
    "5. **Two-tier verification**: exact match vs Athena-methodology expectations, then reconciliation to the published totals (explained Year-0 discounting delta)\n",
    "6. Persists study-scoped IDs (`PALLADIUM_GENESYSCX_*`) to `.env`\n",
    "\n",
    "Safe to re-run — every step finds existing objects before creating new ones."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1b6f1117",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "✅ Athena connected — https://athena.ouranos.helu.ca (2 report templates visible)\n",
      "📁 Study: 202512_GenesysCX\n"
     ]
    }
   ],
   "source": [
    "import sys, pathlib                       # path shim: works on a fresh kernel\n",
    "for _p in [pathlib.Path.cwd(), *pathlib.Path.cwd().parents]:\n",
    "    if (_p / \"pyproject.toml\").exists():\n",
    "        sys.path.insert(0, str(_p)); break\n",
    "\n",
    "import pandas as pd\n",
    "from core.bootstrap import init, update_env\n",
    "\n",
    "pal = init(study=\"202512_GenesysCX\")\n",
    "client, seed, config = pal.client, pal.seed_data, pal.config\n",
    "assert pal.connection.get(\"status\") == \"ok\", \"Fix the connection first → 00_setup.ipynb\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1f8b6bd",
   "metadata": {},
   "source": [
    "## 1 · Report template (find or create)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "cc81e408",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found existing report template UCb2hSJprSBx (status: active)\n"
     ]
    }
   ],
   "source": [
    "REPORT_NAME, VENDOR = \"CX Cloud (Genesys + Salesforce) 2025\", \"Genesys\"\n",
    "\n",
    "report = next(\n",
    "    (r for r in client.list_reports()\n",
    "     if r.get(\"name\") == REPORT_NAME and r.get(\"vendor\") == VENDOR),\n",
    "    None,\n",
    ")\n",
    "if report is None:\n",
    "    report = client.create_report(\n",
    "        name=REPORT_NAME,\n",
    "        vendor=VENDOR,\n",
    "        version=\"1.0\",\n",
    "        description=(\n",
    "            \"Forrester TEI of CX Cloud (Genesys + Salesforce), Dec 2025. \"\n",
    "            \"Includes Palladium's genesys_ai_tokens consumption line, \"\n",
    "            \"which the published study omits.\"\n",
    "        ),\n",
    "        analysis_period_years=seed.ASSUMPTIONS[\"analysis_years\"],\n",
    "        discount_rate=seed.ASSUMPTIONS[\"discount_rate\"],\n",
    "        status=\"draft\",\n",
    "    )\n",
    "    print(f\"Created report template {report['id']}\")\n",
    "else:\n",
    "    print(f\"Found existing report template {report['id']} (status: {report.get('status')})\")\n",
    "\n",
    "REPORT_ID = report[\"id\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e31bbd8b",
   "metadata": {},
   "source": [
    "## 2 · Field definitions\n",
    "\n",
    "Same Palladium conventions as the Amazon Connect study: benefit risk\n",
    "adjustments live on the field; cost values get pushed pre-multiplied by\n",
    "`(1 + risk_adj)`; Year-0 amounts use companion `*_initial` fields.\n",
    "The `genesys_ai_tokens` line is seeded \\$0 (reproduces the published study) —\n",
    "the annual cost gets entered per deal, from the Genesys quote, in\n",
    "`03_business_case.ipynb`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "55e69828",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 fields created, 12 already existed.\n"
     ]
    }
   ],
   "source": [
    "def field_defs():\n",
    "    defs, sort = [], 0\n",
    "    for b in seed.BENEFITS:\n",
    "        sort += 1\n",
    "        defs.append({\n",
    "            \"table\": \"benefits\",\n",
    "            \"field_key\": b[\"field_key\"],\n",
    "            \"label\": b[\"label\"],\n",
    "            \"description\": b[\"notes\"][:200],\n",
    "            \"field_type\": \"currency\",\n",
    "            \"category\": b[\"category\"],\n",
    "            \"is_annual\": True,\n",
    "            \"risk_adjustment\": str(b[\"risk_adjustment\"]),\n",
    "            \"sort_order\": sort,\n",
    "            \"is_required\": True,\n",
    "            \"source_notes\": b[\"notes\"],\n",
    "        })\n",
    "    for c in seed.COSTS:\n",
    "        sort += 1\n",
    "        defs.append({\n",
    "            \"table\": \"costs\",\n",
    "            \"field_key\": c[\"field_key\"],\n",
    "            \"label\": c[\"label\"],\n",
    "            \"description\": c[\"notes\"][:200],\n",
    "            \"field_type\": \"currency\",\n",
    "            \"category\": c[\"category\"],\n",
    "            \"is_annual\": True,\n",
    "            \"risk_adjustment\": \"0\",   # cost risk adj applied client-side\n",
    "            \"sort_order\": sort,\n",
    "            \"is_required\": False,\n",
    "            \"source_notes\": c[\"notes\"],\n",
    "        })\n",
    "        sort += 1\n",
    "        defs.append({\n",
    "            \"table\": \"costs\",\n",
    "            \"field_key\": f\"{c['field_key']}_initial\",\n",
    "            \"label\": f\"{c['label']} — initial (Year 0)\",\n",
    "            \"description\": \"One-time Year-0 amount (companion field).\",\n",
    "            \"field_type\": \"currency\",\n",
    "            \"category\": c[\"category\"],\n",
    "            \"is_annual\": False,\n",
    "            \"risk_adjustment\": \"0\",\n",
    "            \"sort_order\": sort,\n",
    "            \"is_required\": False,\n",
    "            \"source_notes\": \"Year-0 lump sum; Athena treats non-annual values as Year 1.\",\n",
    "        })\n",
    "    return defs\n",
    "\n",
    "existing = {f[\"field_key\"] for f in client.list_fields(REPORT_ID)}\n",
    "created = 0\n",
    "for d in field_defs():\n",
    "    if d[\"field_key\"] not in existing:\n",
    "        client.create_field(REPORT_ID, d)\n",
    "        created += 1\n",
    "print(f\"{created} fields created, {len(existing)} already existed.\")\n",
    "\n",
    "if report.get(\"status\") == \"draft\":\n",
    "    client.update_report(REPORT_ID, status=\"active\")\n",
    "    print(\"Report template activated.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "96b360d3",
   "metadata": {},
   "source": [
    "## 3 · Select the client"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5a0a701f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>vertical</th>\n",
       "      <th>client_type</th>\n",
       "      <th>employee_count</th>\n",
       "      <th>contact_center_agent_count</th>\n",
       "      <th>supervisor_count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2</td>\n",
       "      <td>Global Guardian Insurance</td>\n",
       "      <td>None</td>\n",
       "      <td>For-Profit</td>\n",
       "      <td>12000</td>\n",
       "      <td>2500</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3</td>\n",
       "      <td>Eudaimonix</td>\n",
       "      <td>None</td>\n",
       "      <td>For-Profit</td>\n",
       "      <td>1500</td>\n",
       "      <td>300</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>4</td>\n",
       "      <td>Aetherium Forge</td>\n",
       "      <td>None</td>\n",
       "      <td>For-Profit</td>\n",
       "      <td>500</td>\n",
       "      <td>42</td>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   id                       name vertical client_type  employee_count  \\\n",
       "0   2  Global Guardian Insurance     None  For-Profit           12000   \n",
       "1   3                 Eudaimonix     None  For-Profit            1500   \n",
       "2   4            Aetherium Forge     None  For-Profit             500   \n",
       "\n",
       "   contact_center_agent_count supervisor_count  \n",
       "0                        2500             None  \n",
       "1                         300             None  \n",
       "2                          42             None  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "CLIENT_SEARCH = \"\"          # e.g. \"Acme\" — empty lists everyone\n",
    "\n",
    "clients = client.list_clients(search=CLIENT_SEARCH or None)\n",
    "if clients:\n",
    "    display(pd.DataFrame(clients)[\n",
    "        [c for c in (\"id\", \"name\", \"vertical\", \"client_type\", \"employee_count\",\n",
    "                     \"contact_center_agent_count\", \"supervisor_count\")\n",
    "         if c in clients[0]]\n",
    "    ])\n",
    "else:\n",
    "    print(\"No clients found — create one in the Athena UI (Orbit → Clients) and re-run.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1e375b54",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Global Guardian Insurance</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>id</th>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>name</th>\n",
       "      <td>Global Guardian Insurance</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>abbreviated_name</th>\n",
       "      <td>GGI</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>vertical</th>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>client_type</th>\n",
       "      <td>For-Profit</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>employee_count</th>\n",
       "      <td>12000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>revenue</th>\n",
       "      <td>4500000000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>contact_center_agent_count</th>\n",
       "      <td>2500</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>service_desk_agent_count</th>\n",
       "      <td>300</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>supervisor_count</th>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>location_count</th>\n",
       "      <td>120</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                            Global Guardian Insurance\n",
       "id                                                  2\n",
       "name                        Global Guardian Insurance\n",
       "abbreviated_name                                  GGI\n",
       "vertical                                         None\n",
       "client_type                                For-Profit\n",
       "employee_count                                  12000\n",
       "revenue                                  4500000000.0\n",
       "contact_center_agent_count                       2500\n",
       "service_desk_agent_count                          300\n",
       "supervisor_count                                 None\n",
       "location_count                                    120"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CRM agent count: 2500 (composite: 600) — indicative scale 4.17×\n",
      "CRM revenue: $4,500,000,000 (composite: $2,500,000,000)\n"
     ]
    }
   ],
   "source": [
    "CLIENT_ID = 2            # ← set from the `id` column above, or leave for auto-pick\n",
    "\n",
    "if CLIENT_ID is None and len(clients) == 1:\n",
    "    CLIENT_ID = clients[0][\"id\"]\n",
    "    print(f\"Auto-selected the only client: {clients[0]['name']} (id={CLIENT_ID})\")\n",
    "assert CLIENT_ID is not None, \"Set CLIENT_ID from the table above and re-run this cell.\"\n",
    "\n",
    "profile = client.client_profile(CLIENT_ID)\n",
    "CLIENT_NAME = profile[\"name\"]\n",
    "display(pd.DataFrame([profile]).T.rename(columns={0: CLIENT_NAME}))\n",
    "\n",
    "# Client data → study scaling levers (no re-entry)\n",
    "CLIENT_ASSUMPTIONS = dict(seed.ASSUMPTIONS)\n",
    "if profile.get(\"contact_center_agent_count\"):\n",
    "    CLIENT_ASSUMPTIONS[\"agents_fte\"] = profile[\"contact_center_agent_count\"]\n",
    "    scale = CLIENT_ASSUMPTIONS[\"agents_fte\"] / seed.ASSUMPTIONS[\"agents_fte\"]\n",
    "    print(f\"CRM agent count: {CLIENT_ASSUMPTIONS['agents_fte']} \"\n",
    "          f\"(composite: {seed.ASSUMPTIONS['agents_fte']}) — \"\n",
    "          f\"indicative scale {scale:.2f}×\")\n",
    "if profile.get(\"revenue\"):\n",
    "    CLIENT_ASSUMPTIONS[\"annual_revenue\"] = float(profile[\"revenue\"])\n",
    "    print(f\"CRM revenue: ${CLIENT_ASSUMPTIONS['annual_revenue']:,.0f} \"\n",
    "          f\"(composite: ${seed.ASSUMPTIONS['annual_revenue']:,.0f})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ff83486",
   "metadata": {},
   "source": [
    "## 4 · Pick the attachment — Proposal or Engagement"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "584e01dd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Proposals for Global Guardian Insurance:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>status</th>\n",
       "      <th>opportunity</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>Secure Cloud Infrastructure Modernization</td>\n",
       "      <td>Draft</td>\n",
       "      <td>Secure Cloud Infrastructure Modernization</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   id                                       name status  \\\n",
       "0   1  Secure Cloud Infrastructure Modernization  Draft   \n",
       "\n",
       "                                 opportunity  \n",
       "0  Secure Cloud Infrastructure Modernization  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "proposals = client.proposals_for_client(CLIENT_ID)\n",
    "engagements = client.engagements_for_client(CLIENT_NAME)\n",
    "\n",
    "if proposals:\n",
    "    print(f\"Proposals for {CLIENT_NAME}:\")\n",
    "    display(pd.DataFrame([\n",
    "        {\"id\": p[\"id\"], \"name\": p.get(\"name\"), \"status\": p.get(\"status\"),\n",
    "         \"opportunity\": (p.get(\"opportunity\") or {}).get(\"name\")}\n",
    "        for p in proposals\n",
    "    ]))\n",
    "if engagements:\n",
    "    print(f\"Engagements for {CLIENT_NAME}:\")\n",
    "    display(pd.DataFrame([\n",
    "        {\"id\": e[\"id\"], \"name\": e.get(\"name\"), \"status\": e.get(\"status\")}\n",
    "        for e in engagements\n",
    "    ]))\n",
    "if not proposals and not engagements:\n",
    "    print(f\"{CLIENT_NAME} has no proposals or engagements yet — \"\n",
    "          \"the next cell can create a sandbox opportunity + proposal.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "e04b1676",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Attaching via: {'proposal': 1}\n"
     ]
    }
   ],
   "source": [
    "# Set exactly ONE (ids from above). Leave both None to auto-pick — a single\n",
    "# existing option wins; otherwise a sandbox opportunity + proposal is created.\n",
    "PROPOSAL_ID   = config.PROPOSAL_ID      # or e.g. 42\n",
    "ENGAGEMENT_ID = config.ENGAGEMENT_ID    # or e.g. 7\n",
    "\n",
    "if PROPOSAL_ID is None and ENGAGEMENT_ID is None:\n",
    "    if len(proposals) == 1 and not engagements:\n",
    "        PROPOSAL_ID = proposals[0][\"id\"]\n",
    "        print(f\"Auto-selected proposal {PROPOSAL_ID}: {proposals[0].get('name')}\")\n",
    "    elif len(engagements) == 1 and not proposals:\n",
    "        ENGAGEMENT_ID = engagements[0][\"id\"]\n",
    "        print(f\"Auto-selected engagement {ENGAGEMENT_ID}: {engagements[0].get('name')}\")\n",
    "    elif not proposals and not engagements:\n",
    "        opp = client.create_opportunity(\n",
    "            name=f\"{CLIENT_NAME} — CX Cloud Modernization (sandbox)\",\n",
    "            client_id=CLIENT_ID,\n",
    "            description=\"Created by Palladium 00_provision for the Genesys CX Cloud TEI.\",\n",
    "        )\n",
    "        prop = client.create_proposal(\n",
    "            name=f\"{CLIENT_NAME} — Genesys CX Cloud TEI (sandbox)\",\n",
    "            opportunity_id=opp[\"id\"],\n",
    "            status=\"Draft\",\n",
    "        )\n",
    "        PROPOSAL_ID = prop[\"id\"]\n",
    "        print(f\"Created opportunity {opp['id']} and proposal {PROPOSAL_ID} for {CLIENT_NAME}.\")\n",
    "    else:\n",
    "        raise SystemExit(\"Multiple options — set PROPOSAL_ID or ENGAGEMENT_ID above and re-run.\")\n",
    "\n",
    "assert (PROPOSAL_ID is None) != (ENGAGEMENT_ID is None), \\\n",
    "    \"Set exactly one of PROPOSAL_ID / ENGAGEMENT_ID.\"\n",
    "attach = {\"proposal\": PROPOSAL_ID} if PROPOSAL_ID else {\"engagement\": ENGAGEMENT_ID}\n",
    "print(f\"Attaching via: {attach}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b4fcb45",
   "metadata": {},
   "source": [
    "## 5 · Tool instance & seed the published values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "0655d1fc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found existing tool 3rzDgVdsjhVv (status: draft)\n"
     ]
    }
   ],
   "source": [
    "from core.tei_client import AthenaAPIError\n",
    "\n",
    "def _report_id_of(t):\n",
    "    r = t.get(\"report\")\n",
    "    return r.get(\"id\") if isinstance(r, dict) else r\n",
    "\n",
    "def _matches_attachment(t):\n",
    "    if PROPOSAL_ID is not None:\n",
    "        opp = t.get(\"opportunity\") or {}\n",
    "        return t.get(\"proposal\") == PROPOSAL_ID or opp.get(\"proposal_id\") == PROPOSAL_ID\n",
    "    eng = t.get(\"engagement\")\n",
    "    eng_id = eng.get(\"id\") if isinstance(eng, dict) else eng\n",
    "    return eng_id == ENGAGEMENT_ID\n",
    "\n",
    "candidates = [t for t in client.list_tools() if _report_id_of(t) == REPORT_ID]\n",
    "tool = next((t for t in candidates if _matches_attachment(t)),\n",
    "            candidates[0] if len(candidates) == 1 else None)\n",
    "\n",
    "if tool is None:\n",
    "    try:\n",
    "        tool = client.create_tool(\n",
    "            report_public_id=REPORT_ID,\n",
    "            name=f\"{CLIENT_NAME} — Genesys CX Cloud TEI\",\n",
    "            **attach,\n",
    "        )\n",
    "        print(f\"Created tool {tool['id']} attached to {attach}\")\n",
    "    except AthenaAPIError as e:\n",
    "        if e.status_code == 409:   # DUPLICATE_INSTANCE\n",
    "            raise SystemExit(\n",
    "                \"An active tool already exists for this report + attachment. \"\n",
    "                \"Find it with client.list_tools() or pick a different proposal/engagement.\"\n",
    "            ) from e\n",
    "        raise\n",
    "else:\n",
    "    print(f\"Found existing tool {tool['id']} (status: {tool.get('status')})\")\n",
    "\n",
    "TOOL_ID = tool[\"id\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "86443d76",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Pushed values for 8 fields (genesys_ai_tokens seeded at $0 — published-study baseline).\n"
     ]
    }
   ],
   "source": [
    "payload = []\n",
    "for b in seed.BENEFITS:   # nominal; Athena risk-adjusts via the field definition\n",
    "    payload.append({\n",
    "        \"field_key\": b[\"field_key\"],\n",
    "        \"year_values\": b[\"year_values\"],\n",
    "        \"notes\": b[\"notes\"],\n",
    "    })\n",
    "for c in seed.COSTS:      # risk-adjusted UP client-side (Forrester methodology)\n",
    "    factor = 1 + c[\"risk_adjustment\"]\n",
    "    payload.append({\n",
    "        \"field_key\": c[\"field_key\"],\n",
    "        \"year_values\": {y: round(v * factor, 2) for y, v in c[\"year_values\"].items()},\n",
    "        \"initial\": round(c[\"initial\"] * factor, 2),\n",
    "        \"notes\": c[\"notes\"],\n",
    "    })\n",
    "\n",
    "client.update_values(TOOL_ID, payload)\n",
    "print(f\"Pushed values for {len(payload)} fields \"\n",
    "      f\"(genesys_ai_tokens seeded at $0 — published-study baseline).\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "509b52be",
   "metadata": {},
   "source": [
    "## 6 · Calculate & verify\n",
    "\n",
    "**Tier 1 — pipeline correctness:** Athena must match `seed.ATHENA_EXPECTED`\n",
    "(the published model re-discounted under Athena's Year-0-as-Year-1 rule)\n",
    "within 0.5%.\n",
    "\n",
    "**Tier 2 — reconciliation:** show Athena vs the published totals. The\n",
    "implementation initial (\\$1.309M, ~32% of cost PV) is discounted by Athena\n",
    "but not by Forrester, so costs PV reads ~\\$119k lower and ROI ~11pp higher\n",
    "than published. That delta is methodology, not data error."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0728b42e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "════════════════════════════════════════════════════════\n",
      "  TEI Financial Summary\n",
      "════════════════════════════════════════════════════════\n",
      "  Total Benefits (PV):  $      14,840,637\n",
      "  Total Costs (PV):     $       3,938,170\n",
      "────────────────────────────────────────────────────────\n",
      "  Net Present Value:    $      10,902,466\n",
      "  ROI:                              277%\n",
      "  Payback:                     4.0 months\n",
      "════════════════════════════════════════════════════════\n"
     ]
    }
   ],
   "source": [
    "summary = client.calculate(TOOL_ID)\n",
    "client.print_summary(TOOL_ID)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "aba8fc21",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>metric</th>\n",
       "      <th>published (Forrester)</th>\n",
       "      <th>expected (Athena methodology)</th>\n",
       "      <th>athena actual</th>\n",
       "      <th>vs expected</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>total_benefits_pv</td>\n",
       "      <td>14,840,638</td>\n",
       "      <td>14,840,640</td>\n",
       "      <td>14,840,637</td>\n",
       "      <td>-0.00%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>total_costs_pv</td>\n",
       "      <td>4,057,170</td>\n",
       "      <td>3,938,170</td>\n",
       "      <td>3,938,170</td>\n",
       "      <td>+0.00%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>net_present_value</td>\n",
       "      <td>10,783,468</td>\n",
       "      <td>10,902,470</td>\n",
       "      <td>10,902,466</td>\n",
       "      <td>-0.00%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>roi_percentage</td>\n",
       "      <td>266</td>\n",
       "      <td>277</td>\n",
       "      <td>277</td>\n",
       "      <td>+0.01%</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              metric published (Forrester) expected (Athena methodology)  \\\n",
       "0  total_benefits_pv            14,840,638                    14,840,640   \n",
       "1     total_costs_pv             4,057,170                     3,938,170   \n",
       "2  net_present_value            10,783,468                    10,902,470   \n",
       "3     roi_percentage                   266                           277   \n",
       "\n",
       "  athena actual vs expected  \n",
       "0    14,840,637      -0.00%  \n",
       "1     3,938,170      +0.00%  \n",
       "2    10,902,466      -0.00%  \n",
       "3           277      +0.01%  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Payback: 4 months (expected ≈ 4)\n",
      "✅ Tier 1 passed — pipeline reproduces the study under Athena's discounting.\n",
      "ℹ️  Tier 2: published ROI 266% vs Athena ~277% — explained Year-0 delta (see above).\n"
     ]
    }
   ],
   "source": [
    "rows, ok = [], True\n",
    "for key in (\"total_benefits_pv\", \"total_costs_pv\", \"net_present_value\", \"roi_percentage\"):\n",
    "    actual = float(summary.get(key) or 0)\n",
    "    expected = seed.ATHENA_EXPECTED[key]\n",
    "    published = seed.PUBLISHED[key]\n",
    "    diff = (actual - expected) / expected\n",
    "    rows.append({\n",
    "        \"metric\": key,\n",
    "        \"published (Forrester)\": f\"{published:,.0f}\",\n",
    "        \"expected (Athena methodology)\": f\"{expected:,.0f}\",\n",
    "        \"athena actual\": f\"{actual:,.0f}\",\n",
    "        \"vs expected\": f\"{diff:+.2%}\",\n",
    "    })\n",
    "    ok &= abs(diff) <= 0.005\n",
    "\n",
    "display(pd.DataFrame(rows))\n",
    "print(f\"Payback: {summary.get('payback_period_months')} months (expected ≈ 4)\")\n",
    "assert ok, \"Athena diverged >0.5% from its own expected methodology — investigate.\"\n",
    "print(\"✅ Tier 1 passed — pipeline reproduces the study under Athena's discounting.\")\n",
    "print(\"ℹ️  Tier 2: published ROI 266% vs Athena ~277% — explained Year-0 delta (see above).\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "181c7b55",
   "metadata": {},
   "source": [
    "## 7 · Save a baseline version & persist IDs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d8102590",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saved to /Users/robert/git/palladium/.env:\n",
      "  PALLADIUM_GENESYSCX_REPORT_PUBLIC_ID=UCb2hSJprSBx\n",
      "  PALLADIUM_GENESYSCX_TOOL_PUBLIC_ID=3rzDgVdsjhVv\n",
      "  PALLADIUM_GENESYSCX_PROPOSAL_ID=1\n",
      "\n",
      "Next → 01_benefits.ipynb (walk through the four Forrester benefits).\n"
     ]
    }
   ],
   "source": [
    "if not client.list_versions(TOOL_ID):\n",
    "    client.save_version(TOOL_ID, note=(\n",
    "        \"Baseline — published Forrester CX Cloud TEI figures (Dec 2025). \"\n",
    "        \"genesys_ai_tokens at $0 per the published study; set the annual \"\n",
    "        \"cost from the Genesys quote in 03_business_case before client use.\"\n",
    "    ))\n",
    "    print(\"Saved version 1 (baseline).\")\n",
    "\n",
    "ids = {\n",
    "    \"PALLADIUM_GENESYSCX_REPORT_PUBLIC_ID\": REPORT_ID,\n",
    "    \"PALLADIUM_GENESYSCX_TOOL_PUBLIC_ID\": TOOL_ID,\n",
    "}\n",
    "if PROPOSAL_ID is not None:\n",
    "    ids[\"PALLADIUM_GENESYSCX_PROPOSAL_ID\"] = str(PROPOSAL_ID)\n",
    "if ENGAGEMENT_ID is not None:\n",
    "    ids[\"PALLADIUM_GENESYSCX_ENGAGEMENT_ID\"] = str(ENGAGEMENT_ID)\n",
    "\n",
    "env_path = update_env(**ids)\n",
    "print(f\"Saved to {env_path}:\")\n",
    "for k, v in ids.items():\n",
    "    print(f\"  {k}={v}\")\n",
    "print(\"\\nNext → 01_benefits.ipynb (walk through the four Forrester benefits).\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4fc81c99-f073-486a-9f65-f207e96e59cd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13acdc34-71f6-4220-8675-4e1527cb8e39",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
