From d9047de6fa86d2cff9d5a01b4ff66737568ef708 Mon Sep 17 00:00:00 2001 From: Johann Date: Tue, 15 Sep 2026 08:48:23 -0600 Subject: [PATCH] =?UTF-8?q?Corte=20de=20horas=20al=2015-sep=20(94.08=20h):?= =?UTF-8?q?=2039.25=20h=20del=2010-ago=20al=2015-sep=20reconstruidas=20con?= =?UTF-8?q?=20evidencia=20y=20Excel=20de=20avance;=20seis=20sesiones=20sin?= =?UTF-8?q?=20bit=C3=A1cora=20listadas=20como=20huecos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Seguimiento-horas.csv: 30 filas nuevas (sesiones 'Seguimiento PAF' del 21, 24 y 26-ago y 3, 9 y 10-sep acotadas por los informes de Read AI; bloques de desarrollo por commits y mtimes; comunicación con Pedro y Noé). Marcadas `reconstruida` salvo la sesión del 12-ago (transcript). Actividades nuevas E1-09, E2-02, E2-03, E3-01, E3-02. Etapa 1 32.25 h, Etapa 2 23.75 h, ajuste Jira 14.75 h (rebasa las 7–10 aprobadas), Etapa 3 1.50 h. - Avance-Balam-2026-09-15.xlsx generado desde generar_avance_2026_09_15.py (parte del corte 06b; el reparto por fila aborta si no cuadra con el CSV): publicación provisional en paputec.mx, cotización individual y en lote, prefactura por API bloqueada por BIND. - Seguimiento-horas.md: sección del corte y criterios de la reconstrucción. - PENDIENTES.md: huecos de registro del corte (seis sesiones sin REGISTRO, publicación del 3-sep y lote del 7-sep sin registrar, validación de horas, correos de Noé del 24-ago). Co-Authored-By: Claude Fable 5.1 --- bitacora/PENDIENTES.md | 9 +- planeacion/Avance-Balam-2026-09-15.xlsx | Bin 0 -> 11007 bytes planeacion/Seguimiento-horas.csv | 30 +++ planeacion/Seguimiento-horas.md | 21 +- planeacion/generar_avance_2026_09_15.py | 253 ++++++++++++++++++++++++ 5 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 planeacion/Avance-Balam-2026-09-15.xlsx create mode 100644 planeacion/generar_avance_2026_09_15.py diff --git a/bitacora/PENDIENTES.md b/bitacora/PENDIENTES.md index 130d413..a1146cc 100644 --- a/bitacora/PENDIENTES.md +++ b/bitacora/PENDIENTES.md @@ -2,7 +2,14 @@ Acciones vivas del proyecto. Formato: `[ ]` abierta · `[x]` cerrada (no se borran, dejan rastro). Cada una con responsable y, si aplica, fecha. Ver contexto en [REGISTRO.md](REGISTRO.md). -_Última actualización: **2026-08-21, mediodía** — ⭐ primera cotización real emitida (folio 1026; la 2.ª, corregida, pendiente de confirmar). Anterior: **2026-08-20, noche.** Cruce completo del buzón contra la bitácora (MCP ms365): se incorporaron 9 comunicaciones faltantes y se corrigieron 2 errores de registro. **Hay sesión mañana viernes 21-ago, 7:00 am** con Noé, Ara y Pedro sobre el formulario modificado y `FAC-106`. Ver [REGISTRO #65](REGISTRO.md)–[#68](REGISTRO.md)._ +_Última actualización: **2026-09-15** — corte de horas 10-ago→15-sep reconstruido y huecos de registro listados (seis sesiones sin bitácora). Anterior: **2026-08-21, mediodía** — ⭐ primera cotización real emitida (folio 1026; la 2.ª, corregida, pendiente de confirmar). Anterior: **2026-08-20, noche.** Cruce completo del buzón contra la bitácora (MCP ms365): se incorporaron 9 comunicaciones faltantes y se corrigieron 2 errores de registro. **Hay sesión mañana viernes 21-ago, 7:00 am** con Noé, Ara y Pedro sobre el formulario modificado y `FAC-106`. Ver [REGISTRO #65](REGISTRO.md)–[#68](REGISTRO.md)._ + +## 🚨 Huecos de registro (detectados en el corte del 15-sep) + +- [ ] 🚨 **Seis sesiones con Balam sin entrada en REGISTRO.md** (evidencia: convocatorias de Pedro e informes de Read AI en el buzón): **21-ago 1:00 pm** "Seguimiento - PAF (2)" (homologación de estados del flujo; pendiente prueba de escritura en Jira), **24-ago 7:00 am** (validación cotización→prefactura MXN/USD, IVA 16 %/0 %; Noé condiciona Azure a que las pruebas funcionen), **26-ago 7:00 am** (permisos y flujo remisión/prefactura/factura; el POST se timbró en vivo → [#70](REGISTRO.md)), **3-sep 7:00 am** (datos del tenant de Azure; conceptos de Acuntia por headcount; definición: ítem por código y concepto = título del ticket) y **1:30 pm** (tres tickets de Pedro cotizados desde la plataforma publicada), **9-sep 1:00 pm** "Seguimiento PAF - Prefactura" (Araceli crea una prefactura en la UI de BIND con "Generar venta" mientras se capturan las peticiones: `InvoiceDetails`), **10-sep 1:00 pm** (con Pedro: cotización 1078 de Acuntia y captura de la petición de red de la prefactura). +- [ ] 📝 **Registrar la publicación del 3-sep** (https://paputec.mx/balam/, runbook en `balam-plataforma/deploy/paputec/README.md`) y la **cotización en lote del 7-sep** — hoy solo constan en el CLAUDE.md del repo del cliente y en los commits `03582af`, `ed4c819`, `fbdbd18` (pusheados el 15-sep). +- [ ] ⏱️ **Validar las 39.25 h reconstruidas** del 10-ago al 15-sep en `../planeacion/Seguimiento-horas.csv` (todas marcadas `reconstruida`, con la evidencia en cada fila) y decidir a quién se reporta el corte ahora que el seguimiento es con Pedro. Excel listo: `../planeacion/Avance-Balam-2026-09-15.xlsx`. +- [ ] 📧 **Correos de Noé del 24-ago sin registrar:** "Re: Seguimiento FAC-106" (explica que la prefactura se genera con *Generar venta* en Acciones) y "Acceso a Azure Balam y permisos" (pide los requisitos exactos; Johann respondió el 25-ago con suscripción + grupo de recursos + Contributor). ## 🔥🔴 26-ago — incidente del timbrado y cierre de la investigación ([REGISTRO #70](REGISTRO.md)) diff --git a/planeacion/Avance-Balam-2026-09-15.xlsx b/planeacion/Avance-Balam-2026-09-15.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..985c643663f512bcababae89c26d27cc9a054e70 GIT binary patch literal 11007 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 "2026-08-06": + nuevas += h + +E0, E1, E3 = por_etapa["0"], por_etapa["1"], por_etapa["3"] +AJ = por_act["AJ-01"] # ajuste Jira→BIND (vive dentro de la etapa 2 del CSV) +E2 = por_etapa["2"] - AJ # Etapa 2 propiamente (frontend + emisión) +TOTAL = E0 + E1 + E2 + AJ + E3 +assert abs(TOTAL - sum(por_etapa.values())) < 0.01 +assert abs(TOTAL - CORTE_ANTERIOR - nuevas) < 0.01, "El CSV no arranca del corte del 6-ago" +PCT_GLOBAL = round(TOTAL / ((119 + 146) / 2), 2) + +# --- Reparto por fila de las horas nuevas (10-ago → 15-sep) -------------------- +# Trazabilidad CSV → fila del Excel: +# E1-05 +4.50 (bitácora, cruce del buzón, WhatsApp con Pedro, correo Azure, +# corte de horas) → "Demostración semanal + reporte de horas" (gestión) +# E1-09 +2.50 (publicación en paputec.mx) → 2.25 a "Configuración de +# infraestructura en Azure" (ambiente provisional) y 0.25 a "CI/CD" +# (deploy.sh reproducible + secretos fuera del repo) +# AJ-01 +9.25 → 4.50 a "Disparador…" (sondeo FAC-106 + cableado 20-ago 1.50, +# investigación hasta el folio 1026 el 21-ago 3.00) y 4.75 a +# "Trazabilidad… y prueba observada" (definiciones 10-ago 1.50, sesión +# 12-ago 1.00, Excel de campos 0.75, sesiones 21-ago 0.75 y 3-sep 0.75) +# E2-02 +8.00 (capa de escritura de cotización 11/12-ago 4.50, ítem por +# código 3-sep 1.50, lote 7-sep 2.00) → "Creación de cotizaciones" +# E2-03 +13.50 (prefactura 23-ago, prefactura→factura 25-ago, incidente e +# investigación 26-ago, sesiones 24 y 26-ago, 9 y 10-sep) → +# "Conversión cotización→factura" +# E3-01 +1.00 → "Endurecimiento de seguridad"; E3-02 +0.50 → "Documentación técnica" +DELTAS_TRAB = { + "Demostración semanal": 4.50, + "Configuración de infraestructura en Azure": 2.25, + "CI/CD": 0.25, + "Disparador por estatus": 4.50, + "Trazabilidad ticket": 4.75, + "Creación de cotizaciones desde la plataforma": 8.00, + "Conversión cotización→factura": 13.50, + "Endurecimiento de seguridad": 1.00, + "Documentación técnica": 0.50, +} +assert abs(sum(DELTAS_TRAB.values()) - nuevas) < 0.01, ( + f"El reparto ({sum(DELTAS_TRAB.values()):.2f}) no suma las {nuevas:.2f} h nuevas del CSV") + +ENCABEZADOS = { + "Integracion de plataformas Balam": (TOTAL, PCT_GLOBAL), + "Etapa 0": (E0, 1.0), + "Etapa 1": (E1, 0.95), + "Etapa 2": (E2, 0.70), + "» Ajuste dentro de la Etapa 2": (AJ, 0.85), + "Etapa 3": (E3, 0.05), +} + +# (pct, estatus, fill, font, bold) — solo lo que cambió respecto al 6-ago. +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 15-sep", + A_FILL, A_FONT, False), + "Capa de escritura controlada": (0.9, "✅ Implementada: dry-run + confirmación humana + auditoría en " + "WriteOperations para cotización (21-ago) y prefactura (23-ago) · " + "el timbrado no existe en el API de BIND (es humano, en su pantalla)", + V_FILL, V_FONT, False), + "Configuración de infraestructura en Azure": (0.5, "🟡 Publicada en https://paputec.mx/balam/ (3-sep) como " + "ambiente provisional · Azure sigue con Balam (requisitos " + "enviados a Noé el 25-ago; datos del tenant revisados el 3-sep)", + A_FILL, A_FONT, False), + "CI/CD": (0.3, "🟡 Publicación reproducible (deploy.sh) con secretos fuera del repo · CI real depende de Azure", + A_FILL, A_FONT, False), + "Disparador por estatus": (0.6, "🟡 Cotización real desde el ticket (21-ago, folio 1026) y en lote (7-sep), " + "con disparo manual · el disparo automático por estatus espera el ambiente definitivo", + A_FILL, A_FONT, False), + "Trazabilidad ticket": (0.6, "🟡 Vínculo ticket→cotización→prefactura en la BD · pruebas observadas con " + "Balam el 12, 21, 24 y 26-ago y el 3-sep", + A_FILL, A_FONT, False), + "Creación de cotizaciones desde la plataforma": (0.9, "✅ Cotización individual y en lote con dry-run y " + "confirmación humana · ítem del catálogo BIND por código y " + "concepto = título del ticket (definición del 3-sep)", + V_FILL, V_FONT, False), + "Conversión cotización→factura": (0.6, "🔴 Prefactura por API bloqueada por BIND: IsFiscalInvoice=true " + "TIMBRA al crear (incidente 26-ago, CFDI 2386) y false produce remisión; " + "el tipo Prefactura solo existe en su UI · en curso la captura del " + "endpoint interno (sesiones 9 y 10-sep)", + R_FILL, R_FONT, True), + "Endurecimiento de seguridad": (0.4, "🟡 Aplicado en la publicación: contenedor de solo lectura, rate limit, " + "bloqueo de login, CSP/HSTS, respaldos diarios", + A_FILL, A_FONT, False), + "Documentación técnica": (0.3, "🟡 Runbook de publicación, operación y rollback (deploy/paputec/README.md)", + A_FILL, A_FONT, False), +} + + +def pinta(celda, fill, font_color, bold=False, size=9, align="left"): + celda.fill = PatternFill("solid", fgColor=fill) + celda.font = Font(color=font_color, bold=bold, size=size) + celda.alignment = Alignment(horizontal=align, vertical="center", wrap_text=True) + + +wb = openpyxl.load_workbook(SRC) +ws = wb.active + +ws["A2"] = ("Plan y avance al 15-sep-2026 · plataforma publicada en paputec.mx (provisional), cotización real " + "desde el ticket (individual y en lote); prefactura por API bloqueada por BIND · horas del " + "10-ago al 15-sep reconstruidas, pendientes de validar") +ws["A2"].font = Font(size=10, italic=True, color=GRIS) + +# Las notas del corte anterior van fusionadas A:G y algunas empiezan con +# "Etapa 1: …", que colisiona con los prefijos de encabezado: se localizan y +# limpian ANTES del bucle principal, y este se detiene donde empezaban. +primera_nota = None +for row in range(5, ws.max_row + 1): + v = str(ws.cell(row=row, column=1).value or "") + if v.startswith("✅ Completada ·"): + primera_nota = row + if primera_nota and row >= primera_nota: + for rango in list(ws.merged_cells.ranges): + if rango.min_row == row: + ws.unmerge_cells(str(rango)) + ws.cell(row=row, column=1).value = None +tope = primera_nota if primera_nota else ws.max_row + 1 + +aplicado = set() +for row in range(5, tope): + nombre = str(ws.cell(row=row, column=1).value or "").strip() + if not nombre: + continue + + for prefijo, (trab, pct) in ENCABEZADOS.items(): + if nombre.startswith(prefijo): + if trab is not None: + c = ws.cell(row=row, column=C_TRAB, value=round(trab, 2)) + c.number_format = "0.00" + p = ws.cell(row=row, column=C_PCT, value=pct) + p.number_format = "0%" + if pct >= 1: + pinta(p, V_FILL, V_FONT, bold=True, size=10, align="center") + elif pct > 0: + pinta(p, A_FILL, A_FONT, bold=True, size=10, align="center") + break + + for prefijo, delta in DELTAS_TRAB.items(): + if nombre.startswith(prefijo): + actual = ws.cell(row=row, column=C_TRAB).value + actual = float(actual) if isinstance(actual, (int, float)) else 0.0 + c = ws.cell(row=row, column=C_TRAB, value=round(actual + delta, 2)) + c.number_format = "0.00" + aplicado.add(prefijo) + break + + for prefijo, (pct, txt, fill, fcolor, bold) in FILAS.items(): + if nombre.startswith(prefijo): + if pct is not None: + p = ws.cell(row=row, column=C_PCT, value=pct) + p.number_format = "0%" + if pct >= 1: + pinta(p, V_FILL, V_FONT, bold=True, size=10, align="center") + elif pct > 0: + pinta(p, A_FILL, A_FONT, bold=True, size=10, align="center") + else: + p.font = Font(size=10, color=GRIS) + s = ws.cell(row=row, column=C_STAT, value=txt) + pinta(s, fill, fcolor, bold) + break + +faltan = set(DELTAS_TRAB) - aplicado +assert not faltan, f"Filas no encontradas en el Excel: {faltan}" + +# --- Notas: se escribe el bloque del 15-sep donde estaba el del 6-ago --------- +notas = [ + ("✅ Completada · 🟡 En curso · 🔴 Pendiente/bloqueada · ⚪ Próxima · " + "(adelantada) = ejecutada antes de su fecha plan", True), + (f"Horas trabajadas al 15-sep: Etapa 0 {E0:.2f} h (cerrada y validada) · Etapa 1 {E1:.2f} h " + f"(rango 32–39) · Etapa 2 {E2:.2f} h · ajuste Jira {AJ:.2f} h (de 7–10 aprobadas) · " + f"Etapa 3 {E3:.2f} h · total {TOTAL:.2f} h. Las {nuevas:.2f} h posteriores al corte del 6-ago " + "están reconstruidas con evidencia (commits, correos, informes de reunión) y pendientes de " + "validar. Base de facturación a $600/h + IVA.", True), + ("Etapa 1: la capa de escritura quedó implementada (cotización y prefactura con dry-run, " + "confirmación humana y auditoría). Solo Azure y CI/CD siguen dependiendo de Balam; mientras " + "tanto la plataforma está publicada en https://paputec.mx/balam/ desde el 3-sep (BIND y Jira " + "en solo lectura fuera de sesión).", False), + ("Integración Jira → BIND: primera cotización real desde un ticket el 21-ago (folio 1026, tras " + "5 intentos por dos semánticas indocumentadas del API: Type=2 y VAT como tasa), tres tickets " + "cotizados en la sesión del 3-sep y cotización en lote desde el 7-sep. Rebasa las 7–10 h " + "aprobadas por las semánticas indocumentadas y las sesiones acompañadas (12, 21-ago, 3-sep).", False), + ("Etapa 2: la prefactura por API NO es posible con lo que BIND expone (26-ago: IsFiscalInvoice=true " + "timbra al crear —CFDI 2386, a cancelar— y false produce remisión; el tipo Prefactura solo " + "existe en su UI). Sesiones del 9 y 10-sep con Araceli y Pedro para capturar el endpoint " + "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), +] +r = primera_nota if primera_nota else ws.max_row + 2 +for txt, bold in notas: + c = ws.cell(row=r, column=1, value=txt) + c.font = Font(italic=True, size=9, color=CAFE, bold=bold) + c.alignment = Alignment(wrap_text=True, vertical="top") + try: + ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=7) + except ValueError: + pass # ya estaba fusionada desde el archivo origen + ws.row_dimensions[r].height = 40 if len(txt) > 220 else (28 if len(txt) > 120 else 14) + r += 1 + +ws.print_area = f"A1:G{r}" +wb.save(DST) + +print("OK ->", DST) +print(f" E0 {E0:.2f} · E1 {E1:.2f} · E2 {E2:.2f} · Jira {AJ:.2f} · E3 {E3:.2f} · TOTAL {TOTAL:.2f} h " + f"({nuevas:.2f} nuevas) · avance global {PCT_GLOBAL:.0%}")