schema([ Section::make('Información del Proceso') ->schema([ Select::make('orden_produccion_id') ->label('Orden de Producción') ->options(fn () => \App\Models\OrdenProduccion::all()->pluck('numero_orden', 'id')->toArray()) ->searchable() ->reactive() ->required() ->afterStateUpdated(function ($state, $set) { if ($state) { // Calcular cantidad disponible desde Tintorería (neto: recepciones - reprocesos - cobros) $tintoreriaRecords = \App\Models\Tintoreria::where('orden_produccion_id', $state)->get(); $disponible = 0; foreach ($tintoreriaRecords as $tintoreria) { $recepciones = (int) $tintoreria->recepciones()->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); $reprocesos = (int) $tintoreria->ajustes()->where('tipo', 'reproceso')->sum('cantidad'); $disponible += ($recepciones - $reprocesos); } // Restar lo que ya se envió a otros acabados $yaEnAcabados = \App\Models\ProcesoAcabado::where('orden_produccion_id', $state) ->sum('cantidad_enviada'); $disponible = max(0, $disponible - $yaEnAcabados); $set('cantidad_enviada', $disponible); $orden = \App\Models\OrdenProduccion::find($state); $set('prenda_nombre_info', $orden->prenda_modelo ?? 'Sin especificar'); } else { $set('prenda_nombre_info', null); } }), TextInput::make('prenda_nombre_info') ->label('Prenda') ->disabled() ->dehydrated(false) ->visible(fn ($get) => $get('orden_produccion_id') !== null) ->helperText('Nombre de la prenda de la orden de producción seleccionada'), TextInput::make('tipo_proceso') ->label('Tipo de proceso') ->placeholder('Ej: Planchado, Empacado, etc.') ->required(), TextInput::make('cantidad_enviada') ->label('Cantidad a enviar') ->numeric() ->required() ->minValue(1) ->reactive() ->helperText(function ($get) { $op_id = $get('orden_produccion_id'); if (!$op_id) return 'Selecciona una orden de producción primero'; // Calcular disponible neto desde Tintorería $tintoreriaRecords = \App\Models\Tintoreria::where('orden_produccion_id', $op_id)->get(); $disponible = 0; foreach ($tintoreriaRecords as $tintoreria) { $recepciones = (int) $tintoreria->recepciones()->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)')); $reprocesos = (int) $tintoreria->ajustes()->where('tipo', 'reproceso')->sum('cantidad'); $disponible += ($recepciones - $reprocesos); } // Restar lo que ya se envió a otros acabados $yaEnAcabados = \App\Models\ProcesoAcabado::where('orden_produccion_id', $op_id) ->sum('cantidad_enviada'); $disponible = max(0, $disponible - $yaEnAcabados); return 'Disponible desde Tintorería: ' . $disponible; }), DatePicker::make('fecha_envio') ->label('Fecha de envío') ->required() ->default(now()), ]) ->columns(2), Section::make('Distribución de Proveedores') ->description('Asigna la cantidad a enviar a cada proveedor') ->schema([ Forms\Components\Repeater::make('distribucion_proveedores') ->label('') ->schema([ Select::make('proveedor_id') ->label('Proveedor') ->options(\App\Models\Proveedor::where('categoria', 'empleado')->pluck('nombre', 'id')) ->searchable() ->required(), TextInput::make('cantidad') ->label('Cantidad') ->numeric() ->required() ->minValue(1) ->live() ->afterStateUpdated(function ($state, $set, $get) { // Validar que la suma no exceda el total disponible $total = (int) ($get('../../cantidad_enviada') ?? 0); $distribuciones = $get('../../distribucion_proveedores') ?? []; $suma = 0; foreach ($distribuciones as $dist) { $suma += (int) ($dist['cantidad'] ?? 0); } if ($suma > $total) { throw \Illuminate\Validation\ValidationException::withMessages([ 'cantidad' => "La suma de las distribuciones ({$suma}) excede el total disponible ({$total})." ]); } }), ]) ->columns(2) ->defaultItems(1) ->addActionLabel('Agregar otro proveedor') ->collapsible() ->cloneable() ->live() ->helperText(function ($get) { $total = (int) ($get('cantidad_enviada') ?? 0); $distribuciones = $get('distribucion_proveedores') ?? []; $suma = 0; foreach ($distribuciones as $dist) { $suma += (int) ($dist['cantidad'] ?? 0); } $restante = $total - $suma; if ($restante < 0) { return "⚠️ Excede el total por " . abs($restante) . " unidades"; } elseif ($restante > 0) { return "Faltan {$restante} unidades por distribuir"; } else { return "✓ Total distribuido correctamente"; } }), ]) ->collapsed(fn ($get) => !$get('distribucion_proveedores')), Section::make('Estado y Resumen') ->schema([ Forms\Components\Placeholder::make('resumen_estado') ->label('Resumen del Proceso') ->content(function ($get, $record) { if (!$record) { return 'Guarda el registro para ver el resumen'; } $enviadas = (int) ($record->cantidad_enviada ?? 0); $recibidas = $record->recibido_total ?? 0; $defectuosas = $record->perdidas_total ?? 0; $faltantes = $record->faltantes ?? 0; $estado = $record->estado_recepcion ?? 'Sin envío'; $html = '