Documenta semana 24-27 jul: validación de prototipo (aprobada), API de Jira y avance de Etapa 1
- REGISTRO #55: validación del prototipo Etapa 0 (24-jul) APROBADA; único bloqueo = definir el flujo de facturación en Jira (sesión propuesta por Araceli para el martes 28) - REGISTRO #56: sesión de API de Jira con Pedro (27-jul) — token PAF a 1 año, bandeja FAC; + seguimiento por correo del mismo día con los límites de velocidad (65k puntos/h, burst/s, por-issue) y entrega del token por Google Drive - REGISTRO #57: hilo de WhatsApp con Erika (21-27 jul) — coordinación, envío del flujo por correo y reagenda 23→24 jul; 3 imágenes inferidas - Transcripciones y correo en fuentes/; guion de validación en planeacion/ - Avance-Etapa1-2026-07-27 (nota + mensaje para Erika) y Excel del corte del 27-jul (núcleo verificado; capa de escritura en pausa por definición de Balam) - Seguimiento-horas: sesiones del 24-jul (validación) y 27-jul (API Jira) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
"""Genera Plan-actividades-avance-2026-07-27.xlsx a partir del del 21-jul.
|
||||
Aplica las horas y estatus reales al 27-jul: sesión de reglas (22-jul) y
|
||||
validación del prototipo (24-jul, APROBADO) completadas; sesión de API de Jira
|
||||
(27-jul) en curso; capa de escritura EN PAUSA a la espera de la definición del
|
||||
flujo de facturación (sesión 28-jul con Arturo/Araceli).
|
||||
Reutiliza el estilo/semáforo del archivo del 21-jul."""
|
||||
import re
|
||||
from datetime import date
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
|
||||
|
||||
SRC = "/Users/johann/Desktop/Proyectos personales/BALAM/planeacion/Plan-actividades-avance-2026-07-21.xlsx"
|
||||
DST = "/Users/johann/Desktop/Proyectos personales/BALAM/planeacion/Plan-actividades-avance-2026-07-27.xlsx"
|
||||
HOY = date(2026, 7, 27)
|
||||
|
||||
CAFE, CREMA, GRIS_B, AMARILLO = "331F0E", "FDF3D8", "D9D9D9", "F7BD0C"
|
||||
V_FILL, V_FONT = "C6EFCE", "006100" # verde
|
||||
A_FILL, A_FONT = "FFEB9C", "9C6500" # amarillo
|
||||
R_FILL, R_FONT = "FFC7CE", "9C0006" # rojo
|
||||
G_FILL, G_FONT = "F2F2F2", "595959" # gris
|
||||
|
||||
C_PCT, C_BLQ, C_EST, C_TRAB, C_STAT = 7, 8, 9, 10, 11
|
||||
|
||||
# Prefijo de la actividad -> overrides de datos (pct=%, trab=horas, comienzo/fin=fechas texto)
|
||||
OVERRIDES = {
|
||||
"Integracion de plataformas Balam": dict(pct=0.67, trab=40),
|
||||
"Etapa 0": dict(pct=1.0, trab=23),
|
||||
"Documento de hallazgos": dict(pct=1.0),
|
||||
"Sesión de validación del prototipo": dict(pct=1.0, trab=1.05,
|
||||
comienzo="vie 24/07/26", fin="vie 24/07/26"),
|
||||
"Etapa 1": dict(pct=0.82, trab=17),
|
||||
"Demostración semanal": dict(trab=1.75),
|
||||
"Sesión de reglas y dudas": dict(pct=1.0, trab=0.80),
|
||||
"Definición de alcance Jira": dict(pct=0.40, trab=0.20),
|
||||
}
|
||||
|
||||
# Estatus a mano (gana sobre el semáforo automático): texto, fill, font, negrita
|
||||
K_ESPECIAL = {
|
||||
"Documento de hallazgos": ("✅ Completada", V_FILL, V_FONT, False),
|
||||
"Sesión de validación del prototipo": ("✅ Validado (aprobado)", V_FILL, V_FONT, True),
|
||||
"Demostración semanal": ("🟡 En curso (semanal)", A_FILL, A_FONT, False),
|
||||
"Modelo de facturas": ("🟡 En curso · falta seeder", A_FILL, A_FONT, False),
|
||||
"Capa de escritura controlada": ("🔴 En pausa · def. Balam 28-jul", R_FILL, R_FONT, True),
|
||||
"Sesión de reglas y dudas": ("✅ Completada", V_FILL, V_FONT, False),
|
||||
"Definición de alcance Jira": ("🟡 En curso · API Jira 27-jul", A_FILL, A_FONT, False),
|
||||
"Configuración de infraestructura en Azure": ("🟡 Pendiente (Balam)", A_FILL, A_FONT, False),
|
||||
"CI/CD": ("🔴 Pendiente · dep. Azure", R_FILL, R_FONT, True),
|
||||
}
|
||||
|
||||
def fecha(celda):
|
||||
m = re.search(r"(\d{2})/(\d{2})/(\d{2})", str(celda or ""))
|
||||
return date(2000 + int(m.group(3)), int(m.group(2)), int(m.group(1))) if m else None
|
||||
|
||||
def pinta(celda, fill, font_color, bold=False):
|
||||
celda.fill = PatternFill("solid", fgColor=fill)
|
||||
celda.font = Font(color=font_color, bold=bold, size=10)
|
||||
celda.alignment = Alignment(horizontal="center", vertical="center")
|
||||
|
||||
wb = openpyxl.load_workbook(SRC)
|
||||
ws = wb.active
|
||||
|
||||
# 1) Aplica overrides de datos por prefijo de nombre
|
||||
for row in range(2, ws.max_row + 1):
|
||||
nombre = str(ws.cell(row=row, column=1).value or "").strip()
|
||||
if not nombre:
|
||||
continue
|
||||
for prefijo, ov in OVERRIDES.items():
|
||||
if nombre.startswith(prefijo):
|
||||
if "pct" in ov: ws.cell(row=row, column=C_PCT, value=ov["pct"])
|
||||
if "trab" in ov: ws.cell(row=row, column=C_TRAB, value=ov["trab"])
|
||||
if "comienzo" in ov: ws.cell(row=row, column=3, value=ov["comienzo"])
|
||||
if "fin" in ov: ws.cell(row=row, column=4, value=ov["fin"])
|
||||
break
|
||||
|
||||
# 2) Recalcula el semáforo con HOY=27-jul (mismas reglas que el del 21-jul)
|
||||
for row in range(2, ws.max_row + 1):
|
||||
nombre = str(ws.cell(row=row, column=1).value or "").strip()
|
||||
if not nombre or nombre.startswith("✅") or nombre.startswith("▬"):
|
||||
continue
|
||||
es_etapa = nombre.startswith("Etapa") or nombre.startswith("Integracion")
|
||||
pct = ws.cell(row=row, column=C_PCT).value or 0
|
||||
fin = fecha(ws.cell(row=row, column=4).value)
|
||||
ini = fecha(ws.cell(row=row, column=3).value)
|
||||
stat = ws.cell(row=row, column=C_STAT)
|
||||
|
||||
if es_etapa:
|
||||
stat.value = ""
|
||||
elif pct >= 1:
|
||||
stat.value = "✅ Completada"; pinta(stat, V_FILL, V_FONT)
|
||||
elif fin and fin < HOY:
|
||||
stat.value = "🔴 Vencida"; pinta(stat, R_FILL, R_FONT, bold=True)
|
||||
elif ini and ini <= HOY:
|
||||
stat.value = "🟡 En curso"; pinta(stat, A_FILL, A_FONT)
|
||||
elif pct > 0:
|
||||
stat.value = "🟢 Adelantada"; pinta(stat, V_FILL, V_FONT)
|
||||
else:
|
||||
stat.value = "⚪ Próxima"; pinta(stat, G_FILL, G_FONT)
|
||||
|
||||
# semáforo en la celda de %
|
||||
pcel = ws.cell(row=row, column=C_PCT)
|
||||
if not es_etapa:
|
||||
if pct >= 1: pinta(pcel, V_FILL, V_FONT, bold=True)
|
||||
elif pct > 0: pinta(pcel, A_FILL, A_FONT, bold=True)
|
||||
elif fin and fin < HOY: pinta(pcel, R_FILL, R_FONT, bold=True)
|
||||
pcel.number_format = "0%"
|
||||
ws.cell(row=row, column=C_TRAB).number_format = "0.0"
|
||||
|
||||
# 3) Overrides finos de estatus (bloqueos y dependencias)
|
||||
for row in range(2, ws.max_row + 1):
|
||||
nombre = str(ws.cell(row=row, column=1).value or "").strip()
|
||||
for prefijo, (txt, fill, font, bold) in K_ESPECIAL.items():
|
||||
if nombre.startswith(prefijo):
|
||||
stat = ws.cell(row=row, column=C_STAT)
|
||||
stat.value = txt
|
||||
pinta(stat, fill, font, bold)
|
||||
break
|
||||
|
||||
# 4) Encabezado de la columna de estatus y pie
|
||||
ws.cell(row=1, column=C_STAT, value=f"Estatus (hoy {HOY.day}-jul)")
|
||||
|
||||
# 5) Reescribe leyenda/notas (borra las viejas de la línea de HOY del 21-jul)
|
||||
for row in range(ws.max_row, 1, -1):
|
||||
v = str(ws.cell(row=row, column=1).value or "")
|
||||
if v.startswith("✅ Completada ·") or v.startswith("▬ La línea roja"):
|
||||
for col in range(1, C_STAT + 1):
|
||||
ws.cell(row=row, column=col).value = None
|
||||
|
||||
ley = ws.max_row + 2
|
||||
notas = [
|
||||
("✅ Completada · 🟡 En curso · 🔴 Vencida/Pendiente · ⚪ Próxima", G_FONT, True),
|
||||
("Núcleo de la Etapa 1 construido y verificado contra producción: autenticación y roles, "
|
||||
"bitácora, multi-tenant con RLS, cliente de BIND, sincronización de clientes/facturas/"
|
||||
"cotizaciones, modelo de facturas con estados y cartera por moneda.", CAFE, False),
|
||||
("🔴 La capa de escritura (cotización→factura) queda EN PAUSA a la espera de la definición "
|
||||
"del flujo de facturación (sesión del martes 28-jul con Arturo y Araceli).", "9C0006", False),
|
||||
("API de Jira: token recibido el 27-jul; la integración inicia una vez definido el flujo.", CAFE, False),
|
||||
]
|
||||
for i, (txt, color, bold) in enumerate(notas):
|
||||
c = ws.cell(row=ley + i, column=1, value=txt)
|
||||
c.font = Font(italic=True, size=9, color=color, bold=bold)
|
||||
|
||||
ws.freeze_panes = "A2"
|
||||
ws.oddFooter.center.text = "Avance al 27-jul-2026 · Horas conforme al control local (pendiente conciliar con Jira)"
|
||||
|
||||
wb.save(DST)
|
||||
print("OK ->", DST)
|
||||
Reference in New Issue
Block a user