diff --git a/app/app.ipynb b/app/app.ipynb index 88036bf..e3447dc 100644 --- a/app/app.ipynb +++ b/app/app.ipynb @@ -347,6 +347,9 @@ " return df\n", "\n", "def _build_cobertura(df):\n", + " if df is None or df.empty or 'CANT_DESCARGADA' not in df.columns:\n", + " return pd.DataFrame(columns=['FACTURAEXPO','FECHA_FACTURAEXPO',\n", + " 'componentes_total','componentes_100pct','pct_promedio'])\n", " df_d = df.copy()\n", " df_d['cant_cubierta'] = df_d['CANT_DESCARGADA'].where(df_d['TIPO'].isin(['ORIGINAL','SUSTITUTO']), 0)\n", " cob_comp = df_d.groupby(['FACTURAEXPO','FECHA_FACTURAEXPO','LINEA','PT','COMPONENTE_MP','UNIMED_BOM','CANT_REQUERIDA'],\n", @@ -597,7 +600,7 @@ "def graficar_impo_expo(cmp):\n", " plt.close('all')\n", " fig, axes = plt.subplots(2, 1, figsize=(11, 8))\n", - " fig.suptitle('IMPO vs EXPO por aanio‚±o', fontsize=14, fontweight='bold', y=1.0)\n", + " fig.suptitle('IMPO vs EXPO por a-o', fontsize=14, fontweight='bold', y=1.0)\n", " x = cmp['ANIO'].astype(int).values\n", " xpos = np.arange(len(x)); ancho = 0.4\n", " cI, cE = '#1976D2', '#F57C00'\n", @@ -617,7 +620,7 @@ " ax = axes[1]\n", " b1 = ax.bar(xpos-ancho/2, cmp['valor_me_impo'], ancho, label='IMPO', color=cI)\n", " b2 = ax.bar(xpos+ancho/2, cmp['valor_me_expo'], ancho, label='EXPO', color=cE)\n", - " ax.set_title('Valor ME (USD)'); ax.set_xticks(xpos); ax.set_xticklabels(x); ax.set_xlabel('Aanio‚±o')\n", + " ax.set_title('Valor ME (USD)'); ax.set_xticks(xpos); ax.set_xticklabels(x); ax.set_xlabel('A-o')\n", " ax.yaxis.set_major_formatter(mtick.FuncFormatter(lambda v,_: f'${v:,.0f}'))\n", " ax.legend(loc='upper left'); ax.grid(axis='y', linestyle=':', alpha=0.5)\n", " ax.set_ylim(top=ax.get_ylim()[1]*1.18); lab(ax, b1, cI, '${:,.0f}'); lab(ax, b2, cE, '${:,.0f}')\n", @@ -627,7 +630,7 @@ "def graficar_saldos_anio(por_anio):\n", " plt.close('all')\n", " fig, axes = plt.subplots(1, 2, figsize=(13, 5))\n", - " fig.suptitle('Saldo disponible por aanio‚±o de entrada', fontsize=13, fontweight='bold')\n", + " fig.suptitle('Saldo disponible por a-o de entrada', fontsize=13, fontweight='bold')\n", " x = por_anio['ANIO_ENTRADA'].astype(int).astype(str).values\n", " axes[0].bar(x, por_anio['saldo_cant'], color='#42A5F5')\n", " axes[0].set_title('Cantidad'); axes[0].grid(axis='y', linestyle=':', alpha=0.5)\n", @@ -686,7 +689,7 @@ "def graficar_pesos_anio(cmp):\n", " plt.close('all')\n", " fig, ax = plt.subplots(figsize=(13, 5.5))\n", - " fig.suptitle('Peso por aanio‚±o anio‚ IMPO / EXPO / CONSUMIDO / DESCARGAS', fontsize=13, fontweight='bold')\n", + " fig.suptitle('Peso por a-o - IMPO / EXPO / CONSUMIDO / DESCARGAS', fontsize=13, fontweight='bold')\n", " x = cmp['ANIO'].astype(int).values\n", " xpos = np.arange(len(x)); ancho = 0.2\n", " cI, cE, cC, cD = '#1976D2', '#F57C00', '#43A047', '#8E24AA'\n", @@ -694,7 +697,7 @@ " b2 = ax.bar(xpos-0.5*ancho, cmp['peso_expo'], ancho, label='EXPO', color=cE)\n", " b3 = ax.bar(xpos+0.5*ancho, cmp['peso_consumido'], ancho, label='CONSUMIDO', color=cC)\n", " b4 = ax.bar(xpos+1.5*ancho, cmp['peso_descargas'], ancho, label='DESCARGAS', color=cD)\n", - " ax.set_xticks(xpos); ax.set_xticklabels(x); ax.set_xlabel('Aanio‚±o')\n", + " ax.set_xticks(xpos); ax.set_xticklabels(x); ax.set_xlabel('A-o')\n", " ax.set_ylabel('Peso neto')\n", " ax.yaxis.set_major_formatter(mtick.FuncFormatter(lambda v,_: f'{v:,.0f}'))\n", " ax.legend(loc='upper left'); ax.grid(axis='y', linestyle=':', alpha=0.5)\n", @@ -734,19 +737,19 @@ " cmp['cantidad_impo'] = cmp['cantidad_impo'].round(2)\n", " cmp['cantidad_expo'] = cmp['cantidad_expo'].round(2)\n", " cmp['diferencia'] = (cmp['cantidad_expo'] - cmp['cantidad_impo']).round(2)\n", - " prog.done('Cantidades por aanio‚±o listas')\n", + " prog.done('Cantidades por a-o listas')\n", " return cmp\n", "\n", "def graficar_cantidades_anio(cmp):\n", " plt.close('all')\n", " fig, ax = plt.subplots(figsize=(12, 5.5))\n", - " fig.suptitle('Cantidades por aanio‚±o anio‚ IMPO vs EXPO', fontsize=13, fontweight='bold')\n", + " fig.suptitle('Cantidades por a-o - IMPO vs EXPO', fontsize=13, fontweight='bold')\n", " x = cmp['ANIO'].astype(int).values\n", " xpos = np.arange(len(x)); ancho = 0.4\n", " cI, cE = '#1976D2', '#F57C00'\n", " b1 = ax.bar(xpos-ancho/2, cmp['cantidad_impo'], ancho, label='IMPO', color=cI)\n", " b2 = ax.bar(xpos+ancho/2, cmp['cantidad_expo'], ancho, label='EXPO', color=cE)\n", - " ax.set_xticks(xpos); ax.set_xticklabels(x); ax.set_xlabel('Aanio‚±o')\n", + " ax.set_xticks(xpos); ax.set_xticklabels(x); ax.set_xlabel('A-o')\n", " ax.set_ylabel('Cantidad (suma de unidades, varias UM)')\n", " ax.yaxis.set_major_formatter(mtick.FuncFormatter(lambda v,_: f'{v:,.0f}'))\n", " ax.legend(loc='upper left'); ax.grid(axis='y', linestyle=':', alpha=0.5)\n", @@ -792,7 +795,7 @@ " cmp['cantidad_impo'] = cmp['cantidad_impo'].round(2)\n", " cmp['cantidad_expo'] = cmp['cantidad_expo'].round(2)\n", " cmp['diferencia'] = (cmp['cantidad_expo'] - cmp['cantidad_impo']).round(2)\n", - " prog.done('Cantidades por aanio‚±o + UM listas')\n", + " prog.done('Cantidades por a-o + UM listas')\n", " return cmp\n", "\n", "def graficar_cantidades_anio_um(cmp, top_ums=None):\n", @@ -809,7 +812,7 @@ " return fig\n", " n = len(top_ums)\n", " fig, axes = plt.subplots(n, 1, figsize=(12, 3.2*n), squeeze=False)\n", - " fig.suptitle('Cantidades por aanio‚±o (separado por UM, top {} UMs)'.format(n), fontsize=13, fontweight='bold', y=1.0)\n", + " fig.suptitle('Cantidades por a-o (separado por UM, top {} UMs)'.format(n), fontsize=13, fontweight='bold', y=1.0)\n", " for idx, um in enumerate(top_ums):\n", " sub = filt[filt['UM'] == um].sort_values('ANIO')\n", " ax = axes[idx][0]\n", @@ -1944,7 +1947,7 @@ "def ejecutar_valores(plan, dry_run=True, progress=None, log=print):\n", " \"\"\"Paso B: UPDATE SPartidasExpo por cada partida del plan, usando 3-part\n", " naming si la fila trae BaseDeDatos/Esquema (cuando se uso shelter).\n", - " Transaccion por (pedimento, BD) — rollback si alguna partida falla.\"\"\"\n", + " Transaccion por (pedimento, BD) rollback si alguna partida falla.\"\"\"\n", " assert isinstance(dry_run, bool), 'dry_run debe ser bool'\n", " prog = _Progress(progress)\n", " if plan is None or plan.empty:\n", @@ -3241,11 +3244,11 @@ "btn_p10.on_click(_on_p10)\n", "\n", "tab_desc = W.VBox([\n", - " W.HTML('

Paso 8 anio‚ Pronostico de cobertura

'),\n", + " W.HTML('

Paso 8 - Pronostico de cobertura

'),\n", " btn_pron, bar_pron, out_pron,\n", - " W.HTML('

Paso 9 anio‚ Descargas pendientes (NA anio‚¢ AC)

'),\n", + " W.HTML('

Paso 9 - Descargas pendientes (NA - AC)

'),\n", " W.HBox([modo9, dry9]), W.HBox([fd9, fh9]), btn_p9, bar_p9, out_p9,\n", - " W.HTML('

Paso 10 anio‚ Complementaria (sobre facturas AC)

'),\n", + " W.HTML('

Paso 10 - Complementaria (sobre facturas AC)

'),\n", " W.HBox([modo10, dry10]), W.HBox([fd10, fh10]), facts_obj, btn_p10, bar_p10, out_p10,\n", "])\n", "\n", @@ -3275,46 +3278,46 @@ " print('Calculando IMPO vs EXPO...')\n", " df_imp, df_exp, cmp = calcular_impo_expo_anio(progress=bar_an)\n", " _state['df_imp'], _state['df_exp'], _state['cmp_impo_expo'] = df_imp, df_exp, cmp\n", - " print(f' IMPO aanio‚±os: {len(df_imp)} | EXPO aanio‚±os: {len(df_exp)} | Comparativo: {len(cmp)}')\n", - " print('Calculando pesos IMPO/EXPO/SALDO por aanio‚±o...')\n", + " print(f' IMPO a-os: {len(df_imp)} | EXPO a-os: {len(df_exp)} | Comparativo: {len(cmp)}')\n", + " print('Calculando pesos IMPO/EXPO/SALDO por a-o...')\n", " cmp_pesos = calcular_pesos_por_anio(progress=bar_an)\n", " _state['cmp_pesos_anio'] = cmp_pesos\n", - " print(f' Comparativo pesos: {len(cmp_pesos)} aanio‚±os')\n", - " print('Calculando cantidades IMPO/EXPO por aanio‚±o...')\n", + " print(f' Comparativo pesos: {len(cmp_pesos)} a-os')\n", + " print('Calculando cantidades IMPO/EXPO por a-o...')\n", " cmp_cant = calcular_cantidades_por_anio(progress=bar_an)\n", " _state['cmp_cantidades_anio'] = cmp_cant\n", - " print(f' Comparativo cantidades: {len(cmp_cant)} aanio‚±os')\n", - " print('Calculando cantidades IMPO/EXPO por aanio‚±o + UM...')\n", + " print(f' Comparativo cantidades: {len(cmp_cant)} a-os')\n", + " print('Calculando cantidades IMPO/EXPO por a-o + UM...')\n", " cmp_cant_um = calcular_cantidades_por_anio_um(progress=bar_an)\n", " _state['cmp_cantidades_anio_um'] = cmp_cant_um\n", " print(f' Comparativo cantidades por UM: {len(cmp_cant_um)} filas')\n", " with out_an_anio:\n", " clear_output()\n", - " display(HTML('

Saldo disponible por aanio‚±o (de entrada del lote)

'))\n", + " display(HTML('

Saldo disponible por a-o (de entrada del lote)

'))\n", " display(_state['por_anio_saldos'])\n", " if not _state['por_anio_saldos'].empty:\n", " fig = graficar_saldos_anio(_state['por_anio_saldos']); display(fig); plt.close(fig)\n", " with out_an_imp_exp:\n", " clear_output()\n", - " display(HTML('

IMPO vs EXPO por aanio‚±o

'))\n", + " display(HTML('

IMPO vs EXPO por a-o

'))\n", " display(_state['cmp_impo_expo'])\n", " if not _state['cmp_impo_expo'].empty:\n", " fig = graficar_impo_expo(_state['cmp_impo_expo']); display(fig); plt.close(fig)\n", " with out_an_pesos:\n", " clear_output()\n", - " display(HTML('

Peso por aanio‚±o anio‚ IMPO / EXPO / CONSUMIDO / DESCARGAS

'))\n", + " display(HTML('

Peso por a-o - IMPO / EXPO / CONSUMIDO / DESCARGAS

'))\n", " display(_state['cmp_pesos_anio'])\n", " if not _state['cmp_pesos_anio'].empty:\n", " fig = graficar_pesos_anio(_state['cmp_pesos_anio']); display(fig); plt.close(fig)\n", " with out_an_cant:\n", " clear_output()\n", - " display(HTML('

Cantidades por aanio‚±o anio‚ IMPO vs EXPO

'))\n", + " display(HTML('

Cantidades por a-o - IMPO vs EXPO

'))\n", " display(_state['cmp_cantidades_anio'])\n", " if not _state['cmp_cantidades_anio'].empty:\n", " fig = graficar_cantidades_anio(_state['cmp_cantidades_anio']); display(fig); plt.close(fig)\n", " with out_an_cant_um:\n", " clear_output()\n", - " display(HTML('

Cantidades por aanio‚±o + UM (separado por unidad de medida)

'))\n", + " display(HTML('

Cantidades por a-o + UM (separado por unidad de medida)

'))\n", " display(_state['cmp_cantidades_anio_um'])\n", " if not _state['cmp_cantidades_anio_um'].empty:\n", " fig = graficar_cantidades_anio_um(_state['cmp_cantidades_anio_um']); display(fig); plt.close(fig)\n", @@ -3332,7 +3335,7 @@ "btn_an_xlsx.on_click(_on_an_xlsx)\n", "\n", "tab_an = W.VBox([\n", - " W.HTML('

Ananio‚¡lisis SSaldoTem + IMPO vs EXPO

'),\n", + " W.HTML('

An-lisis SSaldoTem + IMPO vs EXPO

'),\n", " W.HBox([btn_an, btn_an_xlsx]), bar_an, out_an_log, out_an_anio, out_an_imp_exp, out_an_pesos, out_an_cant, out_an_cant_um,\n", "])\n", "\n", @@ -3357,7 +3360,7 @@ "btn_nlp.on_click(_on_nlp)\n", "\n", "tab_nlp = W.VBox([\n", - " W.HTML('

Sustitutos NLP anio‚ TF-IDF + coseno

'),\n", + " W.HTML('

Sustitutos NLP - TF-IDF + coseno

'),\n", " min_sim, top_n, dry_nlp, btn_nlp, bar_nlp, out_nlp,\n", "])\n", "\n", @@ -3408,13 +3411,13 @@ "btn_p12c.on_click(_on_p12c)\n", "\n", "tab_kg = W.VBox([\n", - " W.HTML('

Paso 12 anio‚ Descarga por % de KGS

'\n", + " W.HTML('

Paso 12 - Descarga por % de KGS

'\n", " '

'\n", - " 'cant_req = (BOM.CANTIDAD / 100) anio‚ PESONETO de la partida. Mismo PEPS, UM y sustitutos.

'),\n", + " 'cant_req = (BOM.CANTIDAD / 100) - PESONETO de la partida. Mismo PEPS, UM y sustitutos.

'),\n", " btn_pron12, bar_pron12, out_pron12,\n", - " W.HTML('

Paso 12 anio‚ Descargas pendientes KG (NA anio‚¢ AC)

'),\n", + " W.HTML('

Paso 12 - Descargas pendientes KG (NA - AC)

'),\n", " W.HBox([modo12, dry12]), W.HBox([fd12, fh12]), btn_p12, bar_p12, out_p12,\n", - " W.HTML('

Paso 12 anio‚ Complementaria KG (sobre facturas AC)

'),\n", + " W.HTML('

Paso 12 - Complementaria KG (sobre facturas AC)

'),\n", " W.HBox([modo12c, dry12c]), W.HBox([fd12c, fh12c]), facts_obj12, btn_p12c, bar_p12c, out_p12c,\n", "])\n", "\n", @@ -4662,7 +4665,7 @@ " '

'\n", " 'Recorre todas las bases de datos de la instancia SQL Server (las que el usuario '\n", " 'puede acceder y tienen la tabla SPedimentos.PEDIMENTO) y reporta en '\n", - " 'cual(es) base(s) vive cada pedimento del Excel. Solo es diagnostico — no '\n", + " 'cual(es) base(s) vive cada pedimento del Excel. Solo es diagnostico no '\n", " 'modifica nada. Util cuando el cliente tiene varias BDs y no sabes a cual '\n", " 'apuntar el ajuste.

'),\n", " W.HBox([btn_val_shelter]), bar_val_shelter,\n",