Refactor code structure for improved readability and maintainability
This commit is contained in:
20
assets/static/chart.umd.min.js
vendored
Normal file
20
assets/static/chart.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -452,3 +452,23 @@ pre {
|
|||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
outline: 5px solid blue;
|
outline: 5px solid blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.saveico {
|
||||||
|
border-color: green !important;
|
||||||
|
}
|
||||||
|
.delico {
|
||||||
|
border-color: red !important;
|
||||||
|
}
|
||||||
|
.opicon {
|
||||||
|
border-color: blue !important;
|
||||||
|
}
|
||||||
|
.saveico img, .delico img, .opicon img {
|
||||||
|
height: 52px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.saveico, .delico, .opicon {
|
||||||
|
padding: 2.5px 7.5px;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 4px solid;
|
||||||
|
}
|
||||||
BIN
assets/static/exchange.png
Normal file
BIN
assets/static/exchange.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
BIN
assets/static/exit.png
Normal file
BIN
assets/static/exit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
assets/static/find.png
Normal file
BIN
assets/static/find.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
BIN
assets/static/floppy_disk_green.png
Normal file
BIN
assets/static/floppy_disk_green.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
BIN
assets/static/garbage.png
Normal file
BIN
assets/static/garbage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
BIN
assets/static/printer2.png
Normal file
BIN
assets/static/printer2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
@@ -74,6 +74,7 @@
|
|||||||
<script src="static/pouchdb.min.js"></script>
|
<script src="static/pouchdb.min.js"></script>
|
||||||
<script src="static/toastr.min.js"></script>
|
<script src="static/toastr.min.js"></script>
|
||||||
<script src="static/doublescroll.js"></script>
|
<script src="static/doublescroll.js"></script>
|
||||||
|
<script src="static/chart.umd.min.js"></script>
|
||||||
<script src="pwa.js"></script>
|
<script src="pwa.js"></script>
|
||||||
<script src="config.js"></script>
|
<script src="config.js"></script>
|
||||||
<script src="db.js"></script>
|
<script src="db.js"></script>
|
||||||
|
|||||||
@@ -109,8 +109,14 @@ PAGES.comedor = {
|
|||||||
<input type="text" id="${field_postre}" value="" /><br />
|
<input type="text" id="${field_postre}" value="" /><br />
|
||||||
<div class="picto" id="${btn_picto_postre}"></div>
|
<div class="picto" id="${btn_picto_postre}"></div>
|
||||||
</label>
|
</label>
|
||||||
<button class="btn5" id="${btn_guardar}">Guardar</button>
|
<button class="saveico" id="${btn_guardar}">
|
||||||
<button class="rojo" id="${btn_borrar}">Borrar</button>
|
<img src="static/floppy_disk_green.png" />
|
||||||
|
<br>Guardar
|
||||||
|
</button>
|
||||||
|
<button class="delico" id="${btn_borrar}">
|
||||||
|
<img src="static/garbage.png" />
|
||||||
|
<br>Borrar
|
||||||
|
</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
`;
|
`;
|
||||||
const pictogramSelector = TS_CreateArasaacSelector({
|
const pictogramSelector = TS_CreateArasaacSelector({
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ PAGES.index = {
|
|||||||
Tienes ${parseFloat(SUB_LOGGED_IN_DETAILS.Monedero_Balance).toPrecision(2)} € en el
|
Tienes ${parseFloat(SUB_LOGGED_IN_DETAILS.Monedero_Balance).toPrecision(2)} € en el
|
||||||
monedero.
|
monedero.
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<details style="border: 2px solid black; padding: 15px; border-radius: 10px;">
|
||||||
id="${div_stats}"
|
<summary>Estadisticas</summary>
|
||||||
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 15px; margin-bottom: 20px;"
|
<div
|
||||||
></div>
|
id="${div_stats}"
|
||||||
|
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 15px; margin-bottom: 20px;"
|
||||||
|
></div>
|
||||||
|
</details>
|
||||||
<em>Utiliza el menú superior para abrir un modulo</em>
|
<em>Utiliza el menú superior para abrir un modulo</em>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<button class="btn1" onclick="ActualizarProgramaTeleSec()">Actualizar programa</button>
|
<button class="btn1" onclick="ActualizarProgramaTeleSec()">Actualizar programa</button>
|
||||||
|
|||||||
@@ -18,67 +18,323 @@ PAGES.materiales = {
|
|||||||
var field_cantidad_min = safeuuid();
|
var field_cantidad_min = safeuuid();
|
||||||
var field_ubicacion = safeuuid();
|
var field_ubicacion = safeuuid();
|
||||||
var field_notas = safeuuid();
|
var field_notas = safeuuid();
|
||||||
|
var mov_tipo = safeuuid();
|
||||||
|
var mov_cantidad = safeuuid();
|
||||||
|
var mov_nota = safeuuid();
|
||||||
|
var mov_btn = safeuuid();
|
||||||
|
var mov_registro = safeuuid();
|
||||||
|
var mov_chart = safeuuid();
|
||||||
|
var mov_chart_canvas = safeuuid();
|
||||||
|
var mov_open_modal_btn = safeuuid();
|
||||||
|
var btn_print_chart = safeuuid();
|
||||||
|
var mov_modal = safeuuid();
|
||||||
|
var mov_modal_close = safeuuid();
|
||||||
var btn_guardar = safeuuid();
|
var btn_guardar = safeuuid();
|
||||||
var btn_borrar = safeuuid();
|
var btn_borrar = safeuuid();
|
||||||
var FECHA_ISO = new Date().toISOString().split('T')[0];
|
var FECHA_ISO = new Date().toISOString().split('T')[0];
|
||||||
|
var movimientos = [];
|
||||||
|
var movimientosChartInstance = null;
|
||||||
|
|
||||||
|
function parseNum(v, fallback = 0) {
|
||||||
|
var n = parseFloat(v);
|
||||||
|
return Number.isFinite(n) ? n : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMaterialData() {
|
||||||
|
return {
|
||||||
|
Nombre: document.getElementById(field_nombre).value,
|
||||||
|
Unidad: document.getElementById(field_unidad).value,
|
||||||
|
Cantidad: document.getElementById(field_cantidad).value,
|
||||||
|
Cantidad_Minima: document.getElementById(field_cantidad_min).value,
|
||||||
|
Ubicacion: document.getElementById(field_ubicacion).value,
|
||||||
|
Revision: document.getElementById(field_revision).value,
|
||||||
|
Notas: document.getElementById(field_notas).value,
|
||||||
|
Movimientos: movimientos,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderMovimientos() {
|
||||||
|
var el = document.getElementById(mov_registro);
|
||||||
|
if (!el) return;
|
||||||
|
if (!movimientos.length) {
|
||||||
|
el.innerHTML = '<small>Sin movimientos registrados.</small>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rows = movimientos
|
||||||
|
.map((mov) => {
|
||||||
|
var fecha = mov.Fecha ? new Date(mov.Fecha).toLocaleString('es-ES') : '-';
|
||||||
|
return html`<tr>
|
||||||
|
<td>${fecha}</td>
|
||||||
|
<td>${mov.Tipo || '-'}</td>
|
||||||
|
<td>${mov.Cantidad ?? '-'}</td>
|
||||||
|
<td>${mov.Antes ?? '-'}</td>
|
||||||
|
<td>${mov.Despues ?? '-'}</td>
|
||||||
|
<td>${mov.Nota || ''}</td>
|
||||||
|
</tr>`;
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
el.innerHTML = html`
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Fecha</th>
|
||||||
|
<th>Tipo</th>
|
||||||
|
<th>Cantidad</th>
|
||||||
|
<th>Antes</th>
|
||||||
|
<th>Después</th>
|
||||||
|
<th>Nota</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>${rows}</tbody>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderMovimientosChart() {
|
||||||
|
var el = document.getElementById(mov_chart);
|
||||||
|
if (!el) return;
|
||||||
|
|
||||||
|
if (movimientosChartInstance) {
|
||||||
|
movimientosChartInstance.destroy();
|
||||||
|
movimientosChartInstance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!movimientos.length) {
|
||||||
|
el.innerHTML = html`
|
||||||
|
<h3 style="margin: 0 0 8px 0;">Historial de movimientos por fecha</h3>
|
||||||
|
<small>Sin datos para graficar.</small>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ordered = [...movimientos].sort((a, b) => {
|
||||||
|
return new Date(a.Fecha || 0).getTime() - new Date(b.Fecha || 0).getTime();
|
||||||
|
});
|
||||||
|
|
||||||
|
var deltas = [];
|
||||||
|
var labelsShort = [];
|
||||||
|
|
||||||
|
ordered.forEach((mov) => {
|
||||||
|
var cantidad = parseNum(mov.Cantidad, 0);
|
||||||
|
var delta = 0;
|
||||||
|
if (mov.Tipo === 'Entrada') {
|
||||||
|
delta = cantidad;
|
||||||
|
} else if (mov.Tipo === 'Salida') {
|
||||||
|
delta = -cantidad;
|
||||||
|
} else {
|
||||||
|
var antes = parseNum(mov.Antes, 0);
|
||||||
|
var despues = parseNum(mov.Despues, antes);
|
||||||
|
delta = despues - antes;
|
||||||
|
}
|
||||||
|
deltas.push(Number(delta.toFixed(2)));
|
||||||
|
|
||||||
|
var fechaTxt = mov.Fecha ? new Date(mov.Fecha).toLocaleString('es-ES') : '-';
|
||||||
|
labelsShort.push(fechaTxt);
|
||||||
|
});
|
||||||
|
|
||||||
|
var currentStock = parseNum(document.getElementById(field_cantidad)?.value, 0);
|
||||||
|
var totalNeto = deltas.reduce((acc, n) => acc + n, 0);
|
||||||
|
var stockInicialInferido = currentStock - totalNeto;
|
||||||
|
|
||||||
|
if (ordered.length > 0 && Number.isFinite(parseNum(ordered[0].Antes, NaN))) {
|
||||||
|
stockInicialInferido = parseNum(ordered[0].Antes, stockInicialInferido);
|
||||||
|
}
|
||||||
|
|
||||||
|
var acumulado = stockInicialInferido;
|
||||||
|
var values = deltas.map((neto) => {
|
||||||
|
acumulado += neto;
|
||||||
|
return Number(acumulado.toFixed(2));
|
||||||
|
});
|
||||||
|
|
||||||
|
el.innerHTML = html`
|
||||||
|
<h3 style="margin: 0 0 8px 0;">Historial de movimientos por fecha</h3>
|
||||||
|
<small style="display: block;margin-bottom: 6px;">Stock por fecha (cierre diario)</small>
|
||||||
|
<canvas id="${mov_chart_canvas}" style="width: 100%;height: 280px;"></canvas>
|
||||||
|
`;
|
||||||
|
|
||||||
|
if (typeof Chart === 'undefined') {
|
||||||
|
el.innerHTML += '<small>No se pudo cargar la librería de gráficos.</small>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var chartCanvasEl = document.getElementById(mov_chart_canvas);
|
||||||
|
if (!chartCanvasEl) return;
|
||||||
|
|
||||||
|
movimientosChartInstance = new Chart(chartCanvasEl, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: labelsShort,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Stock diario',
|
||||||
|
data: values,
|
||||||
|
borderColor: '#2d7ef7',
|
||||||
|
backgroundColor: 'rgba(45,126,247,0.16)',
|
||||||
|
fill: true,
|
||||||
|
tension: 0.25,
|
||||||
|
pointRadius: 3,
|
||||||
|
pointHoverRadius: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
title: {
|
||||||
|
display: false,
|
||||||
|
text: 'Stock',
|
||||||
|
},
|
||||||
|
grace: '10%',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
interaction: {
|
||||||
|
mode: 'nearest',
|
||||||
|
axis: 'x',
|
||||||
|
intersect: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
container.innerHTML = html`
|
container.innerHTML = html`
|
||||||
<h1>Material <code id="${nameh1}"></code></h1>
|
<h1>Material <code id="${nameh1}"></code></h1>
|
||||||
${BuildQR('materiales,' + mid)}
|
<fieldset style="width: 100%;max-width: 980px;box-sizing: border-box;">
|
||||||
<fieldset>
|
<div style="display: flex;flex-wrap: wrap;gap: 10px 16px;align-items: flex-end;">
|
||||||
<label>
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 220px;flex: 1 1 280px;">
|
||||||
Fecha Revisión<br />
|
<label for="${field_revision}">Fecha Revisión</label>
|
||||||
<input type="date" id="${field_revision}" />
|
<input type="date" id="${field_revision}" style="flex: 1;" />
|
||||||
<a
|
</div>
|
||||||
onclick='document.getElementById("${field_revision}").value = "${FECHA_ISO}";'
|
|
||||||
style="color: blue;cursor: pointer;font-size: 0.9em;"
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 220px;flex: 1 1 280px;">
|
||||||
>Hoy - Contado todas las existencias </a
|
<label for="${field_nombre}">Nombre</label>
|
||||||
><br /><br />
|
<input type="text" id="${field_nombre}" style="flex: 1;" />
|
||||||
</label>
|
</div>
|
||||||
<label>
|
|
||||||
Nombre<br />
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 220px;flex: 1 1 280px;">
|
||||||
<input type="text" id="${field_nombre}" /><br /><br />
|
<label for="${field_unidad}">Unidad</label>
|
||||||
</label>
|
<select id="${field_unidad}" style="flex: 1;">
|
||||||
<label>
|
<option value="unidad(es)">unidad(es)</option>
|
||||||
Unidad<br />
|
<option value="paquete(s)">paquete(s)</option>
|
||||||
<select id="${field_unidad}">
|
<option value="caja(s)">caja(s)</option>
|
||||||
<option value="unidad(es)">unidad(es)</option>
|
<option value="rollo(s)">rollo(s)</option>
|
||||||
<option value="paquete(s)">paquete(s)</option>
|
<option value="bote(s)">bote(s)</option>
|
||||||
<option value="caja(s)">caja(s)</option>
|
|
||||||
<option value="rollo(s)">rollo(s)</option>
|
<option value="metro(s)">metro(s)</option>
|
||||||
<option value="bote(s)">bote(s)</option>
|
<option value="litro(s)">litro(s)</option>
|
||||||
|
<option value="kg">kg</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 220px;flex: 1 1 280px;">
|
||||||
|
<label for="${field_cantidad}">Cantidad Actual</label>
|
||||||
|
<input type="number" step="0.5" id="${field_cantidad}" style="flex: 1;" disabled />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 220px;flex: 1 1 280px;">
|
||||||
|
<label for="${field_cantidad_min}">Cantidad Minima</label>
|
||||||
|
<input type="number" step="0.5" id="${field_cantidad_min}" style="flex: 1;" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 220px;flex: 1 1 280px;">
|
||||||
|
<label for="${field_ubicacion}">Ubicación</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="${field_ubicacion}"
|
||||||
|
value="-"
|
||||||
|
list="${field_ubicacion}_list"
|
||||||
|
style="flex: 1;"
|
||||||
|
/>
|
||||||
|
<datalist id="${field_ubicacion}_list"></datalist>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 220px;flex: 1 1 100%;">
|
||||||
|
<label for="${field_notas}">Notas</label>
|
||||||
|
<textarea id="${field_notas}" style="flex: 1;"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="${mov_modal}"
|
||||||
|
style="display: none;position: fixed;z-index: 9999;left: 0;top: 0;width: 100%;height: 100%;overflow: auto;background: rgba(0,0,0,0.45);"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="background: #fff;margin: 2vh auto;padding: 14px;border: 1px solid #888;width: min(960px, 96vw);max-height: 94vh;overflow: auto;border-radius: 8px;box-sizing: border-box;"
|
||||||
|
>
|
||||||
|
<div style="display: flex;justify-content: space-between;align-items: center;gap: 10px;">
|
||||||
|
<h3 style="margin: 0;">Realizar movimiento</h3>
|
||||||
|
<button type="button" id="${mov_modal_close}" class="rojo">Cerrar</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 12px;display: flex;gap: 10px;align-items: flex-end;flex-wrap: wrap;">
|
||||||
|
<div style="display: flex;flex-wrap: wrap;gap: 10px 12px;align-items: flex-end;flex: 1 1 420px;">
|
||||||
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 180px;flex: 1 1 220px;">
|
||||||
|
<label for="${mov_tipo}">Tipo</label>
|
||||||
|
<select id="${mov_tipo}" style="flex: 1;">
|
||||||
|
<option value="Entrada">Entrada</option>
|
||||||
|
<option value="Salida">Salida</option>
|
||||||
|
<option value="Ajuste">Ajuste</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 180px;flex: 1 1 220px;">
|
||||||
|
<label for="${mov_cantidad}">Cantidad</label>
|
||||||
|
<input type="number" step="0.5" id="${mov_cantidad}" style="flex: 1;" />
|
||||||
|
</div>
|
||||||
|
<div style="display: flex;flex-direction: column;align-items: stretch;gap: 6px;min-width: 180px;flex: 1 1 220px;">
|
||||||
|
<label for="${mov_nota}">Nota</label>
|
||||||
|
<input type="text" id="${mov_nota}" style="flex: 1;" placeholder="Motivo del movimiento" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex;justify-content: flex-end;flex: 1 1 120px;min-width: 120px;">
|
||||||
|
<button type="button" class="saveico" id="${mov_btn}">
|
||||||
|
<img src="static/floppy_disk_green.png" />
|
||||||
|
<br>Guardar
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 style="margin: 14px 0 6px 0;">Registro de movimientos</h4>
|
||||||
|
<div id="${mov_registro}"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<option value="metro(s)">metro(s)</option>
|
|
||||||
<option value="litro(s)">litro(s)</option>
|
|
||||||
<option value="kg">kg</option></select
|
|
||||||
><br /><br />
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
Cantidad Actual<br />
|
|
||||||
<input type="number" step="0.5" id="${field_cantidad}" /><br /><br />
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
Cantidad Minima<br />
|
|
||||||
<input type="number" step="0.5" id="${field_cantidad_min}" /><br /><br />
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
Ubicación<br />
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="${field_ubicacion}"
|
|
||||||
value="-"
|
|
||||||
list="${field_ubicacion}_list"
|
|
||||||
/><br /><br />
|
|
||||||
<!-- Autocompletar con ubicaciones existentes -->
|
|
||||||
<datalist id="${field_ubicacion}_list"></datalist>
|
|
||||||
</label>
|
|
||||||
<label>
|
|
||||||
Notas<br />
|
|
||||||
<textarea id="${field_notas}"></textarea><br /><br />
|
|
||||||
</label>
|
|
||||||
<hr />
|
<hr />
|
||||||
<button class="btn5" id="${btn_guardar}">Guardar</button>
|
<button class="saveico" id="${btn_guardar}">
|
||||||
<button class="rojo" id="${btn_borrar}">Borrar</button>
|
<img src="static/floppy_disk_green.png" />
|
||||||
|
<br>Guardar
|
||||||
|
</button>
|
||||||
|
<button class="delico" id="${btn_borrar}">
|
||||||
|
<img src="static/garbage.png" />
|
||||||
|
<br>Borrar
|
||||||
|
</button>
|
||||||
|
<button class="opicon" id="${mov_open_modal_btn}">
|
||||||
|
<img src="static/exchange.png" />
|
||||||
|
<br>Movimientos
|
||||||
|
</button>
|
||||||
|
<button class="opicon" id="${btn_print_chart}">
|
||||||
|
<img src="static/printer2.png" />
|
||||||
|
<br>Imprimir
|
||||||
|
</button>
|
||||||
|
<button class="opicon" onclick="setUrlHash('materiales')">
|
||||||
|
<img src="static/exit.png" />
|
||||||
|
<br>Salir
|
||||||
|
</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<div id="${mov_chart}" style="max-width: 980px;width: 100%;margin-top: 14px;min-height: 260px;height: min(400px, 52vh);"></div>
|
||||||
`;
|
`;
|
||||||
// Cargar ubicaciones existentes para autocompletar
|
// Cargar ubicaciones existentes para autocompletar
|
||||||
DB.map('materiales', (data) => {
|
DB.map('materiales', (data) => {
|
||||||
@@ -125,6 +381,9 @@ PAGES.materiales = {
|
|||||||
document.getElementById(field_ubicacion).value = data['Ubicacion'] || '-';
|
document.getElementById(field_ubicacion).value = data['Ubicacion'] || '-';
|
||||||
document.getElementById(field_revision).value = data['Revision'] || '-';
|
document.getElementById(field_revision).value = data['Revision'] || '-';
|
||||||
document.getElementById(field_notas).value = data['Notas'] || '';
|
document.getElementById(field_notas).value = data['Notas'] || '';
|
||||||
|
movimientos = Array.isArray(data['Movimientos']) ? data['Movimientos'] : [];
|
||||||
|
renderMovimientos();
|
||||||
|
renderMovimientosChart();
|
||||||
}
|
}
|
||||||
if (typeof data == 'string') {
|
if (typeof data == 'string') {
|
||||||
TS_decrypt(
|
TS_decrypt(
|
||||||
@@ -140,6 +399,83 @@ PAGES.materiales = {
|
|||||||
load_data(data || {});
|
load_data(data || {});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById(mov_open_modal_btn).onclick = () => {
|
||||||
|
document.getElementById(mov_modal).style.display = 'block';
|
||||||
|
renderMovimientos();
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById(btn_print_chart).onclick = () => {
|
||||||
|
window.print();
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById(mov_modal_close).onclick = () => {
|
||||||
|
document.getElementById(mov_modal).style.display = 'none';
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById(mov_modal).onclick = (evt) => {
|
||||||
|
if (evt.target.id === mov_modal) {
|
||||||
|
document.getElementById(mov_modal).style.display = 'none';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById(mov_btn).onclick = () => {
|
||||||
|
var btn = document.getElementById(mov_btn);
|
||||||
|
if (btn.disabled) return;
|
||||||
|
|
||||||
|
var tipo = document.getElementById(mov_tipo).value;
|
||||||
|
var cantidadMov = parseNum(document.getElementById(mov_cantidad).value, NaN);
|
||||||
|
var nota = document.getElementById(mov_nota).value || '';
|
||||||
|
var actual = parseNum(document.getElementById(field_cantidad).value, 0);
|
||||||
|
|
||||||
|
if (!Number.isFinite(cantidadMov) || cantidadMov <= 0) {
|
||||||
|
toastr.warning('Indica una cantidad válida para el movimiento');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nuevaCantidad = actual;
|
||||||
|
if (tipo === 'Entrada') {
|
||||||
|
nuevaCantidad = actual + cantidadMov;
|
||||||
|
} else if (tipo === 'Salida') {
|
||||||
|
nuevaCantidad = actual - cantidadMov;
|
||||||
|
} else if (tipo === 'Ajuste') {
|
||||||
|
nuevaCantidad = cantidadMov;
|
||||||
|
}
|
||||||
|
|
||||||
|
movimientos.unshift({
|
||||||
|
Fecha: new Date().toISOString(),
|
||||||
|
Tipo: tipo,
|
||||||
|
Cantidad: cantidadMov,
|
||||||
|
Antes: actual,
|
||||||
|
Despues: nuevaCantidad,
|
||||||
|
Nota: nota,
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById(field_cantidad).value = nuevaCantidad;
|
||||||
|
document.getElementById(field_revision).value = FECHA_ISO;
|
||||||
|
document.getElementById(mov_cantidad).value = '';
|
||||||
|
document.getElementById(mov_nota).value = '';
|
||||||
|
renderMovimientos();
|
||||||
|
renderMovimientosChart();
|
||||||
|
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.style.opacity = '0.5';
|
||||||
|
document.getElementById('actionStatus').style.display = 'block';
|
||||||
|
DB.put('materiales', mid, buildMaterialData())
|
||||||
|
.then(() => {
|
||||||
|
toastr.success('Movimiento registrado');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.warn('DB.put error', e);
|
||||||
|
toastr.error('Error al guardar el movimiento');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.style.opacity = '1';
|
||||||
|
document.getElementById('actionStatus').style.display = 'none';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
document.getElementById(btn_guardar).onclick = () => {
|
document.getElementById(btn_guardar).onclick = () => {
|
||||||
// Disable button to prevent double-clicking
|
// Disable button to prevent double-clicking
|
||||||
var guardarBtn = document.getElementById(btn_guardar);
|
var guardarBtn = document.getElementById(btn_guardar);
|
||||||
@@ -148,15 +484,7 @@ PAGES.materiales = {
|
|||||||
guardarBtn.disabled = true;
|
guardarBtn.disabled = true;
|
||||||
guardarBtn.style.opacity = '0.5';
|
guardarBtn.style.opacity = '0.5';
|
||||||
|
|
||||||
var data = {
|
var data = buildMaterialData();
|
||||||
Nombre: document.getElementById(field_nombre).value,
|
|
||||||
Unidad: document.getElementById(field_unidad).value,
|
|
||||||
Cantidad: document.getElementById(field_cantidad).value,
|
|
||||||
Cantidad_Minima: document.getElementById(field_cantidad_min).value,
|
|
||||||
Ubicacion: document.getElementById(field_ubicacion).value,
|
|
||||||
Revision: document.getElementById(field_revision).value,
|
|
||||||
Notas: document.getElementById(field_notas).value,
|
|
||||||
};
|
|
||||||
document.getElementById('actionStatus').style.display = 'block';
|
document.getElementById('actionStatus').style.display = 'block';
|
||||||
DB.put('materiales', mid, data)
|
DB.put('materiales', mid, data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -48,8 +48,14 @@ PAGES.mensajes = {
|
|||||||
<div id="${attachments_list}"></div>
|
<div id="${attachments_list}"></div>
|
||||||
</label>
|
</label>
|
||||||
<hr />
|
<hr />
|
||||||
<button class="btn5" id="${btn_guardar}">Guardar</button>
|
<button class="saveico" id="${btn_guardar}">
|
||||||
<button class="rojo" id="${btn_borrar}">Borrar</button>
|
<img src="static/floppy_disk_green.png" />
|
||||||
|
<br>Guardar
|
||||||
|
</button>
|
||||||
|
<button class="delico" id="${btn_borrar}">
|
||||||
|
<img src="static/garbage.png" />
|
||||||
|
<br>Borrar
|
||||||
|
</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
`;
|
`;
|
||||||
DB.get('mensajes', mid).then((data) => {
|
DB.get('mensajes', mid).then((data) => {
|
||||||
|
|||||||
@@ -45,8 +45,14 @@ PAGES.notas = {
|
|||||||
<div id="${attachments_list}"></div>
|
<div id="${attachments_list}"></div>
|
||||||
</label>
|
</label>
|
||||||
<hr />
|
<hr />
|
||||||
<button class="btn5" id="${btn_guardar}">Guardar</button>
|
<button class="saveico" id="${btn_guardar}">
|
||||||
<button class="rojo" id="${btn_borrar}">Borrar</button>
|
<img src="static/floppy_disk_green.png" />
|
||||||
|
<br>Guardar
|
||||||
|
</button>
|
||||||
|
<button class="delico" id="${btn_borrar}">
|
||||||
|
<img src="static/garbage.png" />
|
||||||
|
<br>Borrar
|
||||||
|
</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
`;
|
`;
|
||||||
var divact = document.getElementById(div_actions);
|
var divact = document.getElementById(div_actions);
|
||||||
|
|||||||
@@ -87,8 +87,14 @@ PAGES.personas = {
|
|||||||
Notas<br>
|
Notas<br>
|
||||||
<textarea id="${field_notas}"></textarea><br><br>
|
<textarea id="${field_notas}"></textarea><br><br>
|
||||||
</label><hr>
|
</label><hr>
|
||||||
<button class="btn5" id="${btn_guardar}">Guardar</button>
|
<button class="saveico" id="${btn_guardar}">
|
||||||
<button class="rojo" id="${btn_borrar}">Borrar</button>
|
<img src="static/floppy_disk_green.png" />
|
||||||
|
<br>Guardar
|
||||||
|
</button>
|
||||||
|
<button class="delico" id="${btn_borrar}">
|
||||||
|
<img src="static/garbage.png" />
|
||||||
|
<br>Borrar
|
||||||
|
</button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
`;
|
`;
|
||||||
var resized = '';
|
var resized = '';
|
||||||
|
|||||||
Reference in New Issue
Block a user