components([ Forms\Components\Select::make('labor_id') ->label(__('Catalog manoperă')) ->options(fn () => Labor::where('is_active', true) ->get() ->mapWithKeys(fn ($l) => [$l->id => "[{$l->category}] {$l->name_ro} ({$l->hours}h)"]) ->toArray()) ->searchable() ->live() ->afterStateUpdated(function ($state, Set $set) { if ($state && $labor = Labor::find($state)) { $set('name', $labor->name_ro); $set('hours', $labor->hours); $set('price_per_hour', $labor->hours > 0 ? round($labor->price / max((float) $labor->hours, 1), 2) : 0); } }) ->columnSpanFull(), Forms\Components\TextInput::make('name')->label(__('Nume'))->required()->columnSpanFull(), Forms\Components\TextInput::make('hours')->label(__('Ore'))->numeric()->default(1)->required(), Forms\Components\TextInput::make('price_per_hour')->label(__('Preț/h'))->numeric()->required(), Forms\Components\Select::make('master_id') ->label(__('Maistru')) ->options(fn () => User::pluck('name', 'id')) ->searchable(), Forms\Components\Select::make('status') ->options(WorkOrderWork::STATUSES) ->default('todo') ->required(), Forms\Components\Textarea::make('notes')->label(__('Notițe'))->columnSpanFull()->rows(2), ]); } /** Global visibility flag from tenant Settings — user can hide margin details in-session. */ private static function marginDetailsVisible(): bool { if (! auth()->user()?->canDo(\App\Auth\Permissions::FINANCE_VIEW_INTERNAL_MARGIN)) { return false; } $tenant = app(\App\Tenancy\TenantManager::class)->current(); return (bool) data_get($tenant?->settings, 'show_internal_margin_details', true); } public function table(Table $table): Table { return $table ->recordTitleAttribute('name') ->columns([ Tables\Columns\TextColumn::make('name')->label(__('Manoperă'))->wrap(), Tables\Columns\TextColumn::make('hours')->label(__('Ore'))->numeric(decimalPlaces: 2)->alignRight(), Tables\Columns\TextColumn::make('price_per_hour')->label(__('Preț/h'))->money('MDL')->alignRight(), Tables\Columns\TextColumn::make('total') ->label(__('Total')) ->money('MDL') ->alignRight() ->description(function ($record) { if (! self::marginDetailsVisible() || $record->salary_base === null) return null; // WO-level toggle off → hide margin text complet if ($record->workOrder && $record->workOrder->apply_margin === false) return null; if ((float) $record->applied_margin_pct === 0.0) return null; return 'Bază salariu: ' . number_format((float) $record->salary_base, 2) . ' MDL · marjă ' . rtrim(rtrim(number_format((float) $record->applied_margin_pct, 2), '0'), '.') . '%'; }), Tables\Columns\TextColumn::make('master.name')->label(__('Maistru'))->placeholder('—'), Tables\Columns\TextColumn::make('status') ->formatStateUsing(fn ($s) => WorkOrderWork::STATUSES[$s] ?? $s) ->badge() ->colors(['gray' => ['todo'], 'warning' => ['in_progress'], 'success' => ['done']]), ]) ->headerActions([ Actions\CreateAction::make() ->after(function (WorkOrderWork $record) { // Auto-add the labor's default parts to the parent WO. if (! $record->labor_id) return; $labor = Labor::with('laborParts.part')->find($record->labor_id); $wo = $record->workOrder; if (! $labor || ! $wo || $labor->laborParts->isEmpty()) return; $composer = app(\App\Services\ServiceComposer::class); foreach ($labor->laborParts as $lp) { if ($lp->part) { $composer->addPart($wo, $lp->part, (float) $lp->qty, $lp->unit); } } \Filament\Notifications\Notification::make() ->title('Piese implicite adăugate (' . $labor->laborParts->count() . ')') ->success()->send(); }), ]) ->actions([ Actions\EditAction::make(), Actions\DeleteAction::make(), ]); } }