""" CTM default inputs and the Genesys meter catalogue. ⚠️ Site volumes/AHTs/costs outside NAM are PLACEHOLDERS flagged ESTIMATED — confirm with CTM data before client use. NAM volumes are from the CTM discovery pack. Named users across all sites total the contracted licence count (2,088). """ from __future__ import annotations from .inputs import CostTakeout, FeatureScope, SiteInput from .meters import Confidence, MeterType, TokenMeter, TokenPricing from .rollout import RolloutPlan # ── Platform ───────────────────────────────────────────────────────── #: Genesys Cloud CX 3 named-user list rate, USD/user/month. #: Source: Genesys Cloud public pricing (CX 3 tier), planning figure. PLATFORM_RATE_PER_USER_MONTHLY = 111.28 #: CTM contracted named-user count — UI warns when site totals diverge. CONTRACTED_NAMED_USERS = 2_088 #: Business-case discount rate (CTM treasury planning assumption). DEFAULT_DISCOUNT_RATE = 0.08 #: One-off implementation estimate, amortized straight-line over the #: analysis horizon in the P&L. ESTIMATED — confirm with delivery team. DEFAULT_IMPLEMENTATION_COST = 0.0 _GENESYS_TOKEN_FAQ = ( "https://help.mypurecloud.com/articles/genesys-cloud-ai-experience-tokens-faqs/" ) # ── Token meters ───────────────────────────────────────────────────── # Rates per the published Genesys AI Experience token tables unless # flagged otherwise. UNKNOWN meters carry working defaults (clearly # labelled) so the model still produces a range. DEFAULT_METERS: dict[str, TokenMeter] = { m.feature: m for m in [ TokenMeter( feature="Voice Bot", meter_type=MeterType.PER_MINUTE, units_per_token=17.0, tokens_per_unit=1 / 17, # 0.0588 confidence=Confidence.CONFIRMED, notes="IVR self-service voice bot minutes; 17 min per token.", source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Virtual Agent (legacy)", meter_type=MeterType.PER_INTERACTION, units_per_token=2.0, tokens_per_unit=0.5, confidence=Confidence.CONFIRMED, notes="Legacy (non-agentic) virtual agent; 2 interactions per token.", source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Agentic Virtual Agent", meter_type=MeterType.PER_INTERACTION, units_per_token=0.833, tokens_per_unit=1.2, confidence=Confidence.CONFIRMED, notes="Agentic VA; 1.2 tokens per interaction.", source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="AI Summary & Insights", meter_type=MeterType.PER_SUMMARY, units_per_token=50.0, tokens_per_unit=0.02, confidence=Confidence.CONFIRMED, notes=( "Supervisor standalone summarization; 50 summaries per token. " "NOT metered where Agent Copilot is assigned — see cost model." ), source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Direct Messaging", meter_type=MeterType.PER_MESSAGE, units_per_token=400.0, tokens_per_unit=0.0025, confidence=Confidence.CONFIRMED, notes="FB/IG/WhatsApp messages; 400 messages per token.", source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Social Listening", meter_type=MeterType.PER_MESSAGE, units_per_token=400.0, tokens_per_unit=0.0025, confidence=Confidence.CONFIRMED, notes="400 messages per token.", source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Social Responses", meter_type=MeterType.PER_MESSAGE, units_per_token=400.0, tokens_per_unit=0.0025, confidence=Confidence.CONFIRMED, notes="400 messages per token.", source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Speech & Text Analytics", meter_type=MeterType.PER_USER_PER_MONTH, units_per_token=0.0, # n/a for per-user meters tokens_per_unit=30.0, confidence=Confidence.CONFIRMED, notes="STA: 30 tokens per named user per month.", source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Agent Copilot", meter_type=MeterType.PER_USER_PER_MONTH, units_per_token=0.0, tokens_per_unit=40.0, confidence=Confidence.CONFIRMED, notes=( "40 tokens per named user per month. Includes interaction " "summarization (covers AI Summary & Insights)." ), source_url=_GENESYS_TOKEN_FAQ, ), TokenMeter( feature="Email AI (Auto-Suggest)", meter_type=MeterType.PER_USER_PER_MONTH, units_per_token=0.0, tokens_per_unit=30.0, # TBD — working default confidence=Confidence.UNKNOWN, notes="Rate not yet sourced. Working default 30 tokens/user/month.", ), TokenMeter( feature="Email AI (Auto-Respond)", meter_type=MeterType.PER_MESSAGE, units_per_token=2.0, # TBD tokens_per_unit=0.5, # TBD — working default confidence=Confidence.UNKNOWN, notes="Rate not yet sourced. Working default 0.5 tokens/message.", ), TokenMeter( feature="AI Translate", meter_type=MeterType.PER_USER_PER_MONTH, units_per_token=0.0, tokens_per_unit=20.0, # TBD — working default confidence=Confidence.UNKNOWN, notes="Rate not yet sourced. Working default 20 tokens/user/month.", ), ] } #: Features metered per named user per month. PER_USER_FEATURES = [ f for f, m in DEFAULT_METERS.items() if m.meter_type is MeterType.PER_USER_PER_MONTH ] # ── Token pricing ──────────────────────────────────────────────────── # $1/token US list confirmed; other regions default to the same list # rate until regional figures are sourced (override in UI). DEFAULT_PRICING: dict[str, TokenPricing] = { "US": TokenPricing(region="US", list_rate_per_token=1.0), "EU": TokenPricing(region="EU", list_rate_per_token=1.0), # TBD — assumed US list "AU": TokenPricing(region="AU", list_rate_per_token=1.0), # TBD — assumed US list "APAC": TokenPricing(region="APAC", list_rate_per_token=1.0), # TBD } # ── CTM sites ──────────────────────────────────────────────────────── # NAM figures from CTM discovery. ALL OTHER SITES + every AHT/ACW and # labour-cost figure are ESTIMATED placeholders — confirm with CTM. # Named users sum to CONTRACTED_NAMED_USERS (2,088). _COMMON = { "voice_aht_seconds": 300, # placeholder — flag as estimate "email_aht_seconds": 600, "chat_aht_seconds": 480, "voice_acw_seconds": 60, } CTM_DEFAULT_SITES: list[SiteInput] = [ SiteInput( "NAM", "US", agents=890, supervisors=60, # split TBD voice_volume_monthly=1_214_358, email_volume_monthly=275_800, chat_volume_monthly=110, sms_volume_monthly=1_040, fully_loaded_agent_cost_annual=65_000, # placeholder fully_loaded_supervisor_cost_annual=95_000, languages=["English", "French", "Spanish"], **_COMMON, ), SiteInput( "EMEA", "EU", agents=320, supervisors=25, voice_volume_monthly=420_000, email_volume_monthly=95_000, chat_volume_monthly=40, sms_volume_monthly=400, fully_loaded_agent_cost_annual=60_000, fully_loaded_supervisor_cost_annual=88_000, languages=["English", "French", "German", "Italian", "Spanish"], **_COMMON, ), SiteInput( "AUZ", "AU", agents=180, supervisors=15, voice_volume_monthly=250_000, email_volume_monthly=56_000, chat_volume_monthly=25, sms_volume_monthly=250, fully_loaded_agent_cost_annual=70_000, fully_loaded_supervisor_cost_annual=100_000, languages=["English"], **_COMMON, ), SiteInput( "APAC HK", "APAC", agents=120, supervisors=10, voice_volume_monthly=160_000, email_volume_monthly=38_000, chat_volume_monthly=15, sms_volume_monthly=150, fully_loaded_agent_cost_annual=55_000, fully_loaded_supervisor_cost_annual=80_000, languages=["English", "Cantonese", "Mandarin"], **_COMMON, ), SiteInput( "APAC SG", "APAC", agents=110, supervisors=10, voice_volume_monthly=150_000, email_volume_monthly=34_000, chat_volume_monthly=15, sms_volume_monthly=120, fully_loaded_agent_cost_annual=55_000, fully_loaded_supervisor_cost_annual=80_000, languages=["English", "Mandarin", "Malay"], **_COMMON, ), SiteInput( "APAC SH", "APAC", agents=130, supervisors=10, voice_volume_monthly=175_000, email_volume_monthly=40_000, chat_volume_monthly=15, sms_volume_monthly=130, fully_loaded_agent_cost_annual=35_000, fully_loaded_supervisor_cost_annual=55_000, languages=["Mandarin"], **_COMMON, ), SiteInput( "APAC GZ", "APAC", agents=90, supervisors=8, voice_volume_monthly=120_000, email_volume_monthly=28_000, chat_volume_monthly=10, sms_volume_monthly=100, fully_loaded_agent_cost_annual=35_000, fully_loaded_supervisor_cost_annual=55_000, languages=["Mandarin", "Cantonese"], **_COMMON, ), SiteInput( "APAC JP", "APAC", agents=60, supervisors=6, voice_volume_monthly=80_000, email_volume_monthly=19_000, chat_volume_monthly=8, sms_volume_monthly=80, fully_loaded_agent_cost_annual=60_000, fully_loaded_supervisor_cost_annual=85_000, languages=["Japanese"], **_COMMON, ), SiteInput( "APAC TW", "APAC", agents=40, supervisors=4, voice_volume_monthly=54_000, email_volume_monthly=12_000, chat_volume_monthly=5, sms_volume_monthly=50, fully_loaded_agent_cost_annual=40_000, fully_loaded_supervisor_cost_annual=60_000, languages=["Mandarin"], **_COMMON, ), ] ALL_SITE_NAMES = [s.site_name for s in CTM_DEFAULT_SITES] # ── Cost takeouts ──────────────────────────────────────────────────── CTM_DEFAULT_TAKEOUTS: list[CostTakeout] = [ CostTakeout( "NICE IEX (NAM)", annual_cost=1_300_000, start_year=1, start_month=7, # can only switch off after NAM go-live (month 6) confidence=Confidence.ESTIMATED, notes="Mid-band estimate; needs CTM contract confirmation.", ), CostTakeout( "Legacy CC platform", annual_cost=0, start_year=2, confidence=Confidence.UNKNOWN, notes="Placeholder — populate once retirement scope is confirmed.", ), ] # ── Default rollout & ramp ─────────────────────────────────────────── # 12-month build. Genesys bills the licence commit from contract start; # the 6-month ramp gives a 50% first-year credit on the platform commit. # AI token usage (and benefits) start only when each region goes live. CTM_DEFAULT_ROLLOUT = RolloutPlan( contract_start=None, # set when known — "Date Genesys starts billing" build_months=12, ramp_months=6, first_year_platform_discount=0.50, go_live_month={ "NAM": 6, "EMEA": 9, "AUZ": 12, "APAC HK": 12, "APAC SG": 12, "APAC SH": 12, "APAC GZ": 12, "APAC JP": 12, "APAC TW": 12, }, ) # ── Default feature scoping / phasing ──────────────────────────────── # Phase = model year the feature switches on. Consumption features ramp # via adoption_curve; per-user licences are paid in full from the phase # year. _RAMP = {1: 0.70, 2: 1.0, 3: 1.0} CTM_DEFAULT_FEATURE_SCOPES: list[FeatureScope] = [ FeatureScope("Voice Bot", ALL_SITE_NAMES, phase=1, adoption_curve=_RAMP), FeatureScope("Agentic Virtual Agent", ["NAM", "EMEA"], phase=2, adoption_curve={2: 0.70, 3: 1.0}), FeatureScope("Speech & Text Analytics", ALL_SITE_NAMES, phase=1), FeatureScope("Agent Copilot", ALL_SITE_NAMES, phase=1), FeatureScope("AI Summary & Insights", ALL_SITE_NAMES, phase=1, adoption_curve=_RAMP), FeatureScope("Direct Messaging", ALL_SITE_NAMES, phase=1, adoption_curve=_RAMP), FeatureScope("Email AI (Auto-Suggest)", ["NAM", "EMEA"], phase=2), FeatureScope("Email AI (Auto-Respond)", ["NAM", "EMEA"], phase=2, adoption_curve={2: 0.70, 3: 1.0}), FeatureScope("AI Translate", ["APAC HK", "APAC SG", "APAC SH", "APAC GZ", "APAC JP", "APAC TW"], phase=3), ]