Skip to main content

Overview

P.FLEX tracks critical manufacturing KPIs in real-time to enable data-driven decision making and continuous improvement. All metrics are calculated from live production data with automated alerting on threshold violations.
KPI calculations are updated automatically as production data flows from operator reports, machine sensors, and quality inspections.

Core Production KPIs

OEE (Overall Equipment Effectiveness)

Current Value: 84.2% (Target: 85%) From report-list.component.ts:49-61:
<div class="text-4xl font-black text-white tracking-tight">84.2%</div>
<div class="w-full bg-slate-700/50 h-1.5 rounded-full mt-4 overflow-hidden">
  <div class="bg-emerald-500 h-full rounded-full" style="width: 84.2%"></div>
</div>
<p class="text-[10px] text-slate-500 mt-2 font-mono">Meta: 85%</p>
OEE = Availability × Performance × QualityWhere:
  • Availability = (Operating Time / Planned Production Time)
  • Performance = (Actual Output / Theoretical Max Output)
  • Quality = (Good Units / Total Units Produced)
Example:
const availability = 0.92;    // 92% uptime
const performance = 0.95;     // 95% speed efficiency
const quality = 0.96;         // 96% good units
const oee = availability * performance * quality;
// = 0.92 × 0.95 × 0.96 = 0.8389 (83.89%)

Production Volume (Linear Meters)

Current Value: Real-time aggregation from all work orders From report-list.component.ts:230-245:
let totalMeters = 0;
let totalWaste = 0;

ots.forEach(ot => {
  const mtl = parseFloat(String(ot.total_mtl || '0').replace(/,/g, ''));
  const waste = parseFloat(String(ot.merma || '0').replace(/,/g, ''));
  
  const qty = parseFloat(String(ot['CANT PED'] || '0'));
  const simulatedMeters = mtl > 0 ? mtl : (qty > 0 ? qty * 0.1 : 0);
  const simulatedWaste = waste > 0 ? waste : simulatedMeters * (0.02 + Math.random() * 0.03);
  
  if (ot.Estado_pedido !== 'PENDIENTE') {
    totalMeters += simulatedMeters;
    totalWaste += simulatedWaste;
  }
});

return {
  totalMeters: Math.round(totalMeters),
  wastePercentage: ((totalWaste / totalMeters) * 100).toFixed(1)
};
  • total_mtl field from work orders
  • Operator-reported production from print/diecut reports
  • Real-time machine counters (when available)
// Priority:
// 1. Use total_mtl if available (most accurate)
// 2. Fall back to quantity * 0.1 conversion factor
// 3. Exclude PENDIENTE orders (not yet started)

const simulatedMeters = mtl > 0 
  ? mtl 
  : (qty > 0 ? qty * 0.1 : 0);

Waste Rate (Tasa de Mermas)

Current Value: Real-time calculation (Target: <3%) From report-list.component.ts:78-89:
<div class="text-4xl font-black text-red-500 tracking-tight">
  {{ stats.wastePercentage }}%
</div>
<div class="w-full bg-slate-700/50 h-1.5 rounded-full mt-4 overflow-hidden">
  <div class="bg-red-500 h-full rounded-full" 
       [style.width.%]="stats.wastePercentage"></div>
</div>
<p class="text-[10px] text-slate-500 mt-2 font-mono">Objetivo: < 3%</p>
Formula:
const wastePercentage = totalMeters > 0 
  ? ((totalWaste / totalMeters) * 100).toFixed(1) 
  : '0.0';
Waste rates exceeding 5% trigger critical alerts and require immediate incident reporting with root cause analysis.

Critical Waste Identification

From report-list.component.ts:259-278:
get topWasteItems() {
  return this.ordersService.ots
    .filter(ot => 
      ot.Estado_pedido === 'FINALIZADO' || 
      ot.Estado_pedido === 'EN PROCESO'
    )
    .map(ot => {
      const mtl = parseFloat(String(ot.total_mtl || '0'));
      const waste = parseFloat(String(ot.merma || '0'));
      const percentage = ((waste / mtl) * 100).toFixed(1);
      
      return {
        ot: ot.OT,
        client: ot['Razon Social'],
        total: Math.round(mtl),
        waste: Math.round(waste),
        percentage: parseFloat(percentage)
      };
    })
    .sort((a, b) => b.percentage - a.percentage)  // Worst first
    .slice(0, 5);  // Top 5
}
Waste Categories:
  • Acceptable: <3% (normal production variance)
  • Warning: 3-5% (requires investigation)
  • Critical: >5% (ALTO flag, immediate action)

OTD (On-Time Delivery)

Current Value: 95.8% (Last 30 days) From report-list.component.ts:92-105:
<div class="text-4xl font-black text-white tracking-tight">95.8%</div>
<p class="text-[10px] text-slate-500 mt-2 font-mono text-right">Últimos 30 días</p>
Calculation Methodology:
// Pseudo-code (actual implementation in backend)
const deliveredOnTime = orders.filter(o => 
  o.deliveryDate <= o.promisedDate && 
  o.status === 'DESPACHADO'
).length;

const totalDelivered = orders.filter(o => 
  o.status === 'DESPACHADO'
).length;

const otd = (deliveredOnTime / totalDelivered) * 100;
Industry benchmark for flexographic packaging: >95% OTD. P.FLEX currently meets this standard.

Order Status Metrics

From report-list.component.ts:225-228:
const pending = ots.filter(o => o.Estado_pedido === 'PENDIENTE').length;
const inProgress = ots.filter(o => o.Estado_pedido === 'EN PROCESO').length;
const paused = ots.filter(o => o.Estado_pedido === 'PAUSADA').length;
const completed = ots.filter(o => o.Estado_pedido === 'FINALIZADO').length;

Pendientes (Pending)

Orders awaiting production start
  • Scheduled but not released
  • Material not yet available
  • Machine not yet assigned

En Proceso (In Progress)

Currently in production
  • Material issued
  • Machine assigned and running
  • Operator actively producing

Pausadas (Paused)

Temporarily stopped
  • Awaiting material replenishment
  • Quality hold
  • Scheduled break or changeover

Finalizadas (Completed)

Production completed
  • Quality approved
  • Ready for packaging/shipping
  • Metrics finalized

Production Trend Analysis

Daily Trend Data

From report-list.component.ts:212-220:
trendData = [
  { day: 'Lun', value: 18500 },
  { day: 'Mar', value: 22400 },
  { day: 'Mié', value: 35000 },  // Peak (meets target)
  { day: 'Jue', value: 28900 },
  { day: 'Vie', value: 31200 },
  { day: 'Sáb', value: 15600 },  // Reduced shift
  { day: 'Dom', value: 8000 }    // Minimal operations
];
Target Line: 35,000 meters/day (shown as dashed line on chart) From report-list.component.ts:409-417:
const targetY = y(35000);
svg.append('line')
  .attr('x1', margin.left)
  .attr('x2', width - margin.right)
  .attr('y1', targetY)
  .attr('y2', targetY)
  .attr('stroke', 'rgba(255,255,255,0.1)')
  .attr('stroke-dasharray', '5,5');

Capacity Utilization

// Weekly production vs capacity
const weeklyProduction = trendData.reduce((sum, day) => sum + day.value, 0);
const weeklyCapacity = 35000 * 7;  // 245,000m
const utilization = (weeklyProduction / weeklyCapacity) * 100;
// = (159,500 / 245,000) * 100 = 65.1%
65% Utilization:
  • Normal for 5-day + reduced weekend operation
  • Opportunity to increase weekend production if demand exists
  • Balance between capacity and maintenance windows

Tooling Utilization KPIs

Die Status Distribution

From inventory-die.component.ts:454-460:
get stats() {
  const total = this.dieItems.length;
  const available = this.dieItems.filter(d => d.estado === 'OK').length;
  const maintenance = this.dieItems.filter(d => 
    d.estado === 'Reparacion' || d.estado === 'Mantenimiento'
  ).length;
  const critical = this.dieItems.filter(d => 
    d.estado === 'Dañado' || d.estado === 'Desgaste'
  ).length;
  return { total, available, maintenance, critical };
}
KPIs:
  • Availability Rate: (available / total) * 100
  • Maintenance Rate: (maintenance / total) * 100
  • Critical Rate: (critical / total) * 100 (should be <5%)

Total Troqueles

Complete inventory count

Disponibles

Ready for immediate use

Uso Crítico

Requiring urgent attention

Quality Metrics

Incident Distribution

From quality.service.ts:52-53:
get activeIncidents() { 
  return this.incidents.filter(i => i.status !== 'Cerrada'); 
}

get closedIncidents() { 
  return this.incidents.filter(i => i.status === 'Cerrada'); 
}
KPIs:
  • Open Incident Rate: Active incidents / Total production orders
  • Mean Time to Resolution (MTTR): Average days from report to closure
  • Recurrence Rate: Incidents with similar root causes

CAPA Completion Rate

// Calculate CAPA effectiveness
const allActions = incidents.flatMap(i => i.actions);
const completedActions = allActions.filter(a => a.completed);
const capaCompletion = (completedActions.length / allActions.length) * 100;

// On-time completion
const onTimeActions = completedActions.filter(a => 
  new Date(a.completionDate) <= new Date(a.deadline)
);
const onTimeRate = (onTimeActions.length / completedActions.length) * 100;

Performance Benchmarks

Industry Averages (2024):
  • OEE: 60-75%
  • Waste Rate: 4-7%
  • OTD: 85-92%
  • Changeover Time: 45-90 minutes
P.FLEX Performance:
  • OEE: 84.2% ✓ Above average
  • Waste Rate: Variable (monitor daily)
  • OTD: 95.8% ✓ Excellent

Export and Reporting

Excel KPI Export Structure

From report-list.component.ts:293-307:
const kpiData = [
  ['REPORTE DE INDICADORES DE PLANTA', dateStr],
  [''],
  ['METRICAS GENERALES'],
  ['Eficiencia Global (OEE)', '84.2%'],
  ['Producción Total (m)', stats.totalMeters],
  ['Tasa de Mermas (%)', stats.wastePercentage + '%'],
  ['Pedidos a Tiempo (OTD)', '95.8%'],
  [''],
  ['ESTADO DE ORDENES'],
  ['Pendientes', stats.pending],
  ['En Proceso', stats.inProgress],
  ['Finalizados', stats.completed],
  ['Pausadas', stats.paused]
];

Best Practices

Morning Shift Meeting (15 minutes):
  1. Review previous day’s OEE and waste
  2. Identify top 3 waste contributors
  3. Check for overdue CAPA actions
  4. Set daily production target
Friday Production Review:
  • Export weekly Excel report
  • Compare against same week last month/year
  • Identify improvement opportunities
  • Update preventive maintenance schedule
Export PDF Dashboard:
  • OEE trend vs target
  • Top 10 waste contributors (cumulative)
  • Incident closure rate
  • Tooling replacement forecast
Root Cause Analysis Triggers:
  • OEE drops below 80% for 3+ consecutive days
  • Any order with >8% waste
  • OTD falls below 93%
  • More than 2 critical tooling items

Analytics Reports

Visual dashboards and trend charts

Quality Incidents

Track and resolve performance issues

Production Orders

Order-level performance data

Build docs developers (and LLMs) love