294 lines
13 KiB
PHP
294 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Resources;
|
|
|
|
use App\Filament\Resources\SeguimientoProcesoResource\Pages;
|
|
use App\Models\OrdenProduccion;
|
|
use Filament\Forms;
|
|
use Filament\Forms\Form;
|
|
use Filament\Resources\Resource;
|
|
use Filament\Tables;
|
|
use Filament\Tables\Table;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class SeguimientoProcesoResource extends Resource
|
|
{
|
|
protected static ?string $model = OrdenProduccion::class;
|
|
|
|
protected static ?string $navigationIcon = 'heroicon-o-chart-bar';
|
|
|
|
protected static ?string $navigationLabel = 'Seguimiento de Procesos';
|
|
|
|
protected static ?string $modelLabel = 'Seguimiento de Proceso';
|
|
|
|
protected static ?string $pluralModelLabel = 'Seguimiento de Procesos';
|
|
|
|
protected static ?string $navigationGroup = 'Reportes';
|
|
|
|
protected static ?int $navigationSort = 10;
|
|
|
|
public static function canCreate(): bool
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public static function form(Form $form): Form
|
|
{
|
|
return $form->schema([]);
|
|
}
|
|
|
|
public static function table(Table $table): Table
|
|
{
|
|
return $table
|
|
->query(
|
|
OrdenProduccion::query()
|
|
->orderBy('created_at', 'desc')
|
|
)
|
|
->columns([
|
|
Tables\Columns\TextColumn::make('numero_orden')
|
|
->label('Orden')
|
|
->searchable()
|
|
->sortable(),
|
|
|
|
Tables\Columns\TextColumn::make('prenda_modelo')
|
|
->label('Prenda')
|
|
->searchable()
|
|
->limit(30),
|
|
|
|
Tables\Columns\TextColumn::make('referencia')
|
|
->label('Referencia')
|
|
->searchable()
|
|
->toggleable(),
|
|
|
|
Tables\Columns\TextColumn::make('cantidad_total')
|
|
->label('Total')
|
|
->alignCenter()
|
|
->sortable(),
|
|
|
|
Tables\Columns\TextColumn::make('estado')
|
|
->badge()
|
|
->colors([
|
|
'danger' => 'cancelada',
|
|
'warning' => fn ($state) => in_array($state, ['pendiente', 'en_confeccion', 'en_tintoreria', 'en_acabados']),
|
|
'success' => 'finalizada',
|
|
'primary' => 'en_proceso',
|
|
]),
|
|
|
|
Tables\Columns\TextColumn::make('confeccion')
|
|
->label('📦 Confección')
|
|
->alignCenter()
|
|
->state(function (OrdenProduccion $record): string {
|
|
$enviadas = $record->confecciones()->sum('cantidad_enviada');
|
|
$recibidas = $record->confecciones()->sum('cantidad_recibida');
|
|
|
|
// Calcular disponibles (recibidas - arreglos - cobros - enviadas a ojales)
|
|
$arreglos = \App\Models\Ajuste::where('referencia_type', \App\Models\Confeccion::class)
|
|
->whereHas('referencia', function($q) use ($record) {
|
|
$q->where('orden_produccion_id', $record->id);
|
|
})->where('tipo', 'arreglo')->sum('cantidad');
|
|
|
|
$cobros = \App\Models\Cobro::where('referencia_type', \App\Models\Confeccion::class)
|
|
->whereHas('referencia', function($q) use ($record) {
|
|
$q->where('orden_produccion_id', $record->id);
|
|
})->sum('cantidad');
|
|
|
|
$disponiblesConfeccion = $recibidas - $arreglos - $cobros;
|
|
$enviadasOjales = $record->ojales()->sum('cantidad_enviada');
|
|
$pendientes = max(0, $disponiblesConfeccion - $enviadasOjales);
|
|
|
|
return "E:{$enviadas} R:{$recibidas} P:{$pendientes}";
|
|
})
|
|
->color(fn (OrdenProduccion $record) => self::getPendienteConfeccion($record) > 0 ? 'warning' : 'gray')
|
|
->tooltip('E=Enviadas, R=Recibidas, P=Pendientes'),
|
|
|
|
Tables\Columns\TextColumn::make('ojales')
|
|
->label('🔘 Ojales')
|
|
->alignCenter()
|
|
->state(function (OrdenProduccion $record): string {
|
|
$enviadas = $record->ojales()->sum('cantidad_enviada');
|
|
$terminadas = $record->ojales()->where('terminada', true)->sum('cantidad_enviada');
|
|
$pendientes = max(0, $enviadas - $terminadas);
|
|
|
|
return "E:{$enviadas} T:{$terminadas} P:{$pendientes}";
|
|
})
|
|
->color(fn (OrdenProduccion $record) => self::getPendienteOjales($record) > 0 ? 'warning' : 'gray')
|
|
->tooltip('E=Enviadas, T=Terminadas, P=Pendientes'),
|
|
|
|
Tables\Columns\TextColumn::make('presillas')
|
|
->label('⚫ Presillas')
|
|
->alignCenter()
|
|
->state(function (OrdenProduccion $record): string {
|
|
$enviadas = $record->prensillas()->sum('cantidad_enviada');
|
|
$terminadas = $record->prensillas()->where('terminada', true)->sum('cantidad_enviada');
|
|
$pendientes = max(0, $enviadas - $terminadas);
|
|
|
|
return "E:{$enviadas} T:{$terminadas} P:{$pendientes}";
|
|
})
|
|
->color(fn (OrdenProduccion $record) => self::getPendientePresillas($record) > 0 ? 'warning' : 'gray')
|
|
->tooltip('E=Enviadas, T=Terminadas, P=Pendientes'),
|
|
|
|
Tables\Columns\TextColumn::make('tintoreria')
|
|
->label('🎨 Tintorería')
|
|
->alignCenter()
|
|
->state(function (OrdenProduccion $record): string {
|
|
$enviadas = $record->tintorerias()->sum('cantidad_enviada');
|
|
|
|
$recepciones = 0;
|
|
foreach ($record->tintorerias as $tintoreria) {
|
|
$recepciones += (int) $tintoreria->recepciones()
|
|
->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
|
|
}
|
|
|
|
$pendientes = max(0, $enviadas - $recepciones);
|
|
|
|
return "E:{$enviadas} R:{$recepciones} P:{$pendientes}";
|
|
})
|
|
->color(fn (OrdenProduccion $record) => self::getPendienteTintoreria($record) > 0 ? 'warning' : 'gray')
|
|
->tooltip('E=Enviadas, R=Recibidas, P=Pendientes'),
|
|
|
|
Tables\Columns\TextColumn::make('acabados')
|
|
->label('✨ Acabados')
|
|
->alignCenter()
|
|
->state(function (OrdenProduccion $record): string {
|
|
// Disponibles desde tintorería
|
|
$disponibles = 0;
|
|
foreach ($record->tintorerias as $tintoreria) {
|
|
$recep = (int) $tintoreria->recepciones()
|
|
->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
|
|
$reprocesos = (int) $tintoreria->ajustes()
|
|
->where('tipo', 'reproceso')->sum('cantidad');
|
|
$cobros = (int) $tintoreria->cobros()->sum('cantidad');
|
|
$disponibles += ($recep - $reprocesos - $cobros);
|
|
}
|
|
|
|
$enviadasAcabados = $record->procesosAcabado()->sum('cantidad_enviada');
|
|
$recibidasAcabados = $record->procesosAcabado()
|
|
->whereNotNull('fecha_recepcion')
|
|
->sum('cantidad_recibida');
|
|
$pendientes = max(0, $disponibles - $enviadasAcabados);
|
|
|
|
return "D:{$disponibles} E:{$enviadasAcabados} P:{$pendientes}";
|
|
})
|
|
->color(fn (OrdenProduccion $record) => self::getPendienteAcabados($record) > 0 ? 'warning' : 'gray')
|
|
->tooltip('D=Disponibles, E=Enviadas, P=Pendientes'),
|
|
|
|
Tables\Columns\TextColumn::make('bodega')
|
|
->label('📦 Bodega')
|
|
->alignCenter()
|
|
->state(function (OrdenProduccion $record): string {
|
|
$total = $record->inventarioPrenda()->sum('cantidad_terminada');
|
|
$disponible = $record->inventarioPrenda()->sum('cantidad_disponible');
|
|
|
|
return "T:{$total} D:{$disponible}";
|
|
})
|
|
->color(fn (OrdenProduccion $record) => self::getEnBodega($record) > 0 ? 'success' : 'gray')
|
|
->tooltip('T=Total, D=Disponible'),
|
|
])
|
|
->filters([
|
|
Tables\Filters\SelectFilter::make('estado')
|
|
->options([
|
|
'pendiente' => 'Pendiente',
|
|
'en_proceso' => 'En Proceso',
|
|
'en_confeccion' => 'En Confección',
|
|
'en_tintoreria' => 'En Tintorería',
|
|
'en_acabados' => 'En Acabados',
|
|
'finalizada' => 'Finalizada',
|
|
'cancelada' => 'Cancelada',
|
|
]),
|
|
|
|
Tables\Filters\Filter::make('con_pendientes')
|
|
->label('Solo con pendientes')
|
|
->query(fn (Builder $query) => $query->whereIn('estado', ['en_proceso', 'en_confeccion', 'en_tintoreria', 'en_acabados'])),
|
|
])
|
|
->actions([])
|
|
->bulkActions([])
|
|
->defaultSort('created_at', 'desc')
|
|
->paginated([10, 25, 50, 100])
|
|
->poll('30s');
|
|
}
|
|
|
|
protected static function getPendienteConfeccion(OrdenProduccion $record): int
|
|
{
|
|
$recibidas = $record->confecciones()->sum('cantidad_recibida');
|
|
|
|
$arreglos = \App\Models\Ajuste::where('referencia_type', \App\Models\Confeccion::class)
|
|
->whereHas('referencia', function($q) use ($record) {
|
|
$q->where('orden_produccion_id', $record->id);
|
|
})->where('tipo', 'arreglo')->sum('cantidad');
|
|
|
|
$cobros = \App\Models\Cobro::where('referencia_type', \App\Models\Confeccion::class)
|
|
->whereHas('referencia', function($q) use ($record) {
|
|
$q->where('orden_produccion_id', $record->id);
|
|
})->sum('cantidad');
|
|
|
|
$disponiblesConfeccion = $recibidas - $arreglos - $cobros;
|
|
$enviadasOjales = $record->ojales()->sum('cantidad_enviada');
|
|
|
|
return max(0, $disponiblesConfeccion - $enviadasOjales);
|
|
}
|
|
|
|
protected static function getPendienteOjales(OrdenProduccion $record): int
|
|
{
|
|
$enviadas = $record->ojales()->sum('cantidad_enviada');
|
|
$terminadas = $record->ojales()->where('terminada', true)->sum('cantidad_enviada');
|
|
|
|
return max(0, $enviadas - $terminadas);
|
|
}
|
|
|
|
protected static function getPendientePresillas(OrdenProduccion $record): int
|
|
{
|
|
$enviadas = $record->prensillas()->sum('cantidad_enviada');
|
|
$terminadas = $record->prensillas()->where('terminada', true)->sum('cantidad_enviada');
|
|
|
|
return max(0, $enviadas - $terminadas);
|
|
}
|
|
|
|
protected static function getPendienteTintoreria(OrdenProduccion $record): int
|
|
{
|
|
$enviadas = $record->tintorerias()->sum('cantidad_enviada');
|
|
|
|
$recepciones = 0;
|
|
foreach ($record->tintorerias as $tintoreria) {
|
|
$recepciones += (int) $tintoreria->recepciones()
|
|
->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
|
|
}
|
|
|
|
return max(0, $enviadas - $recepciones);
|
|
}
|
|
|
|
protected static function getPendienteAcabados(OrdenProduccion $record): int
|
|
{
|
|
$disponibles = 0;
|
|
foreach ($record->tintorerias as $tintoreria) {
|
|
$recep = (int) $tintoreria->recepciones()
|
|
->sum(DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
|
|
$reprocesos = (int) $tintoreria->ajustes()
|
|
->where('tipo', 'reproceso')->sum('cantidad');
|
|
$cobros = (int) $tintoreria->cobros()->sum('cantidad');
|
|
$disponibles += ($recep - $reprocesos - $cobros);
|
|
}
|
|
|
|
$enviadasAcabados = $record->procesosAcabado()->sum('cantidad_enviada');
|
|
|
|
return max(0, $disponibles - $enviadasAcabados);
|
|
}
|
|
|
|
protected static function getEnBodega(OrdenProduccion $record): int
|
|
{
|
|
return $record->inventarioPrenda()->sum('cantidad_disponible');
|
|
}
|
|
|
|
public static function getRelations(): array
|
|
{
|
|
return [];
|
|
}
|
|
|
|
public static function getPages(): array
|
|
{
|
|
return [
|
|
'index' => Pages\ListSeguimientoProcesos::route('/'),
|
|
];
|
|
}
|
|
}
|