// Mock data for FLUX
const FLUXData = (() => {
const stores = [
{ id:'CDMX', name:'Tienda CDMX', city:'Ciudad de México', sales:2450230, salesDelta:18.2, breakages:-76, breakagesDelta:20.5, inventory:1245, rotation:24, alerts:2, lat:19.43, lng:-99.13, manager:'Lucía Reyes' },
{ id:'MTY', name:'Tienda Monterrey', city:'Monterrey', sales:1870540, salesDelta:14.7, breakages:-68, breakagesDelta:15.3, inventory:980, rotation:21, alerts:0, lat:25.67, lng:-100.31, manager:'Diego Salinas' },
{ id:'GDL', name:'Tienda Guadalajara', city:'Guadalajara', sales:1450330, salesDelta:11.3, breakages:-72, breakagesDelta:18.1, inventory:865, rotation:20, alerts:0, lat:20.66, lng:-103.34, manager:'Ana Cervantes' },
{ id:'PUE', name:'Tienda Puebla', city:'Puebla', sales:950120, salesDelta:9.8, breakages:-65, breakagesDelta:10.2, inventory:710, rotation:19, alerts:1, lat:19.04, lng:-98.20, manager:'Roberto Mejía' },
{ id:'CUN', name:'Tienda Cancún', city:'Cancún', sales:845300, salesDelta:8.1, breakages:-71, breakagesDelta:12.4, inventory:620, rotation:18, alerts:0, lat:21.16, lng:-86.85, manager:'Sofía Vargas' },
{ id:'TIJ', name:'Tienda Tijuana', city:'Tijuana', sales:780210, salesDelta:6.4, breakages:-58, breakagesDelta:7.9, inventory:540, rotation:17, alerts:1, lat:32.51, lng:-117.04, manager:'Mateo Ríos' },
{ id:'MID', name:'Tienda Mérida', city:'Mérida', sales:640150, salesDelta:12.1, breakages:-62, breakagesDelta:9.4, inventory:485, rotation:16, alerts:0, lat:20.97, lng:-89.62, manager:'Carla Montero' },
{ id:'QRO', name:'Tienda Querétaro', city:'Querétaro', sales:710480, salesDelta:15.6, breakages:-69, breakagesDelta:14.2, inventory:512, rotation:18, alerts:0, lat:20.59, lng:-100.39, manager:'Hugo Bautista' },
];
// 31 days of inventory + demand
const days = Array.from({length:31}, (_,i) => {
const t = i / 30;
const base = 28000 + Math.sin(i*0.42)*8500 + Math.cos(i*0.25)*3000;
const inventory = Math.round(base + (i===14 ? 1500 : 0));
const demand = Math.round(base*0.86 + Math.sin(i*0.55+1)*4000 - i*120);
return { day:i+1, label:`${i+1} may`, inventory, demand };
});
const categories = [
{ id:'electronica', name:'Electrónica', breakReduction:-82, demand:8200, color:'#F5A524' },
{ id:'hogar', name:'Hogar', breakReduction:-74, demand:5400, color:'#E8941A' },
{ id:'moda', name:'Moda', breakReduction:-66, demand:4900, color:'#D97706' },
{ id:'deportes', name:'Deportes', breakReduction:-65, demand:3100, color:'#B45309' },
{ id:'belleza', name:'Belleza', breakReduction:-58, demand:2530, color:'#92400E' },
];
const inventoryStatus = [
{ label:'Disponible', count:3215, pct:47, color:'#16A34A' },
{ label:'En tránsito', count:1128, pct:16, color:'#2563EB' },
{ label:'Reservado', count:1045, pct:15, color:'#7C3AED' },
{ label:'Sin stock', count:982, pct:14, color:'#DC2626' },
{ label:'Dañado', count:472, pct:7, color:'#F5A524' },
];
const channels = [
{ label:'Tienda física', count:12450, pct:52, color:'#F5A524' },
{ label:'E-commerce', count:7210, pct:30, color:'#E8941A' },
{ label:'Marketplaces', count:3350, pct:14, color:'#FCE9C2' },
{ label:'Otros', count:1120, pct:4, color:'#ECE6DC' },
];
const alerts = [
{ id:1, level:'critical', title:'Stock mínimo alcanzado', detail:'SKU-1248 · Tienda CDMX', time:'Hoy, 09:15', sku:'SKU-1248', store:'CDMX', action:'Solicitar reabasto' },
{ id:2, level:'critical', title:'Alta probabilidad de quiebre', detail:'SKU-8872 · Tienda Monterrey', time:'Hoy, 08:40', sku:'SKU-8872', store:'MTY', action:'Transferir desde GDL' },
{ id:3, level:'warning', title:'Retraso en entrega', detail:'PO-3392 · Proveedor ABC', time:'Ayer, 17:35', sku:'PO-3392', store:'—', action:'Contactar proveedor' },
{ id:4, level:'warning', title:'Variación inusual de demanda', detail:'SKU-2311 · Tienda Guadalajara', time:'Ayer, 14:20', sku:'SKU-2311', store:'GDL', action:'Revisar pronóstico' },
{ id:5, level:'info', title:'Nueva integración disponible', detail:'Conector Shopify v2.4', time:'Ayer, 11:02', sku:'—', store:'—', action:'Configurar' },
{ id:6, level:'critical', title:'Quiebre detectado', detail:'SKU-5519 · Tienda Puebla', time:'Hoy, 07:22', sku:'SKU-5519', store:'PUE', action:'Reabastecer urgente' },
{ id:7, level:'warning', title:'Caducidad próxima (30 días)', detail:'SKU-7104 · 142 unidades', time:'Ayer, 09:50', sku:'SKU-7104', store:'CDMX', action:'Promocionar' },
];
const integrations = [
{ id:'sap', name:'ERP · SAP S/4HANA', vendor:'SAP', kind:'ERP', status:'connected', last:'hace 2 min' },
{ id:'wms', name:'WMS · Manhattan', vendor:'Manhattan', kind:'WMS', status:'connected', last:'hace 5 min' },
{ id:'pos', name:'POS · Oracle Retail', vendor:'Oracle', kind:'POS', status:'connected', last:'hace 1 min' },
{ id:'pbi', name:'Power BI', vendor:'Microsoft', kind:'BI', status:'connected', last:'hace 12 min' },
{ id:'shopify', name:'Shopify Plus', vendor:'Shopify', kind:'E-commerce', status:'available', last:'—' },
{ id:'salesforce', name:'Salesforce CRM', vendor:'Salesforce', kind:'CRM', status:'available', last:'—' },
{ id:'slack', name:'Slack', vendor:'Slack', kind:'Comms', status:'connected', last:'hace 30 min' },
{ id:'twilio', name:'Twilio', vendor:'Twilio', kind:'SMS', status:'available', last:'—' },
];
// Top SKUs
const skus = [
{ sku:'SKU-1248', name:'Audífonos Bluetooth Pro X', category:'Electrónica', stock:8, threshold:50, sold30:412, forecast30:480, store:'CDMX', risk:0.92, price:1899, supplier:'TechCorp MX' },
{ sku:'SKU-8872', name:'Cafetera Espresso Compact', category:'Hogar', stock:14, threshold:60, sold30:298, forecast30:340, store:'MTY', risk:0.88, price:3499, supplier:'HomeWare SA' },
{ sku:'SKU-2311', name:'Mochila trail 28L', category:'Deportes', stock:142, threshold:80, sold30:188, forecast30:265, store:'GDL', risk:0.41, price:1290, supplier:'OutdoorMex' },
{ sku:'SKU-5519', name:'Smart TV 55" 4K', category:'Electrónica', stock:0, threshold:25, sold30:156, forecast30:175, store:'PUE', risk:0.99, price:12499, supplier:'TechCorp MX' },
{ sku:'SKU-7104', name:'Set crema facial AM/PM', category:'Belleza', stock:286, threshold:100, sold30:142, forecast30:130, store:'CDMX', risk:0.18, price:899, supplier:'BeautyLine' },
{ sku:'SKU-3382', name:'Tenis running W12', category:'Moda', stock:62, threshold:75, sold30:240, forecast30:280, store:'CDMX', risk:0.71, price:2199, supplier:'StrideMex' },
{ sku:'SKU-9920', name:'Aspiradora Inalámbrica V8', category:'Hogar', stock:38, threshold:40, sold30:95, forecast30:120, store:'MTY', risk:0.62, price:5499, supplier:'HomeWare SA' },
{ sku:'SKU-4471', name:'Bicicleta urbana 26"', category:'Deportes', stock:24, threshold:30, sold30:48, forecast30:62, store:'GDL', risk:0.55, price:6890, supplier:'OutdoorMex' },
{ sku:'SKU-6602', name:'Auriculares ANC studio', category:'Electrónica', stock:194, threshold:120, sold30:312, forecast30:340, store:'CUN', risk:0.34, price:2790, supplier:'TechCorp MX' },
{ sku:'SKU-1130', name:'Camisa lino slim', category:'Moda', stock:88, threshold:60, sold30:155, forecast30:170, store:'TIJ', risk:0.29, price:790, supplier:'TextilNorte' },
];
const suppliers = [
{ id:'TC', name:'TechCorp MX', contact:'Juan Marín', email:'jmarin@techcorp.mx', skus:142, otd:96, leadTime:7, rating:4.8, status:'active' },
{ id:'HW', name:'HomeWare SA', contact:'Patricia Lima', email:'plima@homeware.com', skus:88, otd:91, leadTime:11, rating:4.5, status:'active' },
{ id:'OM', name:'OutdoorMex', contact:'Tomás Rivas', email:'trivas@outdoormex.mx', skus:64, otd:88, leadTime:9, rating:4.3, status:'active' },
{ id:'BL', name:'BeautyLine', contact:'Renata Ojeda', email:'renata@beautyline.mx', skus:112, otd:94, leadTime:5, rating:4.7, status:'active' },
{ id:'SM', name:'StrideMex', contact:'Iván Pacheco', email:'ipacheco@stride.mx', skus:53, otd:82, leadTime:14, rating:3.9, status:'review' },
{ id:'TN', name:'TextilNorte', contact:'Adriana Solís', email:'asolis@textilnorte.mx', skus:96, otd:90, leadTime:10, rating:4.4, status:'active' },
{ id:'AB', name:'Proveedor ABC', contact:'Mario Quezada', email:'mario@abc.mx', skus:34, otd:74, leadTime:18, rating:3.4, status:'review' },
];
const users = [
{ name:'María González', role:'Admin', email:'maria@flux.mx', team:'Operaciones', status:'active', last:'En línea', avatar:'MG' },
{ name:'Lucía Reyes', role:'Manager', email:'lucia@flux.mx', team:'Tienda CDMX', status:'active', last:'hace 5 min', avatar:'LR' },
{ name:'Diego Salinas', role:'Manager', email:'diego@flux.mx', team:'Tienda MTY', status:'active', last:'hace 12 min', avatar:'DS' },
{ name:'Ana Cervantes', role:'Manager', email:'ana@flux.mx', team:'Tienda GDL', status:'active', last:'hace 30 min', avatar:'AC' },
{ name:'Bruno Aldama', role:'Analyst', email:'bruno@flux.mx', team:'Analytics', status:'active', last:'hace 1 h', avatar:'BA' },
{ name:'Sofía Vargas', role:'Manager', email:'sofia@flux.mx', team:'Tienda CUN', status:'active', last:'hace 3 h', avatar:'SV' },
{ name:'Roberto Mejía', role:'Manager', email:'roberto@flux.mx', team:'Tienda PUE', status:'active', last:'hace 1 d', avatar:'RM' },
{ name:'Karla Núñez', role:'Viewer', email:'karla@flux.mx', team:'Finanzas', status:'invited', last:'—', avatar:'KN' },
];
// Forecast data — 60d historical + 30d forecast
const forecast = (() => {
const arr = [];
for(let i=0;i<90;i++){
const t = i;
const base = 22000 + Math.sin(t*0.18)*5000 + Math.cos(t*0.09)*3000 + t*45;
arr.push({
day:i+1,
actual: i<60 ? Math.round(base + (Math.sin(t*1.3)*1500)) : null,
forecast: i>=58 ? Math.round(base + Math.sin(t*0.2)*1000) : null,
upper: i>=58 ? Math.round(base*1.08 + Math.sin(t*0.2)*1000 + 1500) : null,
lower: i>=58 ? Math.round(base*0.92 + Math.sin(t*0.2)*1000 - 1500) : null,
});
}
return arr;
})();
// AI insights
const insights = [
{ id:1, severity:'high', icon:'Sparkles', title:'Transferencia recomendada', body:'SKU-8872 (Cafetera Espresso) tiene 14 u. en MTY con riesgo 88% de quiebre, y 67 u. en GDL con baja rotación. Transferir 25 u. equilibraría ambas tiendas.', cta:'Ejecutar transferencia' },
{ id:2, severity:'high', icon:'Brain', title:'Patrón estacional detectado', body:'La demanda de Electrónica en Cancún sube 34% durante temporada de cruceros (mayo-jun). Sugiero subir cobertura de SKU-6602 a 240 u. antes del 20 may.', cta:'Aplicar pronóstico' },
{ id:3, severity:'medium', icon:'Target', title:'Promoción inteligente', body:'SKU-7104 tiene 286 u. y caducidad en 30 días. Una promoción 2x1 absorbería el inventario en ~9 días y mantendría margen ≥18%.', cta:'Crear promoción' },
{ id:4, severity:'medium', icon:'Activity', title:'Anomalía de tráfico', body:'Tienda Tijuana muestra -23% de tráfico los miércoles vs. promedio. Posible problema operativo o de horarios.', cta:'Investigar' },
];
return { stores, days, categories, inventoryStatus, channels, alerts, integrations, skus, suppliers, users, forecast, insights };
})();
window.FLUXData = FLUXData;