diff --git a/app/Filament/Resources/InventarioPrendaResource.php b/app/Filament/Resources/InventarioPrendaResource.php index 1bc3248..cb28fdf 100644 --- a/app/Filament/Resources/InventarioPrendaResource.php +++ b/app/Filament/Resources/InventarioPrendaResource.php @@ -45,7 +45,19 @@ class InventarioPrendaResource extends Resource TextInput::make('cantidad_terminada') ->numeric() - ->required(), + ->required() + ->afterStateUpdated(function ($state, $set) { + // Mantener la cantidad disponible igual a la terminada al crear + $set('cantidad_disponible', $state); + }), + + Select::make('producto_id') + ->label('Producto (opcional)') + ->relationship('producto', 'nombre') + ->searchable() + ->preload() + ->nullable() + ->helperText('Si se selecciona, el stock del producto se incrementará automáticamente cuando se guarde.'), TextInput::make('cantidad_disponible') ->disabled() diff --git a/app/Filament/Resources/OrdenProduccionResource.php b/app/Filament/Resources/OrdenProduccionResource.php index 3b6bde2..71ae96f 100644 --- a/app/Filament/Resources/OrdenProduccionResource.php +++ b/app/Filament/Resources/OrdenProduccionResource.php @@ -59,6 +59,14 @@ class OrdenProduccionResource extends Resource ->preload() ->nullable(), + Select::make('producto_id') + ->label('Producto (opcional)') + ->relationship('producto', 'nombre') + ->searchable() + ->preload() + ->nullable() + ->helperText('Si no se selecciona, se intentará crear el producto automáticamente cuando la orden finalice.'), + TextInput::make('metros_requeridos') ->label('Metros requeridos') ->numeric() diff --git a/app/Models/InventarioPrenda.php b/app/Models/InventarioPrenda.php index f4c90b1..030c6d0 100644 --- a/app/Models/InventarioPrenda.php +++ b/app/Models/InventarioPrenda.php @@ -12,6 +12,7 @@ class InventarioPrenda extends Model 'cantidad_disponible', 'fecha_ingreso', 'estado', + 'producto_id', ]; public function ordenProduccion() @@ -19,6 +20,11 @@ class InventarioPrenda extends Model return $this->belongsTo(OrdenProduccion::class); } + public function producto() + { + return $this->belongsTo(\App\Models\Producto::class, 'producto_id'); + } + protected static function booted() { static::creating(function ($inventario) { @@ -36,6 +42,16 @@ class InventarioPrenda extends Model } $op = $inventario->ordenProduccion; + + // Priorizar producto explícito si fue seleccionado + if ($inventario->producto_id) { + $producto = \App\Models\Producto::find($inventario->producto_id); + if ($producto && ! $producto->variants()->exists()) { + $producto->increment('stock', $inventario->cantidad_terminada); + } + return; + } + if (! $op) { return; } diff --git a/app/Models/OrdenProduccion.php b/app/Models/OrdenProduccion.php index c64f2e8..bc099e2 100644 --- a/app/Models/OrdenProduccion.php +++ b/app/Models/OrdenProduccion.php @@ -15,6 +15,7 @@ class OrdenProduccion extends Model 'referencia', 'cantidad_total', 'tela_id', + 'producto_id', 'fecha_inicio', 'fecha_entrega_estimada', 'estado', @@ -52,6 +53,11 @@ class OrdenProduccion extends Model return $this->hasMany(\App\Models\InventarioPrenda::class); } + public function producto() + { + return $this->belongsTo(\App\Models\Producto::class, 'producto_id'); + } + public function avanzarEstado(): void { $flujo = [ @@ -78,13 +84,34 @@ class OrdenProduccion extends Model // 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) { + $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'] + ); + $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á) } } } diff --git a/database/migrations/2026_01_18_121500_add_producto_id_to_inventario_prendas.php b/database/migrations/2026_01_18_121500_add_producto_id_to_inventario_prendas.php new file mode 100644 index 0000000..84510f4 --- /dev/null +++ b/database/migrations/2026_01_18_121500_add_producto_id_to_inventario_prendas.php @@ -0,0 +1,23 @@ +foreignId('producto_id')->nullable()->constrained('productos')->nullOnDelete()->after('orden_produccion_id'); + }); + } + + public function down(): void + { + Schema::table('inventario_prendas', function (Blueprint $table) { + $table->dropForeign(['producto_id']); + $table->dropColumn('producto_id'); + }); + } +}; \ No newline at end of file diff --git a/database/migrations/2026_01_18_122500_add_producto_id_to_orden_produccions.php b/database/migrations/2026_01_18_122500_add_producto_id_to_orden_produccions.php new file mode 100644 index 0000000..48decf6 --- /dev/null +++ b/database/migrations/2026_01_18_122500_add_producto_id_to_orden_produccions.php @@ -0,0 +1,23 @@ +foreignId('producto_id')->nullable()->constrained('productos')->nullOnDelete()->after('tela_id'); + }); + } + + public function down(): void + { + Schema::table('orden_produccions', function (Blueprint $table) { + $table->dropForeign(['producto_id']); + $table->dropColumn('producto_id'); + }); + } +}; \ No newline at end of file