2.5.0: las grabaciones bajan hasta el día de rodaje
El año y el mes salían de la fecha de cada archivo desde 2.2.0, pero dentro
del mes iba todo junto: en Camilo, 13 días de rodaje y 907 archivos en la
misma carpeta.
- Nueva variable {dia} («15- Viernes», como los meses) en las plantillas de
grabación de los cuatro tipos de trabajo, con migración de las guardadas.
- Plan._dias_de_rodaje() cuenta los días distintos por mes y dia_de()
devuelve "" cuando el mes tuvo un solo rodaje: la carpeta del día solo
aparece donde hace falta. David Reyes la necesita en 1 de 8 meses,
Danney en 36 de 57, Camilo en 12 de 26. 186 grupos, cero colisiones.
- Un archivo de cámara suelto también se archiva por su propia fecha:
plan_archivo hacía «if mes: fm = mes» y se saltaba la regla de 2.2.0.
- «¿Dónde va a parar este archivo?» dice también el día.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Este commit está contenido en:
@@ -37,7 +37,7 @@ import actualizador
|
||||
asistente.O = sys.modules[__name__]
|
||||
actualizador.O = sys.modules[__name__]
|
||||
|
||||
VERSION = "2.4.0"
|
||||
VERSION = "2.5.0"
|
||||
|
||||
CONGELADO = getattr(sys, "frozen", False)
|
||||
SIN_VENTANA = getattr(subprocess, "CREATE_NO_WINDOW", 0) # ffmpeg/ffprobe/net sin abrir consolas negras # empaquetado como .exe con PyInstaller
|
||||
@@ -264,6 +264,9 @@ for t, d in R.PLANTILLAS.items():
|
||||
# los proyectos pasaron a separarse por programa: «01_Proyectos/{nombre}» -> «01_Proyectos/{app}/{nombre}»
|
||||
if b == "PROYECTOS" and PLANTILLAS[t][b] == p.replace("{app}/", ""):
|
||||
PLANTILLAS[t][b] = p
|
||||
# y las grabaciones, por día de rodaje cuando el mes tiene más de uno
|
||||
if b in ("GRABACION", "CELULAR") and PLANTILLAS[t][b] == p.replace("{dia}/", ""):
|
||||
PLANTILLAS[t][b] = p
|
||||
guardar_json(PLANTILLAS_PATH, PLANTILLAS)
|
||||
|
||||
|
||||
@@ -627,6 +630,7 @@ def destino_plantilla(tipo, cubeta, **kw):
|
||||
"anio": str(anio) if anio else "",
|
||||
"mes": R.nombre_mes(mes) if mes else "",
|
||||
"nombre": kw.get("nombre", ""),
|
||||
"dia": kw.get("dia", ""),
|
||||
"sub": kw.get("sub", ""),
|
||||
"rel": kw.get("rel", ""),
|
||||
"fuente": kw.get("fuente", ""),
|
||||
@@ -665,6 +669,31 @@ class Plan:
|
||||
self.sueltos = defaultdict(list) # (cubeta, destino, motivo, confianza) -> archivos
|
||||
self.con = db()
|
||||
self.avisos = []
|
||||
self.dias_mes = self._dias_de_rodaje()
|
||||
|
||||
def _dias_de_rodaje(self):
|
||||
"""Para cada mes, los días distintos en que se grabó algo en esta carpeta de cliente.
|
||||
|
||||
Sirve para decidir si el mes necesita carpetas por día. Medido el 16-sep-2026 sobre el material
|
||||
real: David Reyes tiene un solo día de rodaje en 7 de sus 8 meses (ahí la carpeta del día sería
|
||||
estorbo), mientras que Danney tiene 36 meses con varios días y Camilo llega a 13 días distintos
|
||||
en un mismo mes, 907 archivos mezclados en la misma carpeta."""
|
||||
dias = defaultdict(set)
|
||||
for f in self.con.execute(
|
||||
"SELECT fecha FROM archivos WHERE raiz = ? AND es_basura = 0 AND es_proxy = 0 AND rol IN "
|
||||
"('camara_raw','camara_video','camara_sidecar','audio_grabado','celular_video')", (self.raiz,)):
|
||||
f0 = f["fecha"]
|
||||
try:
|
||||
dias[(int(f0[:4]), int(f0[5:7]))].add(f0)
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
return dias
|
||||
|
||||
def dia_de(self, fecha, anio, mes):
|
||||
"""El nombre de la carpeta del día, o "" si en ese mes solo se grabó un día: entonces sobra."""
|
||||
if len(self.dias_mes.get((anio, mes), ())) < 2:
|
||||
return ""
|
||||
return R.nombre_dia(fecha)
|
||||
|
||||
# ---- helpers ----
|
||||
def rel(self, ruta):
|
||||
@@ -1039,7 +1068,7 @@ class Plan:
|
||||
hoy = datetime.date.today()
|
||||
if (ay, am) > (hoy.year, hoy.month):
|
||||
ay -= 1
|
||||
grupos[(ay, am, fuente, fconf)].append((f["ruta"], f["bytes"]))
|
||||
grupos[(ay, am, self.dia_de(f["fecha"], ay, am), fuente, fconf)].append((f["ruta"], f["bytes"]))
|
||||
etiqueta = "" if generico else R.etiqueta_grabacion(nombre)
|
||||
aviso_fecha = ""
|
||||
# hace falta que discrepe una parte de verdad: un archivo suelto traspapelado no debe dejar
|
||||
@@ -1052,13 +1081,16 @@ class Plan:
|
||||
self.avisos.append(f"«{self.rel(e.path)}» está dentro de {R.nombre_mes(mes)} de {anio}, pero {cuantos} de "
|
||||
f"sus archivos se grabaron en {R.nombre_mes(dm)} de {da}. Se archivan en el mes en que "
|
||||
f"se grabaron, no en el que dice la carpeta.")
|
||||
for (ay, am, fuente, fconf), archivos in grupos.items():
|
||||
for (ay, am, dia, fuente, fconf), archivos in grupos.items():
|
||||
sub = fuente if not etiqueta else os.path.join(etiqueta, fuente)
|
||||
destino = destino_plantilla(self.tipo, "GRABACION", anio=ay, mes=am, sub=sub, nombre=limpiar_nombre(nombre))
|
||||
destino = destino_plantilla(self.tipo, "GRABACION", anio=ay, mes=am, dia=dia, sub=sub,
|
||||
nombre=limpiar_nombre(nombre))
|
||||
# si todos ya están en esa carpeta, no hay nada que hacer
|
||||
if all(os.path.normpath(os.path.dirname(a[0])).lower() == self.abs_(destino).lower() for a in archivos):
|
||||
continue
|
||||
mot = motivo + (" · repartido por fuente" if anio and mes else " · mes por la fecha de cada archivo" + (" (fecha de modificación)" if fconf == "baja" else ""))
|
||||
if dia:
|
||||
mot += " · y por día, que ese mes hubo varios rodajes"
|
||||
self.agregar(e.path, self.abs_(destino), "GRABACION", "mover archivos", mot + aviso_fecha, fconf,
|
||||
archivos=archivos)
|
||||
|
||||
@@ -1078,7 +1110,17 @@ class Plan:
|
||||
if anio and fila["fecha_origen"] == "mtime":
|
||||
fa = anio
|
||||
if mes:
|
||||
fm = mes
|
||||
# el archivo manda sobre la carpeta cuando su propia fecha es de fiar, igual que dentro de una
|
||||
# carpeta de grabación: si no, un clip de diciembre traspapelado en la carpeta de marzo se
|
||||
# quedaba archivado en marzo, que es justo lo que 2.2.0 dejó de hacer con las grabaciones.
|
||||
if _discrepa_mes(fila["fecha"], fila["fecha_origen"], anio or fa, mes):
|
||||
if fila["fecha_origen"] == "nombre+mtime" and anio:
|
||||
fa = anio if fm <= mes else anio - 1 # el nombre de la cámara no trae año
|
||||
conf = "media"
|
||||
motivo += (f" · la carpeta dice {R.nombre_mes(mes)} y el archivo se grabó en "
|
||||
f"{R.nombre_mes(fm)}: manda el archivo")
|
||||
else:
|
||||
fm = mes
|
||||
elif fila["fecha_origen"] == "mtime":
|
||||
conf = "baja"
|
||||
motivo += " · mes por fecha de modificación"
|
||||
@@ -1114,7 +1156,8 @@ class Plan:
|
||||
elif cub == "PROYECTOS":
|
||||
destino = destino_plantilla(self.tipo, "PROYECTOS", app=sub)
|
||||
else:
|
||||
destino = destino_plantilla(self.tipo, cub, anio=fa, mes=fm, sub=sub, nombre="")
|
||||
destino = destino_plantilla(self.tipo, cub, anio=fa, mes=fm, sub=sub, nombre="",
|
||||
dia=self.dia_de(fila["fecha"], fa, fm) if cub in ("GRABACION", "CELULAR") else "")
|
||||
self.suelto(fila, cub, destino, motivo, conf)
|
||||
|
||||
def plan_basura(self):
|
||||
@@ -2864,6 +2907,7 @@ def _plural(n, uno, varios):
|
||||
EJEMPLO_VAR = {
|
||||
"anio": ("2026", "el año del material"),
|
||||
"mes": ("09- Septiembre", "el mes del material"),
|
||||
"dia": ("15- Viernes", "el día en que se grabó, y solo si ese mes hubo más de un rodaje"),
|
||||
"nombre": ("Nombre de la pieza", "el nombre de la pieza o de la carpeta"),
|
||||
"fuente": ("URSA_BRAW", "la cámara de la que salió"),
|
||||
"app": ("Premiere", "el programa que abre el proyecto"),
|
||||
@@ -3010,7 +3054,10 @@ def donde_iria(nombre, tipo="contenido"):
|
||||
if cub == "PROYECTOS":
|
||||
kw["app"] = R.app_proyecto(ext) or ("Diseño" if rol == "diseno" else "Edicion")
|
||||
destino = "_Revisar" if cub == "REVISAR" else destino_plantilla(tipo, cub, **kw)
|
||||
return {"nombre": nombre, "rol": rol, "que": R.ROL_QUE.get(rol, rol), "cubeta": cub,
|
||||
# el día solo se sabe con la carpeta del cliente delante (depende de cuántos rodajes tuvo ese mes),
|
||||
# así que aquí se dice cuál sería, no que vaya a estar
|
||||
dia = R.nombre_dia(fecha) if cub in ("GRABACION", "CELULAR") else ""
|
||||
return {"nombre": nombre, "dia": dia, "rol": rol, "que": R.ROL_QUE.get(rol, rol), "cubeta": cub,
|
||||
"titulo": R.CUBETAS.get(cub, cub), "color": R.COLOR_CUBETA.get(cub, R.COLOR_CUBETA[""]),
|
||||
"destino": destino, "crudo": [x for x in (PLANTILLAS.get(tipo, {}).get(cub, "") or "").split("/") if x],
|
||||
"fecha": fecha, "por_fecha": origen, "camara": firma or "",
|
||||
|
||||
Referencia en una nueva incidencia
Block a user