This commit is contained in:
E98Developer 2026-03-04 15:20:17 +01:00
parent caf0cc3f54
commit 9e90feb662
25 changed files with 859 additions and 14 deletions

View File

@ -24,6 +24,7 @@ ##### Modellek és Auditálás
- Minden fő modellnek a `App\Models\BaseAuditable` osztályból kell származnia. - Minden fő modellnek a `App\Models\BaseAuditable` osztályból kell származnia.
- Ez biztosítja a `created_by`, `updated_by` és `deleted_by` mezők automatikus töltését a `ModelUserIdAppenderTrait` segítségével. - Ez biztosítja a `created_by`, `updated_by` és `deleted_by` mezők automatikus töltését a `ModelUserIdAppenderTrait` segítségével.
- Használjunk `SoftDeletes`-t, ahol az adatok megőrzése fontos. - Használjunk `SoftDeletes`-t, ahol az adatok megőrzése fontos.
- **Enums**: Amennyiben egy modell mezőjéhez meghatározott értékkészlet tartozik, kötelező PHP Enum használata és annak beállítása a `$casts` tömbben.
##### Hibrid Frontend Architektúra (Mix & Vite) és a "Clean Cut" elv ##### Hibrid Frontend Architektúra (Mix & Vite) és a "Clean Cut" elv
A projekt fokozatos modernizáció alatt áll, ezért két párhuzamos build rendszert használunk a **"Clean Cut"** (tiszta vágás) elv mentén: A projekt fokozatos modernizáció alatt áll, ezért két párhuzamos build rendszert használunk a **"Clean Cut"** (tiszta vágás) elv mentén:
@ -79,12 +80,17 @@ ##### JavaScript Kódolási Stílus
##### Blade Sablonok ##### Blade Sablonok
- A nézetek az `resources/views` mappában találhatóak, logikusan csoportosítva (pl. `admin/product`, `admin/statistics`). - A nézetek az `resources/views` mappában találhatóak, logikusan csoportosítva (pl. `admin/product`, `admin/statistics`).
- A szűrők és közös komponensek gyakran külön fájlokba vannak kiszervezve (pl. `filter.blade.php`). - A szűrők és közös komponensek gyakran külön fájlokba vannak kiszervezve (pl. `filter.blade.php`).
#### Eszközök és Konvenciók - CLI
- **Artisan parancsok**: Generáló parancsok (pl. `make:filament-resource`) esetén törekedni kell az interakciómentes futtatásra a `--no-interaction` kapcsoló használatával.
- **Filament Resource**: Új Resource létrehozásakor kötelező megadni a `--record-title-attribute` paramétert (pl. `name` vagy `filename`), és javasolt a `--generate` használata, ha az adatbázis séma már rendelkezésre áll.
#### Verziókezelés (Git) #### Verziókezelés (Git)
* **Üzenetek**: Angol vagy magyar nyelven, rövid de tömör leírással, hogy mit változtattál. Példa: `feature: Add order archive export functionality`. * **Üzenetek**: Angol vagy magyar nyelven, rövid de tömör leírással, hogy mit változtattál. Példa: `feature: Add order archive export functionality`.
* **Méretes fájlok**: Ne committolj nagyméretű képeket, build artifactokat vagy érzékeny adatokat (`.env`). * **Méretes fájlok**: Ne committolj nagyméretű képeket, build artifactokat vagy érzékeny adatokat (`.env`).
#### Adatbázis kezelés #### Adatbázis kezelés
* **Migrációk**: Minden adatbázis sémaváltoztatást migrációval kell végrehajtani. * **Migrációk**: Minden adatbázis sémaváltoztatást migrációval kell végrehajtani.
* **Enums**: Ha egy mező meghatározott értékkészlettel rendelkezik, a migrációban is `enum` típust kell használni, az értékeket pedig dinamikusan a megfelelő PHP Enum osztályból kell kinyerni (pl. `array_column(Enum::cases(), 'value')`).
* **Factories/Seeders**: Új modulokhoz hozz létre gyárat (factory) és seedert a könnyű tesztelhetőségért. * **Factories/Seeders**: Új modulokhoz hozz létre gyárat (factory) és seedert a könnyű tesztelhetőségért.
#### Tesztelés #### Tesztelés

View File

@ -0,0 +1,25 @@
<?php
namespace App\Enums;
enum PricelistFileStatusEnum: string
{
case todo = 'todo';
case inprogress = 'inprogress';
case fail = 'fail';
case done = 'done';
case waiting_for_approval = 'waiting_for_approval';
case closed = 'closed';
public function label(): string
{
return match ($this) {
self::todo => 'elvégzendő',
self::inprogress => 'folyamatban',
self::fail => 'hiba',
self::done => 'elkészült',
self::waiting_for_approval => 'jóváhagyásra vár',
self::closed => 'lezárva',
};
}
}

View File

@ -11,7 +11,7 @@ class Schema extends BaseSchema
/** /**
* Get a schema builder instance for a connection. * Get a schema builder instance for a connection.
*/ */
public static function connection(?string $name): Builder public static function connection($name)
{ {
/** @var Builder $builder */ /** @var Builder $builder */
$builder = static::$app['db']->connection($name)->getSchemaBuilder(); $builder = static::$app['db']->connection($name)->getSchemaBuilder();

View File

@ -3,11 +3,26 @@
namespace App\Filament\Pages; namespace App\Filament\Pages;
use Filament\Pages\Page; use Filament\Pages\Page;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\FileUpload;
use Filament\Schemas\Schema;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Concerns\InteractsWithForms;
use App\Models\Supplier;
use App\Models\PricelistFile;
use App\Filament\Resources\PricelistFiles\PricelistFileResource;
use App\Jobs\PricelistPreProcessJob;
use Filament\Notifications\Notification;
use Filament\Actions\Action;
use Illuminate\Contracts\Support\Htmlable; use Illuminate\Contracts\Support\Htmlable;
class PriceListProcessor extends Page class PriceListProcessor extends Page implements HasForms
{ {
use InteractsWithForms;
protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-document-text'; protected static string | \BackedEnum | null $navigationIcon = 'heroicon-o-document-text';
protected string $view = 'filament.pages.price-list-processor'; protected string $view = 'filament.pages.price-list-processor';
@ -17,4 +32,80 @@ class PriceListProcessor extends Page
protected static ?string $navigationLabel = 'Árlista feldolgozó'; protected static ?string $navigationLabel = 'Árlista feldolgozó';
protected static bool $shouldRegisterNavigation = false; protected static bool $shouldRegisterNavigation = false;
public ?array $data = [];
public function mount(): void
{
$this->form->fill();
}
public function form(Schema $form): Schema
{
return $form
->schema([
Select::make('supplier_id')
->label('Beszállító')
->options(Supplier::query()->pluck('name', 'id'))
->required()
->searchable(),
DatePicker::make('available_date')
->label('Életbelépés dátuma')
->required()
->native(false)
->displayFormat('Y.m.d'),
Textarea::make('note')
->label('Megjegyzés')
->rows(3),
FileUpload::make('filename')
->label('Fájl kiválasztása')
->required()
->acceptedFileTypes(['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'text/csv'])
->disk('public')
->directory('pricelist-uploads')
->preserveFilenames(),
])
->statePath('data');
}
protected function getFormActions(): array
{
return [
Action::make('save')
->label('Feltöltés és feldolgozás indítása')
->submit('save')
->color('primary'),
];
}
public function save()
{
$data = $this->form->getState();
$pricelistFile = PricelistFile::create([
'filename' => $data['filename'],
'supplier_id' => $data['supplier_id'],
'available_date' => $data['available_date'],
'note' => $data['note'],
'status' => \App\Enums\PricelistFileStatusEnum::todo,
'workflow_steps' => [
['name' => 'preprocess', 'label' => 'Előfeldolgozás', 'status' => 'pending'],
['name' => 'validation', 'label' => 'Validálás', 'status' => 'pending'],
['name' => 'approval', 'label' => 'Jóváhagyás', 'status' => 'pending'],
['name' => 'execution', 'label' => 'Végrehajtás', 'status' => 'pending']
],
]);
PricelistPreProcessJob::dispatch($pricelistFile);
Notification::make()
->title('Sikeres feltöltés')
->body('Az árlista fájl rögzítve lett és a feldolgozás elindult.')
->success()
->send();
$this->form->fill();
return redirect()->to(PricelistFileResource::getUrl('view', ['record' => $pricelistFile]));
}
} }

View File

@ -0,0 +1,11 @@
<?php
namespace App\Filament\Resources\PricelistFiles\Pages;
use App\Filament\Resources\PricelistFiles\PricelistFileResource;
use Filament\Resources\Pages\CreateRecord;
class CreatePricelistFile extends CreateRecord
{
protected static string $resource = PricelistFileResource::class;
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Filament\Resources\PricelistFiles\Pages;
use App\Filament\Resources\PricelistFiles\PricelistFileResource;
use Filament\Actions\DeleteAction;
use Filament\Actions\ForceDeleteAction;
use Filament\Actions\RestoreAction;
use Filament\Actions\ViewAction;
use Filament\Resources\Pages\EditRecord;
class EditPricelistFile extends EditRecord
{
protected static string $resource = PricelistFileResource::class;
protected function getHeaderActions(): array
{
return [
ViewAction::make(),
DeleteAction::make(),
ForceDeleteAction::make(),
RestoreAction::make(),
];
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Filament\Resources\PricelistFiles\Pages;
use App\Filament\Resources\PricelistFiles\PricelistFileResource;
use Filament\Actions\Action;
use App\Filament\Pages\PriceListProcessor;
use Filament\Resources\Pages\ListRecords;
class ListPricelistFiles extends ListRecords
{
protected static string $resource = PricelistFileResource::class;
protected function getHeaderActions(): array
{
return [
Action::make('create_pricelist')
->label('Új árlista felvitele')
->url(fn (): string => PriceListProcessor::getUrl())
->button()
->color('primary'),
];
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace App\Filament\Resources\PricelistFiles\Pages;
use App\Filament\Resources\PricelistFiles\PricelistFileResource;
use Filament\Actions\EditAction;
use Filament\Resources\Pages\ViewRecord;
class ViewPricelistFile extends ViewRecord
{
protected static string $resource = PricelistFileResource::class;
protected function getHeaderActions(): array
{
return [
EditAction::make(),
];
}
public function getHeading(): string
{
return "Árlista fájl: " . $this->record->filename;
}
protected function getHeaderWidgets(): array
{
return [
// Később ide jöhetnek widgetek, pl. statisztika a feldolgozásról
];
}
public function getSubheading(): ?string
{
return "Beszállító: " . $this->record->supplier?->name;
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace App\Filament\Resources\PricelistFiles;
use App\Filament\Resources\PricelistFiles\Pages\CreatePricelistFile;
use App\Filament\Resources\PricelistFiles\Pages\EditPricelistFile;
use App\Filament\Resources\PricelistFiles\Pages\ListPricelistFiles;
use App\Filament\Resources\PricelistFiles\Pages\ViewPricelistFile;
use App\Filament\Resources\PricelistFiles\Schemas\PricelistFileForm;
use App\Filament\Resources\PricelistFiles\Schemas\PricelistFileInfolist;
use App\Filament\Resources\PricelistFiles\Tables\PricelistFilesTable;
use App\Models\PricelistFile;
use BackedEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
use Filament\Support\Enums\MaxWidth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class PricelistFileResource extends Resource
{
protected static ?string $model = PricelistFile::class;
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationLabel = 'Árlista feldolgozó';
protected static ?string $breadcrumb = 'Árlista feldolgozó';
protected static ?string $pluralLabel = 'Árlista feldolgozó';
protected static ?string $modelLabel = 'Árlista fájl';
public static function getMaxWidth(): MaxWidth|string|null
{
return MaxWidth::Full;
}
public static function form(Schema $schema): Schema
{
return PricelistFileForm::configure($schema);
}
public static function infolist(Schema $schema): Schema
{
return PricelistFileInfolist::configure($schema);
}
public static function table(Table $table): Table
{
return PricelistFilesTable::configure($table);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => ListPricelistFiles::route('/'),
'create' => CreatePricelistFile::route('/create'),
'view' => ViewPricelistFile::route('/{record}'),
'edit' => EditPricelistFile::route('/{record}/edit'),
];
}
public static function getRecordRouteBindingEloquentQuery(): Builder
{
return parent::getRecordRouteBindingEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Filament\Resources\PricelistFiles\Schemas;
use Filament\Schemas\Schema;
class PricelistFileForm
{
public static function configure(Schema $schema): Schema
{
return $schema
->components([
//
]);
}
}

View File

@ -0,0 +1,104 @@
<?php
namespace App\Filament\Resources\PricelistFiles\Schemas;
use App\Enums\PricelistFileStatusEnum;
use Filament\Schemas\Components\Section;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\RepeatableEntry;
use Filament\Schemas\Components\Grid;
use Filament\Schemas\Schema;
class PricelistFileInfolist
{
public static function configure(Schema $schema): Schema
{
return $schema
->components([
Section::make('Fájl információk')
->poll('5s')
->schema([
Grid::make(3)
->schema([
TextEntry::make('filename')
->label('Fájlnév')
->icon('heroicon-o-document-text')
->color('primary'),
TextEntry::make('supplier.name')
->label('Beszállító')
->icon('heroicon-o-user'),
TextEntry::make('status')
->label('Státusz')
->badge()
->formatStateUsing(fn (PricelistFileStatusEnum $state): string => $state->label())
->color(fn (PricelistFileStatusEnum $state): string => match ($state) {
PricelistFileStatusEnum::todo => 'gray',
PricelistFileStatusEnum::inprogress => 'info',
PricelistFileStatusEnum::done => 'success',
PricelistFileStatusEnum::fail => 'danger',
PricelistFileStatusEnum::waiting_for_approval => 'primary',
PricelistFileStatusEnum::closed => 'warning',
}),
]),
Grid::make(3)
->schema([
TextEntry::make('available_date')
->label('Életbelépés dátuma')
->date('Y.m.d'),
TextEntry::make('created_at')
->label('Feltöltés időpontja')
->dateTime('Y.m.d H:i'),
TextEntry::make('processing_current_step')
->label('Aktuális folyamat')
->weight('bold')
->color('info')
->formatStateUsing(fn ($state, $record) => "$state ({$record->processing_current_step_percentage}%)"),
]),
TextEntry::make('note')
->label('Megjegyzés')
->placeholder('Nincs megjegyzés')
->columnSpanFull(),
]),
Section::make('Feldolgozási folyamat (Workflow)')
->poll('5s')
->schema([
RepeatableEntry::make('workflow_steps')
->label(false)
->schema([
TextEntry::make('label')
->label('Lépés')
->weight('bold')
->inlineLabel(),
TextEntry::make('status')
->label('Állapot')
->badge()
->inlineLabel()
->formatStateUsing(fn (string $state): string => match ($state) {
'pending' => 'várakozik',
'inprogress' => 'folyamatban',
'done' => 'kész',
'fail' => 'hiba',
default => $state,
})
->color(fn (string $state): string => match ($state) {
'pending' => 'gray',
'inprogress' => 'info',
'done' => 'success',
'fail' => 'danger',
default => 'gray',
})
->icon(fn (string $state): string => match ($state) {
'pending' => 'heroicon-o-clock',
'inprogress' => 'heroicon-o-arrow-path',
'done' => 'heroicon-o-check-circle',
'fail' => 'heroicon-o-x-circle',
default => 'heroicon-o-question-mark-circle',
}),
])
->columns(2)
->columnSpanFull(),
]),
]);
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace App\Filament\Resources\PricelistFiles\Tables;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\ForceDeleteBulkAction;
use Filament\Actions\RestoreBulkAction;
use Filament\Actions\ViewAction;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use App\Enums\PricelistFileStatusEnum;
class PricelistFilesTable
{
public static function configure(Table $table): Table
{
return $table
->poll('5s')
->columns([
TextColumn::make('filename')
->label('Fájlnév')
->searchable()
->sortable(),
TextColumn::make('supplier.name')
->label('Beszállító')
->searchable()
->sortable(),
TextColumn::make('status')
->label('Státusz')
->badge()
->formatStateUsing(fn (PricelistFileStatusEnum $state): string => $state->label())
->color(fn (PricelistFileStatusEnum $state): string => match ($state) {
PricelistFileStatusEnum::todo => 'gray',
PricelistFileStatusEnum::inprogress => 'info',
PricelistFileStatusEnum::done => 'success',
PricelistFileStatusEnum::fail => 'danger',
PricelistFileStatusEnum::waiting_for_approval => 'primary',
PricelistFileStatusEnum::closed => 'warning',
})
->sortable(),
TextColumn::make('processing_current_step')
->label('Aktuális lépés')
->placeholder('Nincs adat'),
TextColumn::make('processing_current_step_percentage')
->label('Készültség')
->suffix('%')
->alignCenter(),
TextColumn::make('created_at')
->label('Feltöltve')
->dateTime('Y.m.d H:i')
->sortable(),
])
->filters([
TrashedFilter::make(),
])
->recordActions([
ViewAction::make(),
EditAction::make(),
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
ForceDeleteBulkAction::make(),
RestoreBulkAction::make(),
]),
]);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Jobs;
use App\Models\PricelistFile;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
class PricelistPreProcessJob implements ShouldQueue
{
use Queueable;
/**
* Create a new job instance.
*/
public function __construct(
public PricelistFile $pricelistFile
)
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
// Ide kerül majd az üzleti logika a PricelistFileProcessService segítségével
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace App\Models;
use App\Enums\PricelistFileStatusEnum;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class PricelistFile extends BaseAuditable
{
use SoftDeletes;
protected $casts = [
'status' => PricelistFileStatusEnum::class,
'processing_current_step_percentage' => 'integer',
'available_date' => 'date',
'workflow_steps' => 'array',
];
public function supplier(): BelongsTo
{
return $this->belongsTo(Supplier::class);
}
public function priceList(): BelongsTo
{
return $this->belongsTo(PriceList::class);
}
}

View File

@ -45,6 +45,13 @@ public function register(): void
*/ */
public function boot(): void public function boot(): void
{ {
// \Livewire\Livewire::component('app.filament.pages.price-list-processor', \App\Filament\Pages\PriceListProcessor::class);
/*
\Livewire\Livewire::component('filament.livewire.notifications', \Filament\Livewire\Notifications::class);
\Livewire\Livewire::component('filament.livewire.database-notifications', \Filament\Livewire\DatabaseNotifications::class);
\Livewire\Livewire::component('filament.livewire.sidebar', \Filament\Livewire\Sidebar::class);
\Livewire\Livewire::component('filament.livewire.topbar', \Filament\Livewire\Topbar::class);
\Livewire\Livewire::component('filament.livewire.global-search', \Filament\Livewire\GlobalSearch::class);
*/
} }
} }

View File

@ -0,0 +1,91 @@
<?php
namespace App\Services;
use App\Models\PricelistFile;
use App\Enums\PricelistFileStatusEnum;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class PricelistFileProcessService
{
public function __construct(
protected PriceListService $priceListService
) {}
/**
* Előfeldolgozás (Pre-processing) - Adatok ellenőrzése és validálása
*
* @param PricelistFile $pricelistFile
* @param array $data Az XLS-ből beolvasott adatok
* @return bool
*/
public function preProcess(PricelistFile $pricelistFile, array $data): bool
{
$pricelistFile->update([
'status' => PricelistFileStatusEnum::inprogress,
'processing_current_step' => 'Előfeldolgozás: Adatok ellenőrzése...',
'processing_current_step_percentage' => 10,
]);
try {
// Itt hívjuk majd meg a PriceListService ellenőrző metódusait
// $results = $this->priceListService->importPriceListCheck($pricelistFile->supplier_id, $data);
// TODO: Eredmények mentése (pl. preview_data JSON mezőbe vagy fájlba)
$pricelistFile->update([
'status' => PricelistFileStatusEnum::todo, // Visszaállítjuk, vagy egy új 'waiting_for_approval' státuszra, ha létezik
'processing_current_step' => 'Előfeldolgozás kész, jóváhagyásra vár.',
'processing_current_step_percentage' => 100,
]);
return true;
} catch (\Exception $e) {
Log::error('Pricelist pre-process error: ' . $e->getMessage());
$pricelistFile->update([
'status' => PricelistFileStatusEnum::fail,
'processing_current_step' => 'Hiba az előfeldolgozás során: ' . $e->getMessage(),
]);
return false;
}
}
/**
* Végrehajtás (Execution) - Módosítások tényleges alkalmazása tranzakcióban
*
* @param PricelistFile $pricelistFile
* @param array $dataToImport A véglegesítendő adatok
* @return bool
*/
public function execute(PricelistFile $pricelistFile, array $dataToImport): bool
{
$pricelistFile->update([
'status' => PricelistFileStatusEnum::inprogress,
'processing_current_step' => 'Végrehajtás: Árlista frissítése...',
'processing_current_step_percentage' => 0,
]);
DB::beginTransaction();
try {
// Tényleges importálás végrehajtása a PriceListService segítségével
// $this->priceListService->importPriceList(...);
DB::commit();
$pricelistFile->update([
'status' => PricelistFileStatusEnum::done,
'processing_current_step' => 'Sikeresen befejezve.',
'processing_current_step_percentage' => 100,
]);
return true;
} catch (\Exception $e) {
DB::rollBack();
Log::error('Pricelist execution error: ' . $e->getMessage());
$pricelistFile->update([
'status' => PricelistFileStatusEnum::fail,
'processing_current_step' => 'Hiba a végrehajtás során: ' . $e->getMessage(),
]);
return false;
}
}
}

View File

@ -0,0 +1,35 @@
<?php
use App\Database\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$builder = DB::connection()->getSchemaBuilder();
$builder->blueprintResolver(function ($table, $callback) {
return new Blueprint($table, $callback);
});
$builder->create('pricelist_files', function (Blueprint $table) {
$table->id();
$table->string('filename');
$table->timestamps();
$table->softDeletes();
$table->userIdFields();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
DB::connection()->getSchemaBuilder()->dropIfExists('pricelist_files');
}
};

View File

@ -0,0 +1,30 @@
<?php
use App\Database\Blueprint;
use App\Enums\PricelistFileStatusEnum;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('pricelist_files', function ($table) {
$table->integer('file_size')->nullable()->after('filename');
$table->enum('status', array_column(PricelistFileStatusEnum::cases(), 'value'))->default(PricelistFileStatusEnum::todo->value)->after('file_size');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pricelist_files', function ($table) {
$table->dropColumn(['file_size', 'status']);
});
}
};

View File

@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('pricelist_files', function (Blueprint $table) {
$table->string('processing_current_step')->nullable()->default(null)->after('status');
$table->integer('processing_current_step_percentage')->nullable()->default(null)->after('processing_current_step');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pricelist_files', function (Blueprint $table) {
$table->dropColumn(['processing_current_step', 'processing_current_step_percentage']);
});
}
};

View File

@ -0,0 +1,34 @@
<?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('pricelist_files', function (Blueprint $table) {
$table->unsignedBigInteger('supplier_id')->nullable()->after('filename');
$table->unsignedBigInteger('price_list_id')->nullable()->after('supplier_id');
$table->foreign('supplier_id')->references('id')->on('suppliers')->onDelete('set null');
$table->foreign('price_list_id')->references('id')->on('price_lists')->onDelete('set null');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pricelist_files', function (Blueprint $table) {
$table->dropForeign(['supplier_id']);
$table->dropForeign(['price_list_id']);
$table->dropColumn(['supplier_id', 'price_list_id']);
});
}
};

View File

@ -0,0 +1,29 @@
<?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('pricelist_files', function (Blueprint $table) {
$table->date('available_date')->nullable()->after('price_list_id');
$table->text('note')->nullable()->after('available_date');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pricelist_files', function (Blueprint $table) {
$table->dropColumn(['available_date', 'note']);
});
}
};

View File

@ -0,0 +1,28 @@
<?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('pricelist_files', function (Blueprint $table) {
$table->json('workflow_steps')->nullable()->after('processing_current_step_percentage');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('pricelist_files', function (Blueprint $table) {
$table->dropColumn('workflow_steps');
});
}
};

View File

@ -7,7 +7,7 @@
['name' => 'product', 'displayName' => 'Termék', 'icon' => 'raktar', 'link' => route('admin.product.index'), 'roles' => ['root','developer','admin']], ['name' => 'product', 'displayName' => 'Termék', 'icon' => 'raktar', 'link' => route('admin.product.index'), 'roles' => ['root','developer','admin']],
['name' => 'supplier', 'displayName' => 'Beszállító adatbázis', 'icon' => 'supplier', 'link' => route('admin.supplier.index'), 'roles' => ['root','developer','admin','profit-center']], ['name' => 'supplier', 'displayName' => 'Beszállító adatbázis', 'icon' => 'supplier', 'link' => route('admin.supplier.index'), 'roles' => ['root','developer','admin','profit-center']],
['name' => 'priceList', 'displayName' => 'Webrendelős árlisták', 'icon' => 'price_list2', 'link' => route('admin.priceList.index'), 'roles' => ['root','developer','admin','profit-center']], ['name' => 'priceList', 'displayName' => 'Webrendelős árlisták', 'icon' => 'price_list2', 'link' => route('admin.priceList.index'), 'roles' => ['root','developer','admin','profit-center']],
['name' => 'priceListProcessor', 'displayName' => 'Árlista feldolgozó', 'icon' => 'price_list', 'link' => '/admin/price-list-processor', 'roles' => ['root','developer','admin']], ['name' => 'priceListProcessor', 'displayName' => 'Árlista feldolgozó', 'icon' => 'price_list', 'link' => '/admin/pricelist-files', 'roles' => ['root','developer','admin']],
]; ];
@endphp @endphp

View File

@ -1,6 +1,20 @@
<x-filament-panels::page> <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"> <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">Árlista feldolgozó</h5> <h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Árlista feldolgozó</h5>
<p class="mb-3 font-normal text-gray-700 dark:text-gray-400">Ez az új, Filament-alapú árlista feldolgozó felület.</p> <p class="mb-3 font-normal text-gray-700 dark:text-gray-400">Töltse fel az új árlistát a feldolgozás indításához.</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> </div>
</x-filament-panels::page> </x-filament-panels::page>

View File

@ -118,9 +118,9 @@
'name' => 'priceListProcessor', 'name' => 'priceListProcessor',
'DisplayName' => 'Árlista feldolgozó', 'DisplayName' => 'Árlista feldolgozó',
'icon' => 'price_list', 'icon' => 'price_list',
'link'=>'/admin/price-list-processor', 'link' => '/admin/pricelist-files',
'noAjax' => true, 'noAjax' => true,
'roles'=>['root','developer','admin'] 'roles' => ['root', 'developer', 'admin'],
], ],
/* /*
*/ */