ADD EV3-431 Profitcenter - betűkód phase2/3 add modern supplier-customer-codes

This commit is contained in:
E98Developer 2026-08-09 18:02:50 +02:00
parent 1f1254c818
commit e5933d0639
4 changed files with 207 additions and 6 deletions

View File

@ -0,0 +1,172 @@
<?php
namespace App\Filament\Pages;
use App\Models\ProfitCenter;
use App\Models\ProfitCenterSupplierCode;
use App\Models\Supplier;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
use Laravel\Pennant\Feature;
class SupplierCustomerCodes extends Page implements HasForms
{
use InteractsWithForms;
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-identification';
protected string $view = 'filament.pages.supplier-customer-codes';
protected static ?string $title = 'Beszállítói vevőkódok';
protected static ?string $navigationLabel = 'Beszállítói vevőkódok';
protected static bool $shouldRegisterNavigation = false;
public ?array $data = [];
/**
* Rollout-védelem: a SupplierCustomerCode Pennant flag alapján dől el, ki éri el ezt
* az oldalt - a topbar menüpont is ezt hívja (ld. speed-button-nav-bar.blade.php).
*/
public static function canAccess(): bool
{
if (! $user = auth()->user()) {
return false;
}
return Feature::for($user)->active('SupplierCustomerCode');
}
public function mount(): void
{
abort_unless(static::canAccess(), 403);
$this->form->fill();
}
public function form(Schema $form): Schema
{
return $form
->schema([
Grid::make(2)
->schema([
Select::make('supplier_id')
->label('Beszállító')
->options(Supplier::query()->orderBy('name')->pluck('name', 'id'))
->required()
->searchable()
->live()
->afterStateUpdated(fn (?string $state, Set $set) => $this->loadSupplierData($state, $set)),
TextInput::make('search')
->label('Profitcenter keresése')
->placeholder('Kezdjen el gépelni a szűküléshez...')
->live(debounce: 300)
->visible(fn (Get $get) => filled($get('supplier_id'))),
]),
Toggle::make('hasCustomerCode')
->label('Vevőkód funkció aktív ennél a beszállítónál')
->visible(fn (Get $get) => filled($get('supplier_id'))),
Section::make('Profitcenterenkénti vevőkód')
->visible(fn (Get $get) => filled($get('supplier_id')))
->columns(3)
->schema(fn (Get $get) => $this->profitCenterCodeFields($get('search'))),
])
->statePath('data');
}
/**
* @return array<int, TextInput>
*/
private function profitCenterCodeFields(?string $search = null): array
{
return ProfitCenter::query()
->when(filled($search), fn ($query) => $query->where('name', 'like', '%'.$search.'%'))
->orderBy('name')
->get()
->map(fn (ProfitCenter $profitCenter) => TextInput::make("codes.{$profitCenter->id}")
->label($profitCenter->name)
->inlineLabel()
->maxLength(255))
->all();
}
private function loadSupplierData(?string $supplierId, Set $set): void
{
$codes = [];
if ($supplierId) {
$supplier = Supplier::find($supplierId);
$set('hasCustomerCode', (bool) $supplier?->hasCustomerCode);
$codes = ProfitCenterSupplierCode::query()
->where('supplier_id', $supplierId)
->pluck('customerCode', 'profit_center_id')
->all();
} else {
$set('hasCustomerCode', false);
}
foreach (ProfitCenter::query()->pluck('id') as $profitCenterId) {
$set("codes.{$profitCenterId}", $codes[$profitCenterId] ?? null);
}
}
protected function getFormActions(): array
{
return [
Action::make('save')
->label('Mentés')
->submit('save')
->color('primary'),
];
}
public function save(): void
{
$state = $this->form->getState();
$supplierId = $state['supplier_id'];
Supplier::whereKey($supplierId)->update([
'hasCustomerCode' => (bool) ($state['hasCustomerCode'] ?? false),
]);
// A form aktuális szűrés (keresés) miatt csak a látható mezőket adná vissza a getState() -
// a $this->data-ban viszont minden profitcenter kódja benne marad, mert a loadSupplierData()
// mindegyiket explicit beállítja, függetlenül attól, hogy éppen renderelve van-e.
foreach ($this->data['codes'] ?? [] as $profitCenterId => $customerCode) {
$customerCode = is_string($customerCode) ? trim($customerCode) : $customerCode;
if (blank($customerCode)) {
ProfitCenterSupplierCode::query()
->where('supplier_id', $supplierId)
->where('profit_center_id', $profitCenterId)
->delete();
continue;
}
ProfitCenterSupplierCode::updateOrCreate(
['supplier_id' => $supplierId, 'profit_center_id' => $profitCenterId],
['customerCode' => $customerCode],
);
}
Notification::make()
->title('Mentve')
->body('A beszállító vevőkód adatai elmentve.')
->success()
->send();
}
}

View File

@ -77,6 +77,7 @@ public function boot(): void
\Livewire\Livewire::component('app.filament.pages.price-list-processor', \App\Filament\Pages\PriceListProcessor::class);
\Livewire\Livewire::component('app.filament.auth.login', \App\Filament\Auth\Login::class);
\Livewire\Livewire::component('app.filament.pages.calendar-test', \App\Filament\Pages\CalendarTest::class);
\Livewire\Livewire::component('app.filament.pages.supplier-customer-codes', \App\Filament\Pages\SupplierCustomerCodes::class);
\Livewire\Livewire::component('app.filament.widgets.delivery-calendar-widget', \App\Filament\Widgets\DeliveryCalendarWidget::class);
\Livewire\Livewire::component('app.filament.supplier-portal.resources.product-stocks.pages.list-product-stocks', \App\Filament\SupplierPortal\Resources\ProductStocks\Pages\ListProductStocks::class);

View File

@ -1,4 +1,17 @@
@php
$deliveryChildren = [
['displayName' => 'Szállítási sablonok', 'link' => \App\Filament\Resources\DeliverySchedules\DeliveryScheduleResource::getUrl()],
['displayName' => 'Beszállítói felülbírálások', 'link' => \App\Filament\Resources\DeliveryCalendarOverrides\DeliveryCalendarOverrideResource::getUrl()],
['displayName' => 'Profitcenter ütemezés', 'link' => \App\Filament\Resources\ProfitCenterSupplierSchedules\ProfitCenterSupplierScheduleResource::getUrl()],
['displayName' => 'Munkanaptárak', 'link' => \App\Filament\Resources\WorkCalendars\WorkCalendarResource::getUrl()],
];
// A vevőkód-kezelő oldalt a Szállítás menü utolsó elemeként jelenítjük meg,
// a SupplierCustomerCode feature flagre bízva a láthatóságot (rollout-védelem).
if (\App\Filament\Pages\SupplierCustomerCodes::canAccess()) {
$deliveryChildren[] = ['displayName' => 'Beszállítói vevőkódok', 'link' => \App\Filament\Pages\SupplierCustomerCodes::getUrl()];
}
$modules = [
['name' => 'home', 'displayName' => 'Főoldal', 'icon' => 'home', 'link' => route('legacy.show', ['path' => 'dashboard']), 'roles' => ['root','admin','developer','profit-center']],
['name' => 'order', 'displayName' => 'Új megrendelés', 'icon' => 'bevetelezes', 'link' => route('legacy.show', ['path' => 'order']), 'roles' => ['root','profit-center']],
@ -13,12 +26,7 @@
['name' => 'statistics', 'displayName' => 'Statisztikák', 'icon' => 'kimutatasok', 'link' => route('legacy.show', ['path' => 'admin/statistics']), 'roles' => ['root','developer','admin']],
['name' => 'export', 'displayName' => 'Export', 'icon' => 'export', 'link' => route('legacy.show', ['path' => 'admin/export']), 'roles' => ['root','developer','admin']],
['name' => 'priceListProcessor', 'displayName' => 'Árlista feldolgozó', 'icon' => 'price_list', 'link' => '/admin/pricelist-files', 'roles' => ['root','developer','admin']],
['name' => 'delivery', 'displayName' => 'Szállítás', 'icon' => 'timetable3', 'roles' => ['root','admin','developer'], 'children' => [
['displayName' => 'Szállítási sablonok', 'link' => \App\Filament\Resources\DeliverySchedules\DeliveryScheduleResource::getUrl()],
['displayName' => 'Beszállítói felülbírálások', 'link' => \App\Filament\Resources\DeliveryCalendarOverrides\DeliveryCalendarOverrideResource::getUrl()],
['displayName' => 'Profitcenter ütemezés', 'link' => \App\Filament\Resources\ProfitCenterSupplierSchedules\ProfitCenterSupplierScheduleResource::getUrl()],
['displayName' => 'Munkanaptárak', 'link' => \App\Filament\Resources\WorkCalendars\WorkCalendarResource::getUrl()],
]],
['name' => 'delivery', 'displayName' => 'Szállítás', 'icon' => 'timetable3', 'roles' => ['root','admin','developer'], 'children' => $deliveryChildren],
['name' => 'calendarTest', 'displayName' => 'Naptár Teszt', 'icon' => 'idopontok', 'link' => \App\Filament\Pages\CalendarTest::getUrl(), 'roles' => ['root','developer','admin']],
];

View File

@ -0,0 +1,20 @@
<x-filament-panels::page>
<div class="space-y-6">
<div class="p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Beszállítói vevőkódok</h5>
<p class="mb-3 font-normal text-gray-700 dark:text-gray-400">Válassza ki a beszállítót, majd adja meg a profitcenterenkénti vevőkódokat.</p>
</div>
<div class="p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<form wire:submit="save">
{{ $this->form }}
<div class="mt-6">
<x-filament::actions
:actions="$this->getFormActions()"
/>
</div>
</form>
</div>
</div>
</x-filament-panels::page>