diff --git a/app/Filament/Resources/TelaResource.php b/app/Filament/Resources/TelaResource.php index f29ffc3..e8d6c09 100644 --- a/app/Filament/Resources/TelaResource.php +++ b/app/Filament/Resources/TelaResource.php @@ -53,9 +53,6 @@ class TelaResource extends Resource $valor_total = $get('valor_total'); $metros_comprados = $state; - // Establecer automáticamente metros disponibles igual a metros comprados al crear/editar - $set('metros_disponibles', $metros_comprados); - if ($valor_total && $metros_comprados) { $costo_por_metro = $valor_total / $metros_comprados; $set('costo_por_metro', $costo_por_metro); @@ -75,10 +72,13 @@ class TelaResource extends Resource TextInput::make('costo_por_metro')->numeric()->prefix('$')->readOnly()->dehydrated()->default(0)->step(0.01), - TextInput::make('metros_disponibles')->numeric()->reactive()->disabled()->dehydrated() - ->default(function ($get) { - return $get('metros_comprados'); - })->helperText('Se establece automáticamente igual a "Metros comprados" al crear.'), + Forms\Components\Placeholder::make('metros_disponibles_display') + ->label('Metros disponibles') + ->content(function ($record) { + if (!$record) return 'Se calculará después de guardar'; + return number_format($record->metros_disponibles, 2) . ' m (Comprados - Usados en OPs)'; + }) + ->helperText('Este valor se calcula automáticamente: Metros comprados - Total usado en órdenes de producción'), DatePicker::make('fecha_compra')->required()->default(now()), diff --git a/app/Models/OrdenProduccion.php b/app/Models/OrdenProduccion.php index a261eef..d9f1fc6 100644 --- a/app/Models/OrdenProduccion.php +++ b/app/Models/OrdenProduccion.php @@ -104,7 +104,7 @@ class OrdenProduccion extends Model $orden->referencia = ''; } - // Reserva de tela al crear cuando la OP usa una tela: restar metros_disponibles inmediatamente + // Reserva de tela al crear cuando la OP usa una tela: validar disponibilidad if ($orden->tela_id && ($orden->metros_requeridos ?? 0) > 0) { $tela = \App\Models\Tela::find($orden->tela_id); if (! $tela) { @@ -113,70 +113,46 @@ class OrdenProduccion extends Model ]); } - if ($tela->metros_disponibles < $orden->metros_requeridos) { + // Calcular metros ya usados por otras OPs + $metrosUsados = \App\Models\OrdenProduccion::where('tela_id', $orden->tela_id)->sum('metros_requeridos'); + $disponible = max(0, $tela->metros_comprados - $metrosUsados); + + if ($disponible < $orden->metros_requeridos) { throw \Illuminate\Validation\ValidationException::withMessages([ - 'metros_requeridos' => 'No hay suficientes metros disponibles para reservar (' . $tela->metros_disponibles . ').', + 'metros_requeridos' => 'No hay suficientes metros disponibles para reservar (' . $disponible . ' disponibles).', ]); } - // Reservar: restar metros y marcar orden - $tela->metros_disponibles = $tela->metros_disponibles - $orden->metros_requeridos; - $tela->save(); - $orden->tela_reservada = true; } }); - // Validar y reservar tela al cambiar de estado a 'en_corte' + // Validar disponibilidad de tela al actualizar static::updating(function ($orden) { // Validación: si se especifica tela y metros_requeridos, verificar disponibilidad if ($orden->tela_id && $orden->metros_requeridos !== null) { $tela = \App\Models\Tela::find($orden->tela_id); $originalMetros = $orden->getOriginal('metros_requeridos') ?? 0; - $reservedAlready = $orden->tela_reservada ? $originalMetros : 0; - $available = $tela ? ($tela->metros_disponibles + $reservedAlready) : null; + + // Calcular metros usados por otras OPs (excluyendo esta OP) + $metrosUsadosOtros = \App\Models\OrdenProduccion::where('tela_id', $orden->tela_id) + ->where('id', '!=', $orden->id) + ->sum('metros_requeridos'); + + $disponible = max(0, $tela->metros_comprados - $metrosUsadosOtros); - if ($available !== null && $orden->metros_requeridos > $available) { + if ($orden->metros_requeridos > $disponible) { throw \Illuminate\Validation\ValidationException::withMessages([ - 'metros_requeridos' => 'No hay suficientes metros de tela disponibles. Disponibles: ' . ($available), + 'metros_requeridos' => 'No hay suficientes metros de tela disponibles. Disponibles: ' . $disponible, ]); } } - // Ajustes automáticos de reserva cuando cambia la tela o los metros requeridos - $originalTelaId = $orden->getOriginal('tela_id'); - $originalMetros = $orden->getOriginal('metros_requeridos') ?? 0; - $newTelaId = $orden->tela_id; - $newMetros = $orden->metros_requeridos ?? 0; - - // Si cambió la tela en la OP, devolver los metros reservados en la tela anterior (si aplica) - if ($originalTelaId && $originalTelaId != $newTelaId && $originalMetros > 0) { - $oldTela = \App\Models\Tela::find($originalTelaId); - if ($oldTela) { - $oldTela->metros_disponibles = $oldTela->metros_disponibles + $originalMetros; - $oldTela->save(); - } - } - - // Reservar metros en la nueva tela si se cambió - if ($newTelaId && $originalTelaId != $newTelaId && $newMetros > 0) { - $newTela = \App\Models\Tela::find($newTelaId); - if (! $newTela) { - throw \Illuminate\Validation\ValidationException::withMessages([ - 'tela_id' => 'No se encontró la tela asociada.', - ]); - } - - if ($newTela->metros_disponibles < $newMetros) { - throw \Illuminate\Validation\ValidationException::withMessages([ - 'metros_requeridos' => 'No hay suficientes metros disponibles para reservar (' . $newTela->metros_disponibles . ').', - ]); - } - - $newTela->metros_disponibles = $newTela->metros_disponibles - $newMetros; - $newTela->save(); + // Marcar como reservada si tiene tela y metros + if ($orden->tela_id && $orden->metros_requeridos > 0) { $orden->tela_reservada = true; } + }); // Si la misma tela y cambiaron los metros, ajustar la diferencia if ($originalTelaId == $newTelaId && $originalMetros != $newMetros && $newTelaId) { diff --git a/app/Models/Tela.php b/app/Models/Tela.php index fb85312..fbb553f 100644 --- a/app/Models/Tela.php +++ b/app/Models/Tela.php @@ -34,6 +34,14 @@ class Tela extends Model return $this->hasMany(OrdenProduccion::class); } + // Calcular metros disponibles dinámicamente + public function getMetrosDisponiblesAttribute() + { + $metrosComprados = (float) ($this->attributes['metros_comprados'] ?? 0); + $metrosUsados = (float) $this->ordenesProduccion()->sum('metros_requeridos'); + return max(0, $metrosComprados - $metrosUsados); + } + protected static function booted() { static::saving(function ($tela) {