Files
presupuestos_callcenter/notebooks/.ipynb_checkpoints/01_exploracion-checkpoint.ipynb
T
2026-05-21 18:26:30 +02:00

215 lines
6.1 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "07306d98",
"metadata": {},
"source": [
"# 01 — Exploración: quotes ↔ call_center ↔ factura\n",
"\n",
"Mapa de tablas y joins en `psql_dcpublic` (BigQuery `autingo-159109`).\n",
"\n",
"## Cadena de joins\n",
"\n",
"```\n",
"tpv_authorization_tpvuser_centers (dccenter_id ∈ {159 CALL_CENTER_AURGI, 162 CALL_CENTER})\n",
" │ tpvuser_id\n",
" ▼\n",
"tpv_orders_quote.created_by_id ──► quote por agente call_center\n",
" │ order_id\n",
" ▼\n",
"tpv_orders_order ─► terminal_id ─► tpv_terminals.center_id ─► centers (centro real de facturación)\n",
" │ │ customer_id │ vehicle_id\n",
" ▼ ▼ ▼\n",
"tpv_orders_invoice (status convertido) tpv_customers (tlf) tpv_vehicles_vehicle (matrícula)\n",
"```\n",
"\n",
"Identidad cliente = `(customer_id, vehicle_id)` o (tlf, matrícula) según necesite normalización."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d2b6d545",
"metadata": {},
"outputs": [],
"source": [
"import os, sys\n",
"from google.cloud import bigquery\n",
"import pandas as pd\n",
"\n",
"PROJECT = \"autingo-159109\"\n",
"DATASET = \"psql_dcpublic\"\n",
"bq = bigquery.Client(project=PROJECT)\n",
"\n",
"def q(sql):\n",
" return bq.query(sql).to_dataframe()"
]
},
{
"cell_type": "markdown",
"id": "3238b92e",
"metadata": {},
"source": [
"## 1. Usuarios call_center"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34d656ad",
"metadata": {},
"outputs": [],
"source": [
"cc_users = q(f\"\"\"\n",
"SELECT u.id, u.name, u.email, u.is_active, u.role_id,\n",
" STRING_AGG(CAST(uc.dccenter_id AS STRING)) AS centers\n",
"FROM `{PROJECT}.{DATASET}.tpv_authorization_tpvuser` u\n",
"JOIN `{PROJECT}.{DATASET}.tpv_authorization_tpvuser_centers` uc\n",
" ON u.id = uc.tpvuser_id\n",
"WHERE uc.dccenter_id IN (159, 162)\n",
"GROUP BY 1,2,3,4,5\n",
"ORDER BY u.is_active DESC, u.id\n",
"\"\"\")\n",
"print(f\"Total usuarios call_center: {len(cc_users)} (activos: {cc_users.is_active.sum()})\")\n",
"cc_users.head(20)"
]
},
{
"cell_type": "markdown",
"id": "9ec102fb",
"metadata": {},
"source": [
"## 2. Schema quote — campos clave"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e5f94b52",
"metadata": {},
"outputs": [],
"source": [
"q(f\"\"\"\n",
"SELECT column_name, data_type\n",
"FROM `{PROJECT}.{DATASET}.INFORMATION_SCHEMA.COLUMNS`\n",
"WHERE table_name='tpv_orders_quote'\n",
"ORDER BY ordinal_position\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "32ffc1d2",
"metadata": {},
"source": [
"## 3. Distribución `status` y `accepted` (últimos 90d)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "609022a9",
"metadata": {},
"outputs": [],
"source": [
"q(f\"\"\"\n",
"SELECT status, accepted, COUNT(*) n\n",
"FROM `{PROJECT}.{DATASET}.tpv_orders_quote`\n",
"WHERE created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)\n",
" AND deleted_at IS NULL\n",
"GROUP BY status, accepted\n",
"ORDER BY n DESC\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "73c85198",
"metadata": {},
"source": [
"## 4. Conversion quote → invoice (mismo order_id)\n",
"\n",
"Una quote convierte cuando existe `tpv_orders_invoice` con el mismo `order_id`. Ese invoice fija la facturación real (NAV-sync via `nav_id`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "46378f84",
"metadata": {},
"outputs": [],
"source": [
"q(f\"\"\"\n",
"SELECT\n",
" COUNT(*) AS quotes,\n",
" COUNT(DISTINCT q.order_id) AS distinct_orders,\n",
" SUM(CASE WHEN i.id IS NOT NULL THEN 1 ELSE 0 END) AS quotes_con_invoice,\n",
" SAFE_DIVIDE(SUM(CASE WHEN i.id IS NOT NULL THEN 1 ELSE 0 END), COUNT(*)) AS conversion_rate\n",
"FROM `{PROJECT}.{DATASET}.tpv_orders_quote` q\n",
"LEFT JOIN `{PROJECT}.{DATASET}.tpv_orders_invoice` i\n",
" ON q.order_id = i.order_id\n",
"WHERE q.created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)\n",
" AND q.deleted_at IS NULL\n",
"\"\"\")"
]
},
{
"cell_type": "markdown",
"id": "df8b402c",
"metadata": {},
"source": [
"## 5. Sanity: quote por call_center vs otro\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "506744d3",
"metadata": {},
"outputs": [],
"source": [
"q(f\"\"\"\n",
"WITH cc_users AS (\n",
" SELECT DISTINCT tpvuser_id AS user_id\n",
" FROM `{PROJECT}.{DATASET}.tpv_authorization_tpvuser_centers`\n",
" WHERE dccenter_id IN (159, 162)\n",
")\n",
"SELECT\n",
" CASE WHEN cc.user_id IS NOT NULL THEN 'call_center' ELSE 'otro' END AS origen_user,\n",
" COUNT(*) AS quotes,\n",
" SUM(CASE WHEN i.id IS NOT NULL THEN 1 ELSE 0 END) AS convertidos,\n",
" ROUND(SAFE_DIVIDE(SUM(CASE WHEN i.id IS NOT NULL THEN 1 ELSE 0 END), COUNT(*)), 3) AS conv_rate\n",
"FROM `{PROJECT}.{DATASET}.tpv_orders_quote` q\n",
"LEFT JOIN cc_users cc ON q.created_by_id = cc.user_id\n",
"LEFT JOIN `{PROJECT}.{DATASET}.tpv_orders_invoice` i ON q.order_id = i.order_id\n",
"WHERE q.created_at >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 90 DAY)\n",
" AND q.deleted_at IS NULL\n",
"GROUP BY 1\n",
"\"\"\")"
]
}
],
"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.13.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}