up
This commit is contained in:
@@ -4,13 +4,13 @@ namespace App\Filament\Resources;
|
|||||||
|
|
||||||
use App\Filament\Resources\OjalPresillaResource\Pages;
|
use App\Filament\Resources\OjalPresillaResource\Pages;
|
||||||
use App\Models\Ojal;
|
use App\Models\Ojal;
|
||||||
use App\Models\Prensilla;
|
|
||||||
use Filament\Forms;
|
use Filament\Forms;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Tables;
|
use Filament\Tables;
|
||||||
use Filament\Forms\Components\Select;
|
use Filament\Forms\Components\Select;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
use Filament\Forms\Components\DatePicker;
|
use Filament\Forms\Components\Repeater;
|
||||||
|
use Filament\Forms\Components\Checkbox;
|
||||||
use Filament\Tables\Filters\SelectFilter;
|
use Filament\Tables\Filters\SelectFilter;
|
||||||
|
|
||||||
class OjalPresillaResource extends Resource
|
class OjalPresillaResource extends Resource
|
||||||
@@ -29,124 +29,142 @@ class OjalPresillaResource extends Resource
|
|||||||
public static function form(Forms\Form $form): Forms\Form
|
public static function form(Forms\Form $form): Forms\Form
|
||||||
{
|
{
|
||||||
return $form->schema([
|
return $form->schema([
|
||||||
Select::make('tipo')
|
|
||||||
->label('Tipo')
|
|
||||||
->options([
|
|
||||||
'ojal' => 'Ojal',
|
|
||||||
'prensilla' => 'Prensilla',
|
|
||||||
])
|
|
||||||
->required()
|
|
||||||
->live()
|
|
||||||
->afterStateUpdated(fn ($set) => $set('proveedor_id', null)),
|
|
||||||
|
|
||||||
Select::make('proveedor_id')
|
|
||||||
->label('Proveedor')
|
|
||||||
->options(function ($get) {
|
|
||||||
$tipo = $get('tipo') ?? 'prensilla_ojal';
|
|
||||||
return \App\Models\Proveedor::where('categoria', 'prensilla_ojal')->pluck('nombre', 'id');
|
|
||||||
})
|
|
||||||
->searchable()
|
|
||||||
->preload()
|
|
||||||
->nullable(),
|
|
||||||
|
|
||||||
Select::make('orden_produccion_id')
|
Select::make('orden_produccion_id')
|
||||||
->label('Orden de Producción')
|
->label('Orden de Producción')
|
||||||
->relationship('ordenProduccion', 'numero_orden')
|
->options(function () {
|
||||||
|
// Solo OPs que tienen confecciones recibidas
|
||||||
|
return \App\Models\OrdenProduccion::whereHas('confecciones', function ($q) {
|
||||||
|
$q->where('cantidad_recibida', '>', 0);
|
||||||
|
})->get()->mapWithKeys(function ($op) {
|
||||||
|
$recibido = $op->confecciones->sum('cantidad_recibida');
|
||||||
|
return [$op->id => "{$op->numero_orden} ({$recibido} prendas recibidas)"];
|
||||||
|
});
|
||||||
|
})
|
||||||
->searchable()
|
->searchable()
|
||||||
->preload()
|
->required()
|
||||||
->required(),
|
->live()
|
||||||
|
->afterStateUpdated(function ($state, $set) {
|
||||||
|
if ($state) {
|
||||||
|
$op = \App\Models\OrdenProduccion::find($state);
|
||||||
|
if ($op) {
|
||||||
|
$recibido = $op->confecciones->sum('cantidad_recibida');
|
||||||
|
$set('cantidad_enviada', $recibido);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
DatePicker::make('fecha_envio')
|
TextInput::make('tipo')
|
||||||
->label('Fecha de envío')
|
->label('Tipo')
|
||||||
->default(now())
|
->placeholder('Ej: Ojal, Prensilla, Botón, etc.')
|
||||||
->required(),
|
->required()
|
||||||
|
->helperText('Especifica el tipo de accesorio'),
|
||||||
|
|
||||||
TextInput::make('cantidad_enviada')
|
TextInput::make('cantidad_enviada')
|
||||||
->label('Cantidad enviada')
|
->label('Cantidad total')
|
||||||
->numeric()
|
->numeric()
|
||||||
->required()
|
->readOnly()
|
||||||
->minValue(1),
|
->helperText('Se calcula automáticamente desde confecciones recibidas'),
|
||||||
|
|
||||||
DatePicker::make('fecha_recepcion')
|
Repeater::make('distribuciones')
|
||||||
->label('Fecha de recepción'),
|
->label('Distribución entre proveedores')
|
||||||
|
->schema([
|
||||||
|
Select::make('proveedor_id')
|
||||||
|
->label('Proveedor')
|
||||||
|
->options(fn () => \App\Models\Proveedor::where('categoria', 'prensilla_ojal')->pluck('nombre', 'id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
|
||||||
TextInput::make('cantidad_recibida')
|
TextInput::make('cantidad')
|
||||||
->label('Cantidad recibida')
|
->label('Cantidad')
|
||||||
->numeric()
|
->numeric()
|
||||||
->nullable(),
|
->required()
|
||||||
|
->minValue(1),
|
||||||
|
])
|
||||||
|
->defaultItems(1)
|
||||||
|
->addActionLabel('Agregar proveedor')
|
||||||
|
->helperText('Puedes distribuir la cantidad entre varios proveedores'),
|
||||||
|
|
||||||
TextInput::make('perdidas')
|
Checkbox::make('terminada')
|
||||||
->label('Pérdidas')
|
->label('Marcar como terminada')
|
||||||
->numeric()
|
->helperText('Al marcar terminada, se enviará automáticamente a tintorería')
|
||||||
->default(0),
|
->live(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function table(Tables\Table $table): Tables\Table
|
public static function table(Tables\Table $table): Tables\Table
|
||||||
{
|
{
|
||||||
return $table
|
return $table
|
||||||
->modifyQueryUsing(function ($query) {
|
|
||||||
// Union de ambas tablas
|
|
||||||
$ojales = \App\Models\Ojal::select([
|
|
||||||
'id',
|
|
||||||
'proveedor_id',
|
|
||||||
'orden_produccion_id',
|
|
||||||
'fecha_envio',
|
|
||||||
'cantidad_enviada',
|
|
||||||
'fecha_recepcion',
|
|
||||||
'cantidad_recibida',
|
|
||||||
'perdidas',
|
|
||||||
'created_at',
|
|
||||||
\DB::raw("'ojal' as tipo")
|
|
||||||
]);
|
|
||||||
|
|
||||||
$prensillas = \App\Models\Prensilla::select([
|
|
||||||
'id',
|
|
||||||
'proveedor_id',
|
|
||||||
'orden_produccion_id',
|
|
||||||
'fecha_envio',
|
|
||||||
'cantidad_enviada',
|
|
||||||
'fecha_recepcion',
|
|
||||||
'cantidad_recibida',
|
|
||||||
'perdidas',
|
|
||||||
'created_at',
|
|
||||||
\DB::raw("'prensilla' as tipo")
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $query->from(\DB::raw("({$ojales->toSql()} UNION ALL {$prensillas->toSql()}) as combined"))
|
|
||||||
->mergeBindings($ojales->getQuery())
|
|
||||||
->mergeBindings($prensillas->getQuery());
|
|
||||||
})
|
|
||||||
->columns([
|
->columns([
|
||||||
Tables\Columns\TextColumn::make('tipo')
|
Tables\Columns\TextColumn::make('tipo')
|
||||||
|
->label('Tipo')
|
||||||
|
->searchable()
|
||||||
|
->sortable()
|
||||||
->badge()
|
->badge()
|
||||||
->color(fn (string $state): string => match ($state) {
|
->color('info'),
|
||||||
'ojal' => 'info',
|
|
||||||
'prensilla' => 'success',
|
|
||||||
})
|
|
||||||
->formatStateUsing(fn (string $state): string => ucfirst($state)),
|
|
||||||
|
|
||||||
Tables\Columns\TextColumn::make('proveedor_id')
|
Tables\Columns\TextColumn::make('ordenProduccion.numero_orden')
|
||||||
->label('Proveedor')
|
|
||||||
->formatStateUsing(fn ($state) => \App\Models\Proveedor::find($state)?->nombre ?? 'N/A'),
|
|
||||||
|
|
||||||
Tables\Columns\TextColumn::make('orden_produccion_id')
|
|
||||||
->label('OP')
|
->label('OP')
|
||||||
->formatStateUsing(fn ($state) => \App\Models\OrdenProduccion::find($state)?->numero_orden ?? 'N/A'),
|
->searchable()
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
Tables\Columns\TextColumn::make('cantidad_enviada')->label('Enviadas'),
|
Tables\Columns\TextColumn::make('cantidad_enviada')
|
||||||
Tables\Columns\TextColumn::make('cantidad_recibida')->label('Recibidas'),
|
->label('Cantidad')
|
||||||
Tables\Columns\TextColumn::make('perdidas')->label('Pérdidas'),
|
->sortable(),
|
||||||
Tables\Columns\TextColumn::make('fecha_envio')->date()->label('F. Envío'),
|
|
||||||
Tables\Columns\TextColumn::make('fecha_recepcion')->date()->label('F. Recepción'),
|
Tables\Columns\TextColumn::make('proveedor.nombre')
|
||||||
|
->label('Proveedor')
|
||||||
|
->searchable()
|
||||||
|
->default('Sin asignar'),
|
||||||
|
|
||||||
|
Tables\Columns\IconColumn::make('terminada')
|
||||||
|
->boolean()
|
||||||
|
->label('Terminada')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
|
Tables\Columns\TextColumn::make('fecha_envio')
|
||||||
|
->date()
|
||||||
|
->label('Fecha envío')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
|
Tables\Columns\TextColumn::make('created_at')
|
||||||
|
->dateTime()
|
||||||
|
->label('Creado')
|
||||||
|
->sortable()
|
||||||
|
->toggleable(isToggledHiddenByDefault: true),
|
||||||
])
|
])
|
||||||
->filters([
|
->filters([
|
||||||
SelectFilter::make('tipo')
|
SelectFilter::make('tipo')
|
||||||
|
->label('Tipo'),
|
||||||
|
|
||||||
|
SelectFilter::make('terminada')
|
||||||
->options([
|
->options([
|
||||||
'ojal' => 'Ojal',
|
'0' => 'Pendiente',
|
||||||
'prensilla' => 'Prensilla',
|
'1' => 'Terminada',
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
->actions([
|
||||||
|
Tables\Actions\EditAction::make(),
|
||||||
|
Tables\Actions\Action::make('marcar_terminada')
|
||||||
|
->label('Terminar')
|
||||||
|
->icon('heroicon-o-check-circle')
|
||||||
|
->color('success')
|
||||||
|
->visible(fn ($record) => !$record->terminada)
|
||||||
|
->action(function ($record) {
|
||||||
|
$record->terminada = true;
|
||||||
|
$record->save();
|
||||||
|
|
||||||
|
\Filament\Notifications\Notification::make()
|
||||||
|
->success()
|
||||||
|
->title('Marcado como terminado')
|
||||||
|
->body('Se ha creado automáticamente el envío a tintorería')
|
||||||
|
->send();
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
->bulkActions([
|
||||||
|
Tables\Actions\BulkActionGroup::make([
|
||||||
|
Tables\Actions\DeleteBulkAction::make(),
|
||||||
|
]),
|
||||||
|
])
|
||||||
->defaultSort('created_at', 'desc');
|
->defaultSort('created_at', 'desc');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,48 @@ class CreateOjalPresilla extends CreateRecord
|
|||||||
|
|
||||||
protected function mutateFormDataBeforeCreate(array $data): array
|
protected function mutateFormDataBeforeCreate(array $data): array
|
||||||
{
|
{
|
||||||
$tipo = $data['tipo'] ?? 'ojal';
|
$distribuciones = $data['distribuciones'] ?? [];
|
||||||
unset($data['tipo']);
|
$tipo = $data['tipo'] ?? 'accesorio';
|
||||||
|
$ordenProduccionId = $data['orden_produccion_id'];
|
||||||
|
$cantidadTotal = $data['cantidad_enviada'];
|
||||||
|
$terminada = $data['terminada'] ?? false;
|
||||||
|
|
||||||
// Guardar en la tabla correspondiente
|
// Validar que las distribuciones sumen la cantidad total
|
||||||
if ($tipo === 'prensilla') {
|
$sumaDistribucion = array_sum(array_column($distribuciones, 'cantidad'));
|
||||||
$record = \App\Models\Prensilla::create($data);
|
if ($sumaDistribucion != $cantidadTotal) {
|
||||||
} else {
|
throw \Illuminate\Validation\ValidationException::withMessages([
|
||||||
$record = \App\Models\Ojal::create($data);
|
'distribuciones' => "La suma de las distribuciones ({$sumaDistribucion}) debe ser igual a la cantidad total ({$cantidadTotal})."
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear un registro por cada proveedor
|
||||||
|
foreach ($distribuciones as $distribucion) {
|
||||||
|
\App\Models\Ojal::create([
|
||||||
|
'proveedor_id' => $distribucion['proveedor_id'],
|
||||||
|
'orden_produccion_id' => $ordenProduccionId,
|
||||||
|
'tipo' => $tipo,
|
||||||
|
'fecha_envio' => now(),
|
||||||
|
'cantidad_enviada' => $distribucion['cantidad'],
|
||||||
|
'terminada' => $terminada,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirigir al listado
|
// Redirigir al listado
|
||||||
$this->redirect(OjalPresillaResource::getUrl('index'));
|
$this->redirect(OjalPresillaResource::getUrl('index'));
|
||||||
|
|
||||||
return $data;
|
// Retornar vacío para evitar que Filament intente crear el registro automáticamente
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function afterCreate(): void
|
||||||
|
{
|
||||||
|
// Ya se crearon los registros en mutateFormDataBeforeCreate
|
||||||
|
// Redirigir al index
|
||||||
|
$this->redirect(OjalPresillaResource::getUrl('index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRedirectUrl(): string
|
||||||
|
{
|
||||||
|
return OjalPresillaResource::getUrl('index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,17 @@ class Ojal extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'proveedor_id',
|
'proveedor_id',
|
||||||
'orden_produccion_id',
|
'orden_produccion_id',
|
||||||
|
'tipo',
|
||||||
'fecha_envio',
|
'fecha_envio',
|
||||||
'cantidad_enviada',
|
'cantidad_enviada',
|
||||||
'fecha_recepcion',
|
'fecha_recepcion',
|
||||||
'cantidad_recibida',
|
'cantidad_recibida',
|
||||||
'perdidas',
|
'perdidas',
|
||||||
|
'terminada',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'terminada' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function proveedor()
|
public function proveedor()
|
||||||
@@ -41,5 +47,17 @@ class Ojal extends Model
|
|||||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad_enviada' => 'No hay suficientes unidades disponibles desde confecciones para asignar.']);
|
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad_enviada' => 'No hay suficientes unidades disponibles desde confecciones para asignar.']);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static::saved(function ($registro) {
|
||||||
|
// Si se marca como terminada, crear traslado automático a tintororía
|
||||||
|
if ($registro->terminada && !$registro->getOriginal('terminada')) {
|
||||||
|
\App\Models\Tintoreria::create([
|
||||||
|
'orden_produccion_id' => $registro->orden_produccion_id,
|
||||||
|
'fecha_envio' => now(),
|
||||||
|
'cantidad_enviada' => $registro->cantidad_enviada,
|
||||||
|
'observaciones' => "Auto-enviado desde {$registro->tipo} (ID: {$registro->id})",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,17 @@ class Prensilla extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'proveedor_id',
|
'proveedor_id',
|
||||||
'orden_produccion_id',
|
'orden_produccion_id',
|
||||||
|
'tipo',
|
||||||
'fecha_envio',
|
'fecha_envio',
|
||||||
'cantidad_enviada',
|
'cantidad_enviada',
|
||||||
'fecha_recepcion',
|
'fecha_recepcion',
|
||||||
'cantidad_recibida',
|
'cantidad_recibida',
|
||||||
'perdidas',
|
'perdidas',
|
||||||
|
'terminada',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'terminada' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function proveedor()
|
public function proveedor()
|
||||||
@@ -39,5 +45,17 @@ class Prensilla extends Model
|
|||||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad_enviada' => 'No hay suficientes unidades disponibles desde confecciones para asignar.']);
|
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad_enviada' => 'No hay suficientes unidades disponibles desde confecciones para asignar.']);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static::saved(function ($registro) {
|
||||||
|
// Si se marca como terminada, crear traslado automático a tintororía
|
||||||
|
if ($registro->terminada && !$registro->getOriginal('terminada')) {
|
||||||
|
\App\Models\Tintoreria::create([
|
||||||
|
'orden_produccion_id' => $registro->orden_produccion_id,
|
||||||
|
'fecha_envio' => now(),
|
||||||
|
'cantidad_enviada' => $registro->cantidad_enviada,
|
||||||
|
'observaciones' => "Auto-enviado desde {$registro->tipo} (ID: {$registro->id})",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('ojales', function (Blueprint $table) {
|
||||||
|
$table->string('tipo')->nullable()->after('orden_produccion_id');
|
||||||
|
$table->boolean('terminada')->default(false)->after('perdidas');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('prensillas', function (Blueprint $table) {
|
||||||
|
$table->string('tipo')->nullable()->after('orden_produccion_id');
|
||||||
|
$table->boolean('terminada')->default(false)->after('perdidas');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('ojales', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['tipo', 'terminada']);
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('prensillas', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['tipo', 'terminada']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user