diff --git a/app/Models/OrdenProduccion.php b/app/Models/OrdenProduccion.php index 21751e0..d4484ae 100644 --- a/app/Models/OrdenProduccion.php +++ b/app/Models/OrdenProduccion.php @@ -246,6 +246,116 @@ class OrdenProduccion extends Model $orden->tela_reservada = false; } - }); + }); } + + // Cantidad completada (desde procesos de acabados recibidos) + public function getRealizadoAttribute() + { + return (int) $this->procesosAcabado()->whereNotNull('fecha_recepcion')->sum('cantidad_recibida'); } + + // Faltante para completar la OP + public function getFaltantesAttribute() + { + return max(0, (int)$this->cantidad_total - $this->realizado); + } + + public function canBeFinalized(): bool + { + return $this->realizado >= (int)$this->cantidad_total; + } + + public function tryFinalize(): bool + { + if ($this->canBeFinalized()) { + $this->update(['estado' => 'finalizada']); + return true; + } + return false; + } + + public function avanzarEstado(): void + { + $flujo = [ + 'en_corte', + 'en_confeccion', + 'en_tintoreria', + 'en_acabados', + 'finalizada', + ]; + + $actual = array_search($this->estado, $flujo, true); + + if ($actual !== false && isset($flujo[$actual + 1])) { + $next = $flujo[$actual + 1]; + + // Si el siguiente estado es finalizada, verificar que esté completa + if ($next === 'finalizada' && ! $this->canBeFinalized()) { + return; // No avanzar a finalizada si no está completada + } + + $this->update([ + 'estado' => $next, + ]); + + // Si la orden llega a finalizada, crear entrada en inventario con lo que haya ingresado + if ($this->estado === 'finalizada') { + // Sumar procesos de acabados recibidos para determinar cantidad terminada + $cantidad = \App\Models\ProcesoAcabado::where('orden_produccion_id', $this->id) + ->whereNotNull('fecha_recepcion') + ->sum('cantidad_recibida'); + + // Crear inventario solo si hay traslados a bodega con cantidad + if ($cantidad > 0 && !\App\Models\InventarioPrenda::where('orden_produccion_id', $this->id)->exists()) { + // Determinar producto asociado: preferir producto_id en la OP, sino crear/buscar por prenda_modelo + $productoId = $this->producto_id; + + if (! $productoId) { + $nombre = $this->prenda_modelo ?? $this->referencia ?? null; + if ($nombre) { + // Generar código de barras único por defecto para productos creados automáticamente + $codigo = 'AUTOP-' . $this->id . '-' . time(); + $codigo = substr($codigo, 0, 50); + + // Asegurar unicidad + while (\App\Models\Producto::where('codigo_barras', $codigo)->exists()) { + $codigo .= '-' . rand(0, 9); + $codigo = substr($codigo, 0, 50); + } + + $producto = \App\Models\Producto::firstOrCreate( + ['nombre' => $nombre], + [ + 'descripcion' => 'Creado automáticamente desde OrdenProduccion #' . $this->id, + 'stock' => 0, + 'estado' => true, + 'precio_compra' => 0, + 'precio_venta' => 0, + 'unidad_medida' => 'unidad', + 'codigo_barras' => $codigo, + ] + ); + + $productoId = $producto->id; + + // Guardar vínculo en la OP para futuras referencias + $this->producto_id = $productoId; + $this->save(); + } + } + + \App\Models\InventarioPrenda::create([ + 'orden_produccion_id' => $this->id, + 'cantidad_terminada' => $cantidad, + 'cantidad_disponible' => $cantidad, + 'fecha_ingreso' => now(), + 'estado' => 'en_bodega', + 'producto_id' => $productoId ?? null, + ]); + + // Si se creó inventario, también actualizar stock del producto asociado (handler en InventarioPrenda lo hará) + } + } + } + } } }