wxcli 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. wxcli/__init__.py +4 -0
  2. wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
  3. wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
  4. wxcli/_playbook/.claude/rules/cleanup.md +29 -0
  5. wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
  6. wxcli/_playbook/.claude/rules/org-health.md +14 -0
  7. wxcli/_playbook/.claude/settings.json +8 -0
  8. wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
  9. wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
  10. wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
  11. wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
  12. wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
  13. wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
  14. wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
  15. wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
  16. wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
  17. wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
  18. wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
  19. wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
  20. wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
  21. wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
  22. wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
  23. wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
  24. wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
  25. wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
  26. wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
  27. wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
  28. wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
  29. wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
  30. wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
  31. wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
  32. wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
  33. wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
  34. wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
  35. wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
  36. wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
  37. wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
  38. wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
  39. wxcli/_playbook/CLAUDE.md +373 -0
  40. wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
  41. wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
  42. wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
  43. wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
  44. wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
  45. wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
  46. wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
  47. wxcli/_playbook/docs/reference/admin-partner.md +357 -0
  48. wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
  49. wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
  50. wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
  51. wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
  52. wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
  53. wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
  54. wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
  55. wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
  56. wxcli/_playbook/docs/reference/authentication.md +965 -0
  57. wxcli/_playbook/docs/reference/call-control.md +1205 -0
  58. wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
  59. wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
  60. wxcli/_playbook/docs/reference/call-routing.md +2304 -0
  61. wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
  62. wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
  63. wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
  64. wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
  65. wxcli/_playbook/docs/reference/devices-core.md +1869 -0
  66. wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
  67. wxcli/_playbook/docs/reference/devices-platform.md +467 -0
  68. wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
  69. wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
  70. wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
  71. wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
  72. wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
  73. wxcli/_playbook/docs/reference/meetings-content.md +473 -0
  74. wxcli/_playbook/docs/reference/meetings-core.md +903 -0
  75. wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
  76. wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
  77. wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
  78. wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
  79. wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
  80. wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
  81. wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
  82. wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
  83. wxcli/_playbook/docs/reference/provisioning.md +1366 -0
  84. wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
  85. wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
  86. wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
  87. wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
  88. wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
  89. wxcli/_version.py +24 -0
  90. wxcli/auth.py +137 -0
  91. wxcli/commands/__init__.py +0 -0
  92. wxcli/commands/_registry.py +181 -0
  93. wxcli/commands/activation_email.py +103 -0
  94. wxcli/commands/admin_recordings.py +585 -0
  95. wxcli/commands/analytics.py +105 -0
  96. wxcli/commands/announcement_playlists.py +219 -0
  97. wxcli/commands/announcements.py +519 -0
  98. wxcli/commands/archive_users.py +36 -0
  99. wxcli/commands/attachment_actions.py +60 -0
  100. wxcli/commands/audit_events.py +83 -0
  101. wxcli/commands/authorizations.py +113 -0
  102. wxcli/commands/auto_attendant.py +642 -0
  103. wxcli/commands/broadworks_billing_reports.py +126 -0
  104. wxcli/commands/broadworks_enterprises.py +160 -0
  105. wxcli/commands/broadworks_subscribers.py +319 -0
  106. wxcli/commands/broadworks_workspaces.py +108 -0
  107. wxcli/commands/call_controls.py +1304 -0
  108. wxcli/commands/call_park.py +494 -0
  109. wxcli/commands/call_pickup.py +229 -0
  110. wxcli/commands/call_queue.py +1878 -0
  111. wxcli/commands/call_recording.py +707 -0
  112. wxcli/commands/call_routing.py +1610 -0
  113. wxcli/commands/call_settings_for_me_phase_5.py +212 -0
  114. wxcli/commands/caller_reputation.py +169 -0
  115. wxcli/commands/calling_service.py +305 -0
  116. wxcli/commands/cc_address_book.py +770 -0
  117. wxcli/commands/cc_agent_greetings.py +242 -0
  118. wxcli/commands/cc_agent_summaries.py +39 -0
  119. wxcli/commands/cc_agent_wellbeing.py +216 -0
  120. wxcli/commands/cc_agents.py +425 -0
  121. wxcli/commands/cc_ai_assistant.py +55 -0
  122. wxcli/commands/cc_ai_feature.py +294 -0
  123. wxcli/commands/cc_audio_files.py +149 -0
  124. wxcli/commands/cc_auto_csat.py +311 -0
  125. wxcli/commands/cc_aux_code.py +458 -0
  126. wxcli/commands/cc_business_hour.py +353 -0
  127. wxcli/commands/cc_call_monitoring.py +228 -0
  128. wxcli/commands/cc_callbacks.py +194 -0
  129. wxcli/commands/cc_campaign.py +212 -0
  130. wxcli/commands/cc_captures.py +39 -0
  131. wxcli/commands/cc_contact_list.py +169 -0
  132. wxcli/commands/cc_contact_number.py +295 -0
  133. wxcli/commands/cc_data_sources.py +235 -0
  134. wxcli/commands/cc_desktop_layout.py +380 -0
  135. wxcli/commands/cc_desktop_profile.py +322 -0
  136. wxcli/commands/cc_dial_number.py +511 -0
  137. wxcli/commands/cc_dial_plan.py +347 -0
  138. wxcli/commands/cc_dnc.py +101 -0
  139. wxcli/commands/cc_entry_point.py +545 -0
  140. wxcli/commands/cc_ewt.py +51 -0
  141. wxcli/commands/cc_flow.py +477 -0
  142. wxcli/commands/cc_global_vars.py +430 -0
  143. wxcli/commands/cc_holiday_list.py +335 -0
  144. wxcli/commands/cc_journey.py +1261 -0
  145. wxcli/commands/cc_legacy_flows.py +49 -0
  146. wxcli/commands/cc_multimedia_profile.py +436 -0
  147. wxcli/commands/cc_notification.py +51 -0
  148. wxcli/commands/cc_outdial_ani.py +604 -0
  149. wxcli/commands/cc_overrides.py +341 -0
  150. wxcli/commands/cc_queue.py +1083 -0
  151. wxcli/commands/cc_queue_stats.py +55 -0
  152. wxcli/commands/cc_realtime.py +51 -0
  153. wxcli/commands/cc_resource_collection.py +312 -0
  154. wxcli/commands/cc_search.py +46 -0
  155. wxcli/commands/cc_site.py +400 -0
  156. wxcli/commands/cc_skill.py +350 -0
  157. wxcli/commands/cc_skill_profile.py +289 -0
  158. wxcli/commands/cc_subscriptions.py +426 -0
  159. wxcli/commands/cc_summaries.py +130 -0
  160. wxcli/commands/cc_tasks.py +844 -0
  161. wxcli/commands/cc_team.py +325 -0
  162. wxcli/commands/cc_user_profiles.py +349 -0
  163. wxcli/commands/cc_users.py +701 -0
  164. wxcli/commands/cc_work_types.py +363 -0
  165. wxcli/commands/cdr.py +89 -0
  166. wxcli/commands/classifications.py +38 -0
  167. wxcli/commands/cleanup.py +1427 -0
  168. wxcli/commands/client_settings.py +72 -0
  169. wxcli/commands/conference.py +328 -0
  170. wxcli/commands/configure.py +72 -0
  171. wxcli/commands/converged_recordings.py +347 -0
  172. wxcli/commands/converged_recordings_export.py +310 -0
  173. wxcli/commands/cq_playlists.py +42 -0
  174. wxcli/commands/cucm.py +2794 -0
  175. wxcli/commands/cucm_config.py +129 -0
  176. wxcli/commands/customer_assist.py +373 -0
  177. wxcli/commands/data_sources.py +227 -0
  178. wxcli/commands/dect_devices.py +787 -0
  179. wxcli/commands/device_configurations.py +77 -0
  180. wxcli/commands/device_dynamic_settings.py +320 -0
  181. wxcli/commands/device_settings.py +1489 -0
  182. wxcli/commands/devices.py +280 -0
  183. wxcli/commands/domains.py +142 -0
  184. wxcli/commands/ecm.py +178 -0
  185. wxcli/commands/emergency_services.py +827 -0
  186. wxcli/commands/events.py +83 -0
  187. wxcli/commands/external_voicemail.py +52 -0
  188. wxcli/commands/groups.py +206 -0
  189. wxcli/commands/guest_management.py +76 -0
  190. wxcli/commands/hds.py +340 -0
  191. wxcli/commands/hot_desk.py +67 -0
  192. wxcli/commands/hot_desking_members.py +118 -0
  193. wxcli/commands/hot_desking_portal.py +124 -0
  194. wxcli/commands/hunt_group.py +577 -0
  195. wxcli/commands/hybrid_clusters.py +71 -0
  196. wxcli/commands/hybrid_connectors.py +67 -0
  197. wxcli/commands/identity_org.py +159 -0
  198. wxcli/commands/init_playbook.py +155 -0
  199. wxcli/commands/licenses.py +106 -0
  200. wxcli/commands/live_monitoring.py +40 -0
  201. wxcli/commands/location_call_handling.py +577 -0
  202. wxcli/commands/location_schedules.py +341 -0
  203. wxcli/commands/location_settings.py +1297 -0
  204. wxcli/commands/location_voicemail.py +494 -0
  205. wxcli/commands/locations.py +336 -0
  206. wxcli/commands/meeting_captions.py +110 -0
  207. wxcli/commands/meeting_chats.py +63 -0
  208. wxcli/commands/meeting_invitees.py +234 -0
  209. wxcli/commands/meeting_messages.py +28 -0
  210. wxcli/commands/meeting_participants.py +278 -0
  211. wxcli/commands/meeting_polls.py +111 -0
  212. wxcli/commands/meeting_preferences.py +515 -0
  213. wxcli/commands/meeting_qa.py +78 -0
  214. wxcli/commands/meeting_qualities.py +43 -0
  215. wxcli/commands/meeting_reports.py +101 -0
  216. wxcli/commands/meeting_session_types.py +105 -0
  217. wxcli/commands/meeting_site.py +57 -0
  218. wxcli/commands/meeting_slido.py +44 -0
  219. wxcli/commands/meeting_summaries.py +92 -0
  220. wxcli/commands/meeting_tracking_codes.py +233 -0
  221. wxcli/commands/meeting_transcripts.py +230 -0
  222. wxcli/commands/meetings.py +1997 -0
  223. wxcli/commands/memberships.py +164 -0
  224. wxcli/commands/messages.py +213 -0
  225. wxcli/commands/mode_management.py +244 -0
  226. wxcli/commands/my_call_settings.py +3577 -0
  227. wxcli/commands/numbers.py +405 -0
  228. wxcli/commands/operating_modes.py +410 -0
  229. wxcli/commands/org_contacts.py +284 -0
  230. wxcli/commands/org_health_cli.py +55 -0
  231. wxcli/commands/org_settings.py +71 -0
  232. wxcli/commands/organizations.py +83 -0
  233. wxcli/commands/paging_group.py +257 -0
  234. wxcli/commands/partner_admins.py +141 -0
  235. wxcli/commands/partner_reports.py +188 -0
  236. wxcli/commands/partner_tags.py +216 -0
  237. wxcli/commands/people.py +279 -0
  238. wxcli/commands/person_call_settings.py +71 -0
  239. wxcli/commands/pstn.py +280 -0
  240. wxcli/commands/recording_report.py +154 -0
  241. wxcli/commands/report_templates.py +38 -0
  242. wxcli/commands/reports.py +144 -0
  243. wxcli/commands/resource_group_memberships.py +160 -0
  244. wxcli/commands/resource_groups.py +67 -0
  245. wxcli/commands/roles.py +63 -0
  246. wxcli/commands/room_tabs.py +160 -0
  247. wxcli/commands/rooms.py +225 -0
  248. wxcli/commands/scim_bulk.py +46 -0
  249. wxcli/commands/scim_groups.py +246 -0
  250. wxcli/commands/scim_schemas.py +82 -0
  251. wxcli/commands/scim_users.py +283 -0
  252. wxcli/commands/security_audit.py +54 -0
  253. wxcli/commands/service_apps.py +51 -0
  254. wxcli/commands/single_number_reach.py +209 -0
  255. wxcli/commands/team_memberships.py +155 -0
  256. wxcli/commands/teams.py +153 -0
  257. wxcli/commands/ucm_profile.py +42 -0
  258. wxcli/commands/update.py +219 -0
  259. wxcli/commands/user_settings.py +5116 -0
  260. wxcli/commands/video_mesh.py +1090 -0
  261. wxcli/commands/virtual_extensions.py +502 -0
  262. wxcli/commands/virtual_line_settings.py +2072 -0
  263. wxcli/commands/webhooks.py +176 -0
  264. wxcli/commands/wholesale_billing_reports.py +147 -0
  265. wxcli/commands/wholesale_provisioning.py +523 -0
  266. wxcli/commands/workspace_locations.py +339 -0
  267. wxcli/commands/workspace_metrics.py +103 -0
  268. wxcli/commands/workspace_personalization.py +70 -0
  269. wxcli/commands/workspace_settings.py +3347 -0
  270. wxcli/commands/workspaces.py +279 -0
  271. wxcli/commands/xapi.py +114 -0
  272. wxcli/config.py +139 -0
  273. wxcli/errors.py +77 -0
  274. wxcli/main.py +210 -0
  275. wxcli/migration/CLAUDE.md +106 -0
  276. wxcli/migration/__init__.py +1 -0
  277. wxcli/migration/advisory/CLAUDE.md +196 -0
  278. wxcli/migration/advisory/__init__.py +46 -0
  279. wxcli/migration/advisory/advisor.py +107 -0
  280. wxcli/migration/advisory/advisory_patterns.py +2552 -0
  281. wxcli/migration/advisory/recommendation_rules.py +835 -0
  282. wxcli/migration/cucm/CLAUDE.md +74 -0
  283. wxcli/migration/cucm/__init__.py +5 -0
  284. wxcli/migration/cucm/connection.py +265 -0
  285. wxcli/migration/cucm/discovery.py +225 -0
  286. wxcli/migration/cucm/extractors/__init__.py +1 -0
  287. wxcli/migration/cucm/extractors/announcements.py +92 -0
  288. wxcli/migration/cucm/extractors/base.py +90 -0
  289. wxcli/migration/cucm/extractors/device_profiles.py +98 -0
  290. wxcli/migration/cucm/extractors/devices.py +193 -0
  291. wxcli/migration/cucm/extractors/e911.py +103 -0
  292. wxcli/migration/cucm/extractors/features.py +309 -0
  293. wxcli/migration/cucm/extractors/helpers.py +73 -0
  294. wxcli/migration/cucm/extractors/informational.py +295 -0
  295. wxcli/migration/cucm/extractors/locations.py +221 -0
  296. wxcli/migration/cucm/extractors/moh.py +100 -0
  297. wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
  298. wxcli/migration/cucm/extractors/routing.py +493 -0
  299. wxcli/migration/cucm/extractors/shared_lines.py +146 -0
  300. wxcli/migration/cucm/extractors/templates.py +229 -0
  301. wxcli/migration/cucm/extractors/tier4.py +173 -0
  302. wxcli/migration/cucm/extractors/users.py +240 -0
  303. wxcli/migration/cucm/extractors/voicemail.py +243 -0
  304. wxcli/migration/cucm/extractors/workspaces.py +88 -0
  305. wxcli/migration/cucm/unity_connection.py +304 -0
  306. wxcli/migration/execute/CLAUDE.md +372 -0
  307. wxcli/migration/execute/__init__.py +303 -0
  308. wxcli/migration/execute/batch.py +277 -0
  309. wxcli/migration/execute/dependency.py +483 -0
  310. wxcli/migration/execute/engine.py +964 -0
  311. wxcli/migration/execute/handlers.py +2232 -0
  312. wxcli/migration/execute/planner.py +1939 -0
  313. wxcli/migration/execute/runtime.py +571 -0
  314. wxcli/migration/export/CLAUDE.md +49 -0
  315. wxcli/migration/export/__init__.py +8 -0
  316. wxcli/migration/export/csv_export.py +126 -0
  317. wxcli/migration/export/deployment_plan.py +479 -0
  318. wxcli/migration/export/json_export.py +60 -0
  319. wxcli/migration/models.py +941 -0
  320. wxcli/migration/phone_models.py +50 -0
  321. wxcli/migration/preflight/CLAUDE.md +52 -0
  322. wxcli/migration/preflight/__init__.py +89 -0
  323. wxcli/migration/preflight/checks.py +911 -0
  324. wxcli/migration/preflight/runner.py +293 -0
  325. wxcli/migration/rate_limiter.py +144 -0
  326. wxcli/migration/report/CLAUDE.md +245 -0
  327. wxcli/migration/report/__init__.py +7 -0
  328. wxcli/migration/report/appendix.py +2437 -0
  329. wxcli/migration/report/assembler.py +183 -0
  330. wxcli/migration/report/charts.py +263 -0
  331. wxcli/migration/report/executive.py +776 -0
  332. wxcli/migration/report/explainer.py +704 -0
  333. wxcli/migration/report/helpers.py +74 -0
  334. wxcli/migration/report/ingest.py +152 -0
  335. wxcli/migration/report/notice_templates.py +192 -0
  336. wxcli/migration/report/score.py +375 -0
  337. wxcli/migration/report/styles.py +1052 -0
  338. wxcli/migration/report/user_diff.py +1052 -0
  339. wxcli/migration/report/user_notice.py +425 -0
  340. wxcli/migration/state.py +139 -0
  341. wxcli/migration/store.py +860 -0
  342. wxcli/migration/transform/CLAUDE.md +107 -0
  343. wxcli/migration/transform/__init__.py +12 -0
  344. wxcli/migration/transform/analysis_pipeline.py +453 -0
  345. wxcli/migration/transform/analyzers/__init__.py +142 -0
  346. wxcli/migration/transform/analyzers/css_permission.py +189 -0
  347. wxcli/migration/transform/analyzers/css_routing.py +335 -0
  348. wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
  349. wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
  350. wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
  351. wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
  352. wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
  353. wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
  354. wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
  355. wxcli/migration/transform/analyzers/missing_data.py +300 -0
  356. wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
  357. wxcli/migration/transform/analyzers/shared_line.py +170 -0
  358. wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
  359. wxcli/migration/transform/analyzers/workspace_license.py +212 -0
  360. wxcli/migration/transform/cross_reference.py +1136 -0
  361. wxcli/migration/transform/cucm_pattern.py +246 -0
  362. wxcli/migration/transform/decisions.py +301 -0
  363. wxcli/migration/transform/e164.py +145 -0
  364. wxcli/migration/transform/engine.py +256 -0
  365. wxcli/migration/transform/mappers/CLAUDE.md +123 -0
  366. wxcli/migration/transform/mappers/__init__.py +76 -0
  367. wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
  368. wxcli/migration/transform/mappers/base.py +190 -0
  369. wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
  370. wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
  371. wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
  372. wxcli/migration/transform/mappers/css_mapper.py +868 -0
  373. wxcli/migration/transform/mappers/dect_mapper.py +367 -0
  374. wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
  375. wxcli/migration/transform/mappers/device_mapper.py +227 -0
  376. wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
  377. wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
  378. wxcli/migration/transform/mappers/e911_mapper.py +129 -0
  379. wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
  380. wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
  381. wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
  382. wxcli/migration/transform/mappers/line_mapper.py +310 -0
  383. wxcli/migration/transform/mappers/location_mapper.py +235 -0
  384. wxcli/migration/transform/mappers/moh_mapper.py +114 -0
  385. wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
  386. wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
  387. wxcli/migration/transform/mappers/routing_mapper.py +821 -0
  388. wxcli/migration/transform/mappers/snr_mapper.py +201 -0
  389. wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
  390. wxcli/migration/transform/mappers/user_mapper.py +264 -0
  391. wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
  392. wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
  393. wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
  394. wxcli/migration/transform/normalizers.py +2008 -0
  395. wxcli/migration/transform/pattern_converter.py +106 -0
  396. wxcli/migration/transform/pipeline.py +271 -0
  397. wxcli/migration/transform/rules.py +255 -0
  398. wxcli/org_health/CLAUDE.md +63 -0
  399. wxcli/org_health/__init__.py +7 -0
  400. wxcli/org_health/analyze.py +93 -0
  401. wxcli/org_health/checks.py +458 -0
  402. wxcli/org_health/collector.py +62 -0
  403. wxcli/org_health/models.py +78 -0
  404. wxcli/org_health/report.py +300 -0
  405. wxcli/output.py +101 -0
  406. wxcli-1.2.0.dist-info/METADATA +505 -0
  407. wxcli-1.2.0.dist-info/RECORD +413 -0
  408. wxcli-1.2.0.dist-info/WHEEL +5 -0
  409. wxcli-1.2.0.dist-info/entry_points.txt +2 -0
  410. wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
  411. wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
  412. wxcli-1.2.0.dist-info/scm_version.json +8 -0
  413. wxcli-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,183 @@
1
+ """Report assembler — combines executive summary + appendix into a self-contained HTML file (v4).
2
+
3
+ One public function: ``assemble_report()``.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import html as html_mod
9
+ from datetime import datetime, timezone
10
+
11
+ from wxcli.migration.report.executive import generate_executive_summary
12
+ from wxcli.migration.report.appendix import generate_appendix
13
+ from wxcli.migration.report.styles import REPORT_CSS, GOOGLE_FONTS_LINKS
14
+ from wxcli.migration.store import MigrationStore
15
+
16
+
17
+ def assemble_report(
18
+ store: MigrationStore,
19
+ brand: str,
20
+ prepared_by: str,
21
+ cluster_name: str = "",
22
+ cucm_version: str = "",
23
+ executive_only: bool = False,
24
+ ) -> str:
25
+ """Assemble a complete, self-contained HTML assessment report.
26
+
27
+ Args:
28
+ store: Populated MigrationStore (post-analyze state).
29
+ brand: Customer/brand name for the report header.
30
+ prepared_by: Name of the SE/engineer who prepared the report.
31
+ cluster_name: CUCM cluster name (optional).
32
+ cucm_version: CUCM version string (optional).
33
+ executive_only: If True, skip the technical appendix.
34
+
35
+ Returns:
36
+ Complete HTML document string (starts with ``<!DOCTYPE html>``).
37
+ """
38
+ safe_brand = html_mod.escape(brand)
39
+ safe_prepared_by = html_mod.escape(prepared_by)
40
+ date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
41
+
42
+ # Generate executive summary HTML
43
+ executive_html = generate_executive_summary(
44
+ store,
45
+ brand=brand,
46
+ prepared_by=prepared_by,
47
+ cluster_name=cluster_name,
48
+ cucm_version=cucm_version,
49
+ )
50
+
51
+ # Generate appendix HTML (unless executive_only)
52
+ appendix_html = ""
53
+ if not executive_only:
54
+ appendix_html = generate_appendix(store)
55
+
56
+ # Build sidebar nav
57
+ sidebar_nav = _build_sidebar_nav(executive_only)
58
+
59
+ # IntersectionObserver script for scroll tracking
60
+ observer_js = _intersection_observer_js()
61
+
62
+ return f"""\
63
+ <!DOCTYPE html>
64
+ <html lang="en">
65
+ <head>
66
+ <meta charset="UTF-8">
67
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
68
+ <title>CUCM Migration Assessment — {safe_brand}</title>
69
+ {GOOGLE_FONTS_LINKS}
70
+ <style>{REPORT_CSS}</style>
71
+ </head>
72
+ <body>
73
+ <!-- Print header (hidden on screen) -->
74
+ <div class="print-header">
75
+ <h1>CUCM Migration Assessment</h1>
76
+ <p class="meta">{safe_brand} | Prepared by {safe_prepared_by} | {date_str}</p>
77
+ </div>
78
+
79
+ <!-- Screen header -->
80
+ <div class="page-header">
81
+ <div class="brand">{safe_brand}</div>
82
+ <h1>CUCM Migration Assessment</h1>
83
+ <div class="subtitle">Prepared by {safe_prepared_by}</div>
84
+ <div class="meta">{date_str}</div>
85
+ </div>
86
+
87
+ <div class="main-layout">
88
+ <nav class="step-list">
89
+ {sidebar_nav}
90
+ </nav>
91
+ <div class="detail-panel">
92
+ {executive_html}
93
+ {appendix_html}
94
+ <footer class="report-footer">
95
+ <p>Generated by cucm-assess | {date_str}</p>
96
+ </footer>
97
+ </div>
98
+ </div>
99
+
100
+ {observer_js}
101
+ </body>
102
+ </html>"""
103
+
104
+
105
+ def _build_sidebar_nav(executive_only: bool) -> str:
106
+ """Build the sidebar navigation HTML with numbered exec + lettered tech items."""
107
+ exec_items = [
108
+ ("1", "#score", "Migration Complexity"),
109
+ ("2", "#inventory", "What You Have"),
110
+ ("3", "#decisions", "What Needs Attention"),
111
+ ("4", "#next-steps", "Next Steps"),
112
+ ]
113
+
114
+ tech_items = [
115
+ ("A", "#objects", "Object Inventory"),
116
+ ("B", "#decision-detail", "Decision Detail"),
117
+ ("C", "#css-partitions", "CSS / Partitions"),
118
+ ("D", "#device-detail", "Device Inventory"),
119
+ ("E", "#dn-analysis", "DN Analysis"),
120
+ ("F", "#user-device-map", "User/Device Map"),
121
+ ("G", "#routing", "Routing Topology"),
122
+ ("H", "#voicemail", "Voicemail Analysis"),
123
+ ("I", "#audio-assets", "Audio Assets"),
124
+ ("J", "#coverage", "Data Coverage"),
125
+ ("K", "#gateways", "Gateways & Analog Ports"),
126
+ ("L", "#call-features", "Call Features"),
127
+ ("M", "#button-templates", "Button Templates"),
128
+ ("N", "#device-layouts", "Device Layouts"),
129
+ ("O", "#softkeys", "Softkey Migration"),
130
+ ("P", "#cloud-managed", "Cloud-Managed"),
131
+ ("Q", "#feature-gaps", "Feature Gaps"),
132
+ ("R", "#manual-reconfig", "Manual Reconfig"),
133
+ ("S", "#planning-inputs", "Planning Inputs"),
134
+ ("T", "#recording-inventory", "Call Recording"),
135
+ ("U", "#snr-inventory", "Single Number Reach"),
136
+ ("V", "#caller-id-xforms", "Caller ID Transforms"),
137
+ ("W", "#extension-mobility", "Extension Mobility"),
138
+ ("X", "#dect-networks", "DECT Networks"),
139
+ ]
140
+
141
+ parts = [
142
+ '<div class="step-list-section">',
143
+ '<div class="step-list-section-title">Executive Summary</div>',
144
+ ]
145
+ for num, href, label in exec_items:
146
+ parts.append(
147
+ f'<a href="{href}" class="step-item">'
148
+ f'<span class="step-icon exec">{num}</span> {html_mod.escape(label)}</a>'
149
+ )
150
+ parts.append('</div>')
151
+
152
+ if not executive_only:
153
+ parts.append('<div class="step-list-section">')
154
+ parts.append('<div class="step-list-section-title">Technical Appendix</div>')
155
+ for letter, href, label in tech_items:
156
+ parts.append(
157
+ f'<a href="{href}" class="step-item">'
158
+ f'<span class="step-icon tech">{letter}</span> {html_mod.escape(label)}</a>'
159
+ )
160
+ parts.append('</div>')
161
+
162
+ return "\n ".join(parts)
163
+
164
+
165
+ def _intersection_observer_js() -> str:
166
+ """Return IntersectionObserver JS for sidebar scroll tracking."""
167
+ return """<script>
168
+ (function() {
169
+ const sections = document.querySelectorAll('.detail-panel section, .detail-panel details');
170
+ const navLinks = document.querySelectorAll('.step-item');
171
+ const observer = new IntersectionObserver(entries => {
172
+ entries.forEach(entry => {
173
+ if (entry.isIntersecting) {
174
+ const id = entry.target.id;
175
+ navLinks.forEach(link => {
176
+ link.classList.toggle('active', link.getAttribute('href') === '#' + id);
177
+ });
178
+ }
179
+ });
180
+ }, { root: document.querySelector('.detail-panel'), threshold: 0.2 });
181
+ sections.forEach(s => { if (s.id) observer.observe(s); });
182
+ })();
183
+ </script>"""
@@ -0,0 +1,263 @@
1
+ """Inline SVG chart generators for the CUCM assessment report.
2
+
3
+ Pure functions that accept data and return SVG strings.
4
+ No store dependency, no side effects.
5
+ All SVGs are inline-safe for HTML embedding (no JavaScript).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import html
11
+ import math
12
+
13
+ _FONT = 'font-family="IBM Plex Sans, system-ui, sans-serif"'
14
+ _XMLNS = 'xmlns="http://www.w3.org/2000/svg"'
15
+
16
+
17
+ # ---------------------------------------------------------------------------
18
+ # 1. Gauge chart — 240-degree arc for complexity score
19
+ # ---------------------------------------------------------------------------
20
+
21
+ def gauge_chart(score: int, color: str, label: str) -> str:
22
+ """Return an SVG gauge chart showing a score from 0-100.
23
+
24
+ The gauge is a 240-degree arc (from 150 degrees to 390 degrees,
25
+ i.e. 7-o'clock to 5-o'clock). A gray background arc shows the full
26
+ range; a colored foreground arc shows the proportion filled.
27
+
28
+ Args:
29
+ score: Integer 0-100.
30
+ color: Hex color for the foreground arc (e.g. "#2E7D32").
31
+ label: Text label below the score (e.g. "Straightforward").
32
+
33
+ Returns:
34
+ SVG string.
35
+ """
36
+ score = max(0, min(100, score))
37
+
38
+ cx, cy = 100, 95
39
+ r = 70
40
+ stroke_width = 12
41
+ total_angle = 240 # degrees
42
+ start_angle = 150 # degrees (7-o'clock position)
43
+
44
+ def _arc_endpoint(angle_deg: float) -> tuple[float, float]:
45
+ rad = math.radians(angle_deg)
46
+ return cx + r * math.cos(rad), cy + r * math.sin(rad)
47
+
48
+ def _arc_path(from_angle: float, sweep_deg: float, stroke: str, width: int = stroke_width) -> str:
49
+ if sweep_deg <= 0:
50
+ return ""
51
+ x1, y1 = _arc_endpoint(from_angle)
52
+ x2, y2 = _arc_endpoint(from_angle + sweep_deg)
53
+ large_arc = 1 if sweep_deg > 180 else 0
54
+ return (
55
+ f'<path d="M {x1:.1f} {y1:.1f} A {r} {r} 0 {large_arc} 1 {x2:.1f} {y2:.1f}" '
56
+ f'fill="none" stroke="{stroke}" stroke-width="{width}" stroke-linecap="round"/>'
57
+ )
58
+
59
+ fg_angle = total_angle * score / 100
60
+
61
+ parts = [
62
+ f'<svg {_XMLNS} viewBox="0 0 200 155" width="160" height="125">',
63
+ # Background arc (full 240 degrees)
64
+ _arc_path(start_angle, total_angle, "#e5e7eb"),
65
+ # Foreground arc (proportional to score)
66
+ _arc_path(start_angle, fg_angle, color),
67
+ # Score number centered
68
+ f'<text x="{cx}" y="{cy + 8}" text-anchor="middle" '
69
+ f'{_FONT} font-size="36" font-weight="700" fill="#111827">{score}</text>',
70
+ # Label below
71
+ f'<text x="{cx}" y="{cy + 50}" text-anchor="middle" '
72
+ f'{_FONT} font-size="9" font-weight="500" letter-spacing="0.1em" '
73
+ f'fill="#6b7280">{html.escape(label.upper())}</text>',
74
+ "</svg>",
75
+ ]
76
+ return "\n".join(p for p in parts if p)
77
+
78
+
79
+ # ---------------------------------------------------------------------------
80
+ # 2. Donut chart — segment breakdown (e.g. phone compatibility)
81
+ # ---------------------------------------------------------------------------
82
+
83
+ def donut_chart(segments: list[dict]) -> str:
84
+ """Return an SVG donut chart with legend.
85
+
86
+ Args:
87
+ segments: List of dicts with keys "label", "value", "color".
88
+
89
+ Returns:
90
+ SVG string.
91
+ """
92
+ total = sum(s["value"] for s in segments)
93
+
94
+ cx, cy = 100, 100
95
+ r = 70
96
+ stroke_width = 30
97
+ circumference = 2 * math.pi * r
98
+
99
+ parts = [
100
+ f'<svg {_XMLNS} viewBox="0 0 400 250" width="400" height="250">',
101
+ ]
102
+
103
+ if total == 0:
104
+ # Empty state: just draw a gray circle
105
+ parts.append(
106
+ f'<circle cx="{cx}" cy="{cy}" r="{r}" fill="none" '
107
+ f'stroke="#E0E0E0" stroke-width="{stroke_width}"/>'
108
+ )
109
+ else:
110
+ # Draw each segment using stroke-dasharray on rotated circles.
111
+ cumulative_offset = 0.0
112
+ for seg in segments:
113
+ if seg["value"] <= 0:
114
+ continue
115
+ seg_fraction = seg["value"] / total
116
+ seg_len = circumference * seg_fraction
117
+ gap_len = circumference - seg_len
118
+ # stroke-dashoffset rotates the start; we offset by cumulative.
119
+ # SVG circles start at 3-o'clock; rotate -90 to start at 12-o'clock.
120
+ dash_offset = circumference * 0.25 - cumulative_offset
121
+ parts.append(
122
+ f'<circle cx="{cx}" cy="{cy}" r="{r}" fill="none" '
123
+ f'stroke="{seg["color"]}" stroke-width="{stroke_width}" '
124
+ f'stroke-dasharray="{seg_len:.2f} {gap_len:.2f}" '
125
+ f'stroke-dashoffset="{dash_offset:.2f}"/>'
126
+ )
127
+ cumulative_offset += seg_len
128
+
129
+ # Center label: total count
130
+ parts.append(
131
+ f'<text x="{cx}" y="{cy + 6}" text-anchor="middle" '
132
+ f'{_FONT} font-size="28" font-weight="700" fill="#212121">{total}</text>'
133
+ )
134
+
135
+ # Legend — to the right and below
136
+ legend_x = 220
137
+ legend_y = 30
138
+ row_height = 28
139
+ for seg in segments:
140
+ pct = round(seg["value"] / total * 100) if total > 0 else 0
141
+ # Color swatch
142
+ parts.append(
143
+ f'<rect x="{legend_x}" y="{legend_y - 10}" width="12" height="12" '
144
+ f'rx="2" fill="{seg["color"]}"/>'
145
+ )
146
+ # Label + value + percentage
147
+ parts.append(
148
+ f'<text x="{legend_x + 18}" y="{legend_y}" '
149
+ f'{_FONT} font-size="11" fill="#424242">'
150
+ f'{html.escape(seg["label"])} {seg["value"]} ({pct}%)</text>'
151
+ )
152
+ legend_y += row_height
153
+
154
+ parts.append("</svg>")
155
+ return "\n".join(parts)
156
+
157
+
158
+ # ---------------------------------------------------------------------------
159
+ # 3. Horizontal bar chart — object inventory
160
+ # ---------------------------------------------------------------------------
161
+
162
+ def horizontal_bar_chart(items: list[dict]) -> str:
163
+ """Return an SVG horizontal bar chart, sorted descending by value.
164
+
165
+ Args:
166
+ items: List of dicts with keys "label", "value", "color".
167
+
168
+ Returns:
169
+ SVG string.
170
+ """
171
+ sorted_items = sorted(items, key=lambda x: x["value"], reverse=True)
172
+
173
+ row_height = 30
174
+ padding_top = 10
175
+ padding_bottom = 30
176
+ label_width = 120
177
+ value_width = 50
178
+ bar_area_width = 300
179
+ total_width = 500
180
+ total_height = len(sorted_items) * row_height + padding_top + padding_bottom
181
+
182
+ max_value = max((it["value"] for it in sorted_items), default=1)
183
+ if max_value == 0:
184
+ max_value = 1
185
+
186
+ parts = [
187
+ f'<svg {_XMLNS} viewBox="0 0 {total_width} {total_height}" '
188
+ f'width="{total_width}" height="{total_height}">',
189
+ ]
190
+
191
+ for i, item in enumerate(sorted_items):
192
+ y = padding_top + i * row_height
193
+ bar_width = (item["value"] / max_value) * bar_area_width if max_value else 0
194
+ text_y = y + row_height * 0.65
195
+
196
+ # Label (right-aligned within label area)
197
+ parts.append(
198
+ f'<text x="{label_width - 8}" y="{text_y}" text-anchor="end" '
199
+ f'{_FONT} font-size="12" fill="#424242">{html.escape(item["label"])}</text>'
200
+ )
201
+ # Bar
202
+ parts.append(
203
+ f'<rect x="{label_width}" y="{y + 4}" '
204
+ f'width="{bar_width:.1f}" height="{row_height - 10}" '
205
+ f'rx="3" fill="{item["color"]}"/>'
206
+ )
207
+ # Value (after bar)
208
+ parts.append(
209
+ f'<text x="{label_width + bar_area_width + 8}" y="{text_y}" '
210
+ f'{_FONT} font-size="12" font-weight="600" fill="#424242">{item["value"]}</text>'
211
+ )
212
+
213
+ parts.append("</svg>")
214
+ return "\n".join(parts)
215
+
216
+
217
+ # ---------------------------------------------------------------------------
218
+ # 4. Stacked bar chart — horizontal segments with legend
219
+ # ---------------------------------------------------------------------------
220
+
221
+ def stacked_bar_chart(segments: list[dict]) -> str:
222
+ """Render a horizontal stacked bar with legend.
223
+
224
+ Args:
225
+ segments: List of {"label": str, "value": int, "color": hex}.
226
+ Zero-value segments are omitted.
227
+
228
+ Returns:
229
+ HTML string (div with inline stacked bar + legend), or "" if no data.
230
+ """
231
+ segments = [s for s in segments if s.get("value", 0) > 0]
232
+ if not segments:
233
+ return ""
234
+
235
+ total = sum(s["value"] for s in segments)
236
+ if total == 0:
237
+ return ""
238
+
239
+ bar_parts = []
240
+ for seg in segments:
241
+ pct = seg["value"] / total * 100
242
+ bar_parts.append(
243
+ f'<div style="background:{seg["color"]};width:{pct:.1f}%;" '
244
+ f'title="{html.escape(seg["label"])}: {seg["value"]}"></div>'
245
+ )
246
+
247
+ legend_parts = []
248
+ for seg in segments:
249
+ pct = seg["value"] / total * 100
250
+ legend_parts.append(
251
+ f'<span>'
252
+ f'<span style="display:inline-block;width:8px;height:8px;border-radius:2px;'
253
+ f'background:{seg["color"]};margin-right:4px;vertical-align:middle;"></span>'
254
+ f'{html.escape(seg["label"])}: {seg["value"]} ({pct:.0f}%)</span>'
255
+ )
256
+
257
+ return (
258
+ f'<div style="display:flex;height:20px;border-radius:4px;overflow:hidden;">'
259
+ f'{"".join(bar_parts)}</div>'
260
+ f'<div style="display:flex;justify-content:space-between;margin-top:0.35rem;'
261
+ f'font-size:0.7rem;font-family:var(--font-body);color:var(--slate-500);">'
262
+ f'{"".join(legend_parts)}</div>'
263
+ )