diff --git a/planeacion/Avance-Balam-2026-09-16.xlsx b/planeacion/Avance-Balam-2026-09-16.xlsx index 71c1620..f65ce84 100644 Binary files a/planeacion/Avance-Balam-2026-09-16.xlsx and b/planeacion/Avance-Balam-2026-09-16.xlsx differ diff --git a/planeacion/generar_avance_2026_09_16.py b/planeacion/generar_avance_2026_09_16.py index abce10f..8f848e1 100644 --- a/planeacion/generar_avance_2026_09_16.py +++ b/planeacion/generar_avance_2026_09_16.py @@ -2,7 +2,13 @@ Corte del miércoles 16-sep: sin sesiones ni desarrollo nuevos desde el 15-sep; solo se publicó el Excel de avance en Google Sheets (Drive/Balam) y se -regeneró este corte. El corte del 15-sep no se toca. Las horas se leen de +regeneró este corte. El corte del 15-sep no se toca. + +Además, a petición de Johann (16-sep), las columnas Inicio/Fin dejan de +mostrar las fechas PLAN y muestran las fechas REALES: primer y último día +trabajado de cada tarea según `Seguimiento-horas.csv`, la bitácora y los +commits ("—" = sin iniciar; las tareas en curso llevan como Fin el último día +trabajado). Las fechas plan quedan en Avance-Balam-2026-08-06b.xlsx. Las horas se leen de `Seguimiento-horas.csv`; el script aborta si el reparto no cuadra con las horas nuevas del CSV. """ @@ -61,6 +67,59 @@ ENCABEZADOS = { "Etapa 3": (E3, 0.05), } +# --- Fechas reales por fila (dd/mm/yyyy o "—") --------------------------------- +# Trazabilidad: CSV (fecha por actividad), REGISTRO.md y commits de ambos repos. +SIN_INICIAR = ("—", "—") +FECHAS_REALES = { + "Integracion de plataformas Balam": ("01/07/2026", "16/09/2026"), # en curso + "Etapa 0": ("01/07/2026", "24/07/2026"), # validada por Balam el 24-jul + "Sesión de arranque (kickoff)": ("01/07/2026", "01/07/2026"), + "Sesión de Discovery": ("06/07/2026", "07/07/2026"), # facturación 6-jul, cobranza 7-jul + "Entrega y validación de accesos": ("06/07/2026", "06/07/2026"), + "Validación técnica de la API de BIND": ("06/07/2026", "06/07/2026"), # 117 GETs, adelantada un día + "Prototipo visual navegable": ("08/07/2026", "10/07/2026"), + "Documento de hallazgos": ("10/07/2026", "10/07/2026"), # PDF + correo del 10-jul + "Sesión de validación del prototipo": ("23/07/2026", "24/07/2026"), # guion 23-jul, sesión 24-jul + "Etapa 1": ("13/07/2026", "03/09/2026"), # técnica cerrada 1-ago; publicación provisional 3-sep + "Demostración semanal": ("15/07/2026", "16/09/2026"), # gestión y cortes, en curso + "Repositorio privado GitHub": ("13/07/2026", "16/07/2026"), # push del scaffold 16-jul + "Backend base": ("13/07/2026", "19/07/2026"), # B0–B2 el 19-jul + "Arquitectura multi-tenant": ("14/07/2026", "01/08/2026"), # RLS 21-jul, verificación balam_app 1-ago + "Cliente de la API de BIND": ("15/07/2026", "15/07/2026"), + "Capa de escritura controlada": ("19/07/2026", "23/08/2026"), # diseño 19-jul; cotización 11-ago; prefactura 23-ago + "Sincronización de clientes": ("19/07/2026", "19/07/2026"), # B3 + "Configuración de infraestructura en Azure": ("03/09/2026", "03/09/2026"), # publicación provisional en paputec.mx + "Sincronización de facturas": ("21/07/2026", "01/08/2026"), # B4 21-jul; scheduler B5 1-ago + "Sesión de reglas y dudas": ("21/07/2026", "22/07/2026"), # agenda 21-jul, sesión 22-jul + "Definición de alcance Jira": ("22/07/2026", "07/08/2026"), # v1.3 aprobada 30-jul; definiciones cerradas 7-ago + "Modelo de facturas": ("21/07/2026", "01/08/2026"), # mapper 21-jul; seeder demo 1-ago + "CI/CD": ("03/09/2026", "03/09/2026"), # deploy.sh + secretos fuera del repo + "Etapa 2": ("01/08/2026", "10/09/2026"), # en curso + "» Ajuste dentro de la Etapa 2": ("27/07/2026", "03/09/2026"), # sesión con Pedro 27-jul → tickets cotizados 3-sep + "Cliente de la API de Jira": ("29/07/2026", "06/08/2026"), + "Disparador por estatus": ("20/08/2026", "07/09/2026"), # sondeo FAC-106 → folio 1026 (21-ago) → lote 7-sep + "Trazabilidad ticket": ("10/08/2026", "03/09/2026"), # definiciones → pruebas observadas + "Andamiaje del frontend": ("16/07/2026", "01/08/2026"), # scaffold 16-jul; login JWT 1-ago + "Layout base": ("01/08/2026", "06/08/2026"), + "Listado de facturas": ("01/08/2026", "01/08/2026"), + "Detalle de factura": ("01/08/2026", "01/08/2026"), # PDF; XML pendiente + "Catálogo de clientes": ("01/08/2026", "01/08/2026"), + "Tipo de cambio del DOF": SIN_INICIAR, + "Creación de cotizaciones desde la plataforma": ("06/08/2026", "07/09/2026"), # wizard UI 6-ago → lote 7-sep + "Conversión cotización→factura": ("06/08/2026", "10/09/2026"), # simulación 6-ago → captura del endpoint 10-sep + "Exportación de facturas": ("01/08/2026", "01/08/2026"), # CSV + "Pruebas integrales": SIN_INICIAR, + "Etapa 3": ("03/09/2026", "03/09/2026"), # solo endurecimiento y runbook + "Módulo de cobranza": SIN_INICIAR, + "Alertas internas": SIN_INICIAR, + "Tablero directivo": SIN_INICIAR, + "Reporte operativo": SIN_INICIAR, + "Endurecimiento de seguridad": ("03/09/2026", "03/09/2026"), + "Documentación técnica": ("03/09/2026", "03/09/2026"), + "Sesión de capacitación": SIN_INICIAR, + "Soporte posterior": SIN_INICIAR, +} + FILAS = { "Demostración semanal": (0.6, "🟡 En curso · el seguimiento pasó a Pedro (sesiones 'Seguimiento PAF' " "21, 24 y 26-ago; 3, 9 y 10-sep) · corte de horas al 16-sep, publicado en " @@ -81,6 +140,8 @@ ws["A2"] = ("Plan y avance al 16-sep-2026 · plataforma publicada en paputec.mx "desde el ticket (individual y en lote); prefactura por API bloqueada por BIND · horas del " "10-ago al 16-sep reconstruidas, pendientes de validar") ws["A2"].font = Font(size=10, italic=True, color=GRIS) +ws.cell(row=4, column=2, value="Inicio (real)") +ws.cell(row=4, column=3, value="Fin (real)") # Notas del corte anterior: se limpian antes del bucle y se reescriben abajo. primera_nota = None @@ -96,10 +157,20 @@ for row in range(5, ws.max_row + 1): tope = primera_nota if primera_nota else ws.max_row + 1 aplicado = set() +fechas_aplicadas = set() for row in range(5, tope): nombre = str(ws.cell(row=row, column=1).value or "").strip() if not nombre: continue + for prefijo, (ini, fin) in FECHAS_REALES.items(): + if nombre.startswith(prefijo): + for col, val in ((2, ini), (3, fin)): + cel = ws.cell(row=row, column=col, value=val) + cel.alignment = Alignment(horizontal="center", vertical="center") + if val == "—": + cel.font = Font(size=9, color=GRIS) + fechas_aplicadas.add(prefijo) + break for prefijo, (trab, pct) in ENCABEZADOS.items(): if nombre.startswith(prefijo): c = ws.cell(row=row, column=C_TRAB, value=round(trab, 2)) @@ -128,6 +199,8 @@ for row in range(5, tope): faltan = set(DELTAS_TRAB) - aplicado assert not faltan, f"Filas no encontradas en el Excel: {faltan}" +faltan_fechas = set(FECHAS_REALES) - fechas_aplicadas +assert not faltan_fechas, f"Filas sin fecha real aplicada: {faltan_fechas}" notas = [ ("✅ Completada · 🟡 En curso · 🔴 Pendiente/bloqueada · ⚪ Próxima · " @@ -151,6 +224,9 @@ notas = [ "interno y decidir el camino (réplica, detección al timbrado o soporte de BIND).", False), ("En espera de Balam: acceso a Azure (requisitos enviados el 25-ago), cancelación del CFDI 2386 " "y de la cotización 1026, y la definición del camino de prefactura.", False), + ("Fechas: Inicio y Fin son REALES (primer y último día trabajado según el registro de horas, la " + "bitácora y los commits); las tareas en curso llevan como Fin el último día trabajado y '—' " + "significa sin iniciar. El calendario plan original está en el corte del 6-ago.", False), ] r = primera_nota if primera_nota else ws.max_row + 2 for txt, bold in notas: