Análisis de Solicitud de Material
Página 1 de streamlit-reportes.
Rediseñado 2026-08-31 (ver "Historial" al final) — pasó de dos queries agregadas independientes a una sola query base a grano línea, de la que se derivan en pandas tanto los KPIs/agregados como el detalle.
Conteo de solicitudes de material dadas de alta por operador, con evolución mensual, más una tabla de detalle a nivel línea con surtido, tipo de gasto, equipo y origen de la solicitud.
Grano y fuente
Query base a grano línea (Sm_Folio, Sm_ID), de la que se derivan
todos los agregados. Fuente: TRIVASADB (.207), ZTRV_Solicitud_Material
+ ZTRV_Solicitud_Material_Detalle, más joins a Tipo_Gasto, Sucursal,
Equipo, Orden_Servicio y ZTRV_SOLICITUD_MATERIA_DOCUMENTO (surtido).
⚠️ Advertencia de grano, la razón de este rediseño: una fila del
DataFrame base = una línea, no una solicitud. Un folio con N líneas
aparece N veces. Cualquier métrica de "solicitudes" debe usar
Sm_Folio.nunique(), nunca len(df)/COUNT(*) sobre este resultado
— mezclar esto infla el conteo por el promedio de líneas por folio (dato
real, 2026: 21,415 líneas / 8,704 solicitudes ≈ 2.46 líneas/folio).
Query base
queries/base_solicitud_material_linea.sql
en streamlit-reportes (parametrizada con :anio). Reemplaza las dos
queries previas (solicitudes_por_operador.sql,
solicitudes_por_operador_mensual.sql), que quedan huérfanas en el repo
pendientes de borrar tras confirmar visualmente el reporte.
De dónde sale cada columna
| Columna | Origen | Nota |
|---|---|---|
Sm_Folio, Sm_ID |
PK cabecera + PK detalle | |
producto |
Sm_Concepto |
|
cantidad_solicitada |
Sm_Cantidad_Control_1 (Detalle) |
Confirmado con el usuario: es lo pedido — no Sm_Cantidad_1. |
cantidad_surtida |
SUM(Smd_Cantidad) de ZTRV_SOLICITUD_MATERIA_DOCUMENTO, Estatus<>'CA' |
Misma lógica que ya usa el reporte 3 (Solicitud de Material - Detalle) — confirmada contra la consulta nativa del ERP ZTRV_SOLICITUD_SURTIDO (ver "Consultas internas del ERP" abajo). |
fecha_surtido |
MAX(Mv_Fecha) de Movimiento, join ZTRV_SOLICITUD_MATERIA_DOCUMENTO.Smd_Documento = Movimiento.Mv_Folio AND Smd_Tabla='MOVIMIENTO' AND Smd_Producto = Mv_Cve_Producto |
Ninguna de las dos tablas de solicitud (cabecera ni detalle) trae fecha de surtido propia — sale de Movimiento, la única fuente real. NULL si la línea aún no se surte. |
tipo_gasto |
Tipo_Gasto.Tg_Descripcion vía det.Tg_Cve_Tipo_Gasto |
|
origen |
CASE: Tg_Cve_Tipo_Gasto='' → ORDEN_SERVICIO; Sm_Materia_Prima=1 → MATERIA_PRIMA; si no, CONSUMO_INTERNO |
Replica el filtro real de las consultas internas del módulo (ZTRV_SOLICITUD_DETALLADA / _PP, ver abajo) — el ERP distingue estas 3 modalidades de captura de una solicitud. |
tipo |
Sm_Es_Servicio → SERVICIO/MATERIAL |
Distinto de origen — dice si la línea es material físico o un servicio, no de dónde vino la solicitud. |
usuario |
Oper_Alta (cabecera) |
Usuario del sistema, no nombre de persona. |
fecha_solicitud |
Sm_Fecha (cabecera) |
Confirmado: fecha de creación, no Fecha_Alta genérica (ambas existen en cabecera, ver Solicitud de material). |
Sc_Cve_Sucursal, sucursal |
Sucursal.Sc_Descripcion |
|
estado_detalle |
Es_Cve_Estado (Detalle) |
No hereda el de cabecera, diverge con frecuencia (ver Calidad de datos). |
equipo |
Eq_Cve_Equipo + ' - ' + Eq_UserDef_1 |
Eq_UserDef_1 es donde vive la descripción real del equipo (no existe columna Eq_Descripcion) — confirmado con datos reales, ej. "0000000253 - DOLLY ATRO 2018 SUSP NEU 20 TON". COALESCE de dos caminos: directo (sm.Eq_Cve_Equipo) o heredado de Orden_Servicio.Os_Equipo vía sm.Os_Folio (replica el patrón real del módulo: una solicitud puede originarse de una Orden de Servicio que ya trae equipo ligado — rama ORDEN_SERVICIO de origen). |
El Streamlit
Código: pages/1_Analisis_de_Solicitud_de_Material.py.
- Filtro: año (
st.number_input, default año en curso). - KPIs (en este orden): total de solicitudes (
Sm_Foliodistintos), operadores distintos (usuariodistintos), total de líneas (len(df), nuevo en este rediseño). - Tabla y gráfica agregadas por operador/mes: igual que antes (barras
apiladas Altair, top 15 operadores + "Otros"), ahora derivadas del
DataFrame base con
groupby+Sm_Folio.nunique(), en vez de una segunda query. - Tabla base de detalle (grano línea, todas las columnas de arriba): movida al final de la página, como drill-down después de los agregados (antes era el único contenido de la página).
- Una sola query cacheada (
@st.cache_data(ttl=600)), no dos.
Validado con streamlit.testing.v1.AppTest dentro del contenedor de
producción (usuarios-sm-streamlit), contra .207 en vivo, dos años
distintos, sin excepciones — ver "Historial".
Consultas internas del ERP usadas para diseñar esta versión
Nota de vocabulario: estas no son reportes — son las queries que usan las pantallas de captura de los módulos para operar (búsquedas, combos, validaciones), guardadas en
EMPRESAS_2.dbo.Consultas(1,333 filas). Es una tabla distinta deTRIVASADB3.dbo.Consultas(58 filas) ya documentada en Reportes nativos como parte del patrón B de almacenamiento de SQL — mismo nombre de tabla, misma columnaSQL(ntext), pero viven en bases distintas con contenido distinto. No confundir una con la otra.
ZTRV_SOLICITUD_SURTIDO("CONSULTA DE SURTIDO DE SOLICITUD DE REFACCIONES") — confirma queZTRV_SOLICITUD_MATERIA_DOCUMENTO(join aMovimiento) es la fuente correcta de cantidad y fecha de surtido.ZTRV_SOLICITUD_DETALLADA— variante conWHERE Tg_Cve_Tipo_Gasto = ''(rama Orden de Servicio, equipo heredado víaEquipo_Orden←Orden_Servicio.Os_Equipo).ZTRV_SOLICITUD_DETALLADA_PP— variante conWHERE (Tg_Cve_Tipo_Gasto <> '' OR Sm_Materia_Prima = '1')(ramas Consumo Interno y Materia Prima, agrupadas por el mismo filtro — el sistema las trata igual, no como ramas independientes).
Pendiente
- Confirmar con un caso real que el fallback de
equipovíaOrden_Serviciotrae datos — la validación de esta sesión solo tocó foliosCONSUMO_INTERNOcon equipo directo. - Decidir si
apartado/existencia/requisicion(columnas ya presentes en el reporte 3) hacen falta aquí — descartadas por ahora, fuera de foco para un reporte "por usuario".
Historial
- 2026-08-31: rediseño completo — de dos queries agregadas (grano
cabecera) a una query base a grano línea con
cantidad_solicitada,cantidad_surtida,fecha_surtido,tipo_gasto,origen,tipo,sucursal,estado_detalle,equipo. KPI nuevo: total de líneas. Tabla de detalle movida al final. Ver commits deanalisis-usuario-sm(proyectos-bi) para el detalle de la sesión de diseño. Commiteado y pusheado enstreamlit-reportes(5283075). - 2026-08-31: borradas
queries/solicitudes_por_operador.sqlyqueries/solicitudes_por_operador_mensual.sql— huérfanas desde el rediseño de arriba, confirmado sin referencias enpages/*.py(8818324).