feat: add price history mock data generation and enable date range filtering for price history chart
This commit is contained in:
@@ -49,6 +49,45 @@ def generar_historico_definitivo(dias_atras=180):
|
|||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', workers_data)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', workers_data)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
# 2.5 GENERACIÓN DE HISTORIAL DE PRECIOS MOCK
|
||||||
|
print("Generando fluctuaciones de precios históricas de prueba...")
|
||||||
|
c.execute("SELECT id FROM productos")
|
||||||
|
prod_ids = [row[0] for row in c.fetchall()]
|
||||||
|
c.execute("SELECT id FROM zonas")
|
||||||
|
zona_ids = [row[0] for row in c.fetchall()]
|
||||||
|
|
||||||
|
precios_historicos_extra = []
|
||||||
|
hoy = date.today()
|
||||||
|
|
||||||
|
for p_id in prod_ids:
|
||||||
|
for z_id in zona_ids:
|
||||||
|
c.execute("SELECT price, commission FROM precios_historicos WHERE producto_id = ? AND zona_id = ? ORDER BY fecha_activacion ASC LIMIT 1", (p_id, z_id))
|
||||||
|
base_row = c.fetchone()
|
||||||
|
if not base_row:
|
||||||
|
continue
|
||||||
|
base_price, base_comm = base_row
|
||||||
|
|
||||||
|
# Create 3 historical price changes in the last 180 days
|
||||||
|
intervalos = [140, 80, 30]
|
||||||
|
current_price = base_price
|
||||||
|
current_comm = base_comm
|
||||||
|
for dias in intervalos:
|
||||||
|
if random.random() < 0.70:
|
||||||
|
change_percent = random.choice([-0.15, -0.10, 0.05, 0.10, 0.15, 0.20])
|
||||||
|
current_price = int(current_price * (1 + change_percent))
|
||||||
|
current_price = max(1000, (current_price // 100) * 100)
|
||||||
|
|
||||||
|
comm_change = random.choice([-50, 0, 50, 100])
|
||||||
|
current_comm = max(100, current_comm + comm_change)
|
||||||
|
|
||||||
|
fecha_cambio = (hoy - timedelta(days=dias)).strftime('%Y-%m-%d 00:00:00')
|
||||||
|
precios_historicos_extra.append((p_id, z_id, current_price, current_comm, fecha_cambio))
|
||||||
|
|
||||||
|
c.executemany('''INSERT INTO precios_historicos
|
||||||
|
(producto_id, zona_id, price, commission, fecha_activacion)
|
||||||
|
VALUES (?, ?, ?, ?, ?)''', precios_historicos_extra)
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
# 3. PREPARACIÓN DE DATOS
|
# 3. PREPARACIÓN DE DATOS
|
||||||
c.execute("SELECT id, modulo_id, tipo FROM workers WHERE is_admin = 0")
|
c.execute("SELECT id, modulo_id, tipo FROM workers WHERE is_admin = 0")
|
||||||
all_workers_data = c.fetchall()
|
all_workers_data = c.fetchall()
|
||||||
|
|||||||
@@ -3,22 +3,53 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
|
|
||||||
const COLORS = ['#0d6efd', '#198754', '#dc3545', '#ffc107', '#0dcaf0'];
|
const COLORS = ['#0d6efd', '#198754', '#dc3545', '#ffc107', '#0dcaf0'];
|
||||||
let priceChartInstance = null;
|
let priceChartInstance = null;
|
||||||
|
let rawChartData = [];
|
||||||
|
let currentProdId = null;
|
||||||
|
let currentProdName = "";
|
||||||
|
|
||||||
window.showHistory = async function (prodId, prodName) {
|
window.showHistory = async function (prodId, prodName) {
|
||||||
|
currentProdId = prodId;
|
||||||
|
currentProdName = prodName;
|
||||||
|
|
||||||
const modal = new bootstrap.Modal(document.getElementById('chartModal'));
|
const modal = new bootstrap.Modal(document.getElementById('chartModal'));
|
||||||
document.getElementById('chartModalTitle').innerText = 'Fluctuación de Precio: ' + prodName;
|
document.getElementById('chartModalTitle').innerText = 'Fluctuación de Precio: ' + prodName;
|
||||||
modal.show();
|
modal.show();
|
||||||
|
|
||||||
const res = await fetch(`/admin/api/productos/${prodId}/historial`);
|
const res = await fetch(`/admin/api/productos/${prodId}/historial`);
|
||||||
const data = await res.json();
|
rawChartData = await res.json();
|
||||||
|
|
||||||
const zonas = [...new Set(data.map(d => d.zona))];
|
// Initialize dates in input fields if not set or reset
|
||||||
const fechas = [...new Set(data.map(d => d.fecha.split(' ')[0]))].sort();
|
const dates = rawChartData.map(d => d.fecha.split(' ')[0]);
|
||||||
|
if (dates.length > 0) {
|
||||||
|
document.getElementById('chartFilterDesde').value = dates[0];
|
||||||
|
document.getElementById('chartFilterHasta').value = dates[dates.length - 1];
|
||||||
|
} else {
|
||||||
|
document.getElementById('chartFilterDesde').value = '';
|
||||||
|
document.getElementById('chartFilterHasta').value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
renderChart();
|
||||||
|
};
|
||||||
|
|
||||||
|
function renderChart() {
|
||||||
|
const desde = document.getElementById('chartFilterDesde').value;
|
||||||
|
const hasta = document.getElementById('chartFilterHasta').value;
|
||||||
|
|
||||||
|
let filteredData = rawChartData;
|
||||||
|
if (desde) {
|
||||||
|
filteredData = filteredData.filter(d => d.fecha.split(' ')[0] >= desde);
|
||||||
|
}
|
||||||
|
if (hasta) {
|
||||||
|
filteredData = filteredData.filter(d => d.fecha.split(' ')[0] <= hasta);
|
||||||
|
}
|
||||||
|
|
||||||
|
const zonas = [...new Set(filteredData.map(d => d.zona))];
|
||||||
|
const fechas = [...new Set(filteredData.map(d => d.fecha.split(' ')[0]))].sort();
|
||||||
|
|
||||||
const datasets = zonas.map((zona, index) => {
|
const datasets = zonas.map((zona, index) => {
|
||||||
let lastPrice = 0;
|
let lastPrice = 0;
|
||||||
const dataPoints = fechas.map(f => {
|
const dataPoints = fechas.map(f => {
|
||||||
const hits = data.filter(d => d.zona === zona && d.fecha.startsWith(f));
|
const hits = filteredData.filter(d => d.zona === zona && d.fecha.startsWith(f));
|
||||||
if (hits.length > 0) {
|
if (hits.length > 0) {
|
||||||
lastPrice = hits[hits.length - 1].price;
|
lastPrice = hits[hits.length - 1].price;
|
||||||
}
|
}
|
||||||
@@ -51,5 +82,10 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
const btnFilter = document.getElementById('btnFilterChart');
|
||||||
|
if (btnFilter) {
|
||||||
|
btnFilter.addEventListener('click', renderChart);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user