ADD supplier portal
This commit is contained in:
parent
5275dfcd0b
commit
1a9fa66af5
25
app/Enums/StockStatusEnum.php
Normal file
25
app/Enums/StockStatusEnum.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
enum StockStatusEnum: string
|
||||
{
|
||||
case InStock = 'in_stock';
|
||||
case OutOfStock = 'out_of_stock';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::InStock => 'Raktáron',
|
||||
self::OutOfStock => 'Nincs raktáron',
|
||||
};
|
||||
}
|
||||
|
||||
public function color(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::InStock => 'success',
|
||||
self::OutOfStock => 'danger',
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\SupplierPortal\Resources\ProductStocks\Pages;
|
||||
|
||||
use App\Filament\SupplierPortal\Resources\ProductStocks\ProductStockResource;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditProductStock extends EditRecord
|
||||
{
|
||||
protected static string $resource = ProductStockResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Action::make('back')
|
||||
->label('Vissza a listához')
|
||||
->url(fn () => ProductStockResource::getUrl('index'))
|
||||
->color('gray'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getRedirectUrl(): string
|
||||
{
|
||||
return ProductStockResource::getUrl('index');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\SupplierPortal\Resources\ProductStocks\Pages;
|
||||
|
||||
use App\Filament\SupplierPortal\Resources\ProductStocks\ProductStockResource;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListProductStocks extends ListRecords
|
||||
{
|
||||
protected static string $resource = ProductStockResource::class;
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\SupplierPortal\Resources\ProductStocks;
|
||||
|
||||
use App\Filament\SupplierPortal\Resources\ProductStocks\Pages\EditProductStock;
|
||||
use App\Filament\SupplierPortal\Resources\ProductStocks\Pages\ListProductStocks;
|
||||
use App\Filament\SupplierPortal\Resources\ProductStocks\Schemas\ProductStockForm;
|
||||
use App\Filament\SupplierPortal\Resources\ProductStocks\Tables\ProductStocksTable;
|
||||
use App\Models\Product;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class ProductStockResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Product::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCube;
|
||||
|
||||
protected static ?string $navigationLabel = 'Termékeim';
|
||||
|
||||
protected static ?string $breadcrumb = 'Termékeim';
|
||||
|
||||
protected static ?string $modelLabel = 'Termék';
|
||||
|
||||
protected static ?string $pluralLabel = 'Termékeim';
|
||||
|
||||
/**
|
||||
* Csak a bejelentkezett supplier saját termékei jelennek meg.
|
||||
*/
|
||||
public static function getEloquentQuery(): Builder
|
||||
{
|
||||
return parent::getEloquentQuery()
|
||||
->where('supplier_id', auth()->user()->supplier_id);
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return ProductStockForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return ProductStocksTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListProductStocks::route('/'),
|
||||
'edit' => EditProductStock::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\SupplierPortal\Resources\ProductStocks\Schemas;
|
||||
|
||||
use App\Enums\StockStatusEnum;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
class ProductStockForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema->components([
|
||||
Select::make('stock_status')
|
||||
->label('Készlet státusz')
|
||||
->options(
|
||||
collect(StockStatusEnum::cases())
|
||||
->mapWithKeys(fn (StockStatusEnum $case) => [$case->value => $case->label()])
|
||||
)
|
||||
->required(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\SupplierPortal\Resources\ProductStocks\Tables;
|
||||
|
||||
use App\Enums\StockStatusEnum;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Columns\ToggleColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class ProductStocksTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('name')
|
||||
->label('Termék neve')
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('sku')
|
||||
->label('Cikkszám')
|
||||
->searchable(),
|
||||
|
||||
ToggleColumn::make('stock_status')
|
||||
->label('Raktáron')
|
||||
->onColor('success')
|
||||
->offColor('danger')
|
||||
->getStateUsing(fn ($record) => $record->stock_status === StockStatusEnum::InStock)
|
||||
->updateStateUsing(function ($record, bool $state) {
|
||||
$record->stock_status = $state
|
||||
? StockStatusEnum::InStock
|
||||
: StockStatusEnum::OutOfStock;
|
||||
$record->save();
|
||||
}),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -132,6 +132,11 @@ private function getSupplierDataFromRequest(Request $request)
|
||||
$data['profitCenterId'] = \App\Models\ProfitCenter::whereIn('name', (array) $profitCenterNames)->get()->pluck('id')->toArray();
|
||||
}
|
||||
|
||||
$data['userId'] = [];
|
||||
if ($userIds = $request->get('userId')) {
|
||||
$data['userId'] = array_map('intval', (array) $userIds);
|
||||
}
|
||||
|
||||
if ($request->file('logoFile')) {
|
||||
$disk = 'image';
|
||||
// A Storage::path('') visszaadja a disk root könyvtárát
|
||||
@ -264,6 +269,31 @@ public function destroy(int $SupplierId): Response|JsonResponse
|
||||
|
||||
}
|
||||
|
||||
public function createUser(): JsonResponse
|
||||
{
|
||||
$data = \request()->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'email', 'max:255', 'unique:users,email'],
|
||||
'password' => ['required', 'string', 'min:8'],
|
||||
]);
|
||||
|
||||
$user = \App\Models\User::create([
|
||||
'name' => $data['name'],
|
||||
'email' => $data['email'],
|
||||
'password' => \Illuminate\Support\Facades\Hash::make($data['password']),
|
||||
]);
|
||||
|
||||
$supplierRole = \App\Models\Role::where('name', 'supplier')->first();
|
||||
if ($supplierRole) {
|
||||
$user->addRole($supplierRole);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'user' => ['id' => $user->id, 'name' => $user->name, 'email' => $user->email],
|
||||
]);
|
||||
}
|
||||
|
||||
public function getDataTableContent(): JsonResponse
|
||||
{
|
||||
|
||||
|
||||
@ -30,6 +30,10 @@ public function authenticate(Request $request)
|
||||
)) {
|
||||
$request->session()->regenerate();
|
||||
|
||||
if (Auth::user()->supplier_id !== null) {
|
||||
return redirect('/supplier-portal/product-stocks');
|
||||
}
|
||||
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\StockStatusEnum;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@ -15,6 +16,13 @@ class Product extends BaseAuditable
|
||||
protected $guarded = ['id'];
|
||||
// protected $fillable=['name'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'stock_status' => StockStatusEnum::class,
|
||||
];
|
||||
}
|
||||
|
||||
public function ProductGroup(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ProductGroup::class);
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Supplier extends BaseAuditable
|
||||
@ -43,6 +44,11 @@ public function profitCenter(): BelongsToMany
|
||||
return $this->belongsToMany(ProfitCenter::class)->withTimestamps();
|
||||
}
|
||||
|
||||
public function users(): HasMany
|
||||
{
|
||||
return $this->hasMany(User::class);
|
||||
}
|
||||
|
||||
public function attachment(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->morphMany(Attachment::class, 'attachable');
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Filament\Panel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
@ -14,7 +17,7 @@
|
||||
/**
|
||||
* @property Collection<ProfitCenter> profitCenters
|
||||
*/
|
||||
class User extends Authenticatable implements LaratrustUser
|
||||
class User extends Authenticatable implements LaratrustUser, FilamentUser
|
||||
{
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
use HasRolesAndPermissions;
|
||||
@ -29,6 +32,7 @@ class User extends Authenticatable implements LaratrustUser
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
'supplier_id',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -60,4 +64,18 @@ public function profitCenters(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(ProfitCenter::class, 'profit_center_users')->withTimestamps();
|
||||
}
|
||||
|
||||
public function supplier(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Supplier::class);
|
||||
}
|
||||
|
||||
public function canAccessPanel(Panel $panel): bool
|
||||
{
|
||||
return match ($panel->getId()) {
|
||||
'admin' => $this->hasRole(['root', 'developer', 'admin', 'profit-center']),
|
||||
'supplierPortal' => $this->hasRole('supplier'),
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
75
app/Policies/ProductPolicy.php
Normal file
75
app/Policies/ProductPolicy.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
|
||||
class ProductPolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->hasRole(['root', 'developer', 'admin', 'supplier']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, Product $product): bool
|
||||
{
|
||||
if ($user->hasRole('supplier')) {
|
||||
return $user->supplier_id === $product->supplier_id;
|
||||
}
|
||||
|
||||
return $user->hasRole(['root', 'developer', 'admin']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->hasRole(['root', 'developer', 'admin']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Csak akkor engedélyezett a szerkesztés, ha a termék
|
||||
* a bejelentkezett supplier-hez tartozik.
|
||||
*/
|
||||
public function update(User $user, Product $product): bool
|
||||
{
|
||||
if ($user->hasRole('supplier')) {
|
||||
return $user->supplier_id === $product->supplier_id;
|
||||
}
|
||||
|
||||
return $user->hasRole(['root', 'developer', 'admin']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, Product $product): bool
|
||||
{
|
||||
return $user->hasRole(['root', 'developer', 'admin']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore the model.
|
||||
*/
|
||||
public function restore(User $user, Product $product): bool
|
||||
{
|
||||
return $user->hasRole(['root', 'developer', 'admin']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete the model.
|
||||
*/
|
||||
public function forceDelete(User $user, Product $product): bool
|
||||
{
|
||||
return $user->hasRole(['root', 'developer', 'admin']);
|
||||
}
|
||||
}
|
||||
83
app/Providers/Filament/SupplierPanelProvider.php
Normal file
83
app/Providers/Filament/SupplierPanelProvider.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers\Filament;
|
||||
|
||||
use Filament\Http\Middleware\Authenticate;
|
||||
use Filament\Http\Middleware\AuthenticateSession;
|
||||
use Filament\Http\Middleware\DisableBladeIconComponents;
|
||||
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
||||
use Filament\Panel;
|
||||
use Filament\PanelProvider;
|
||||
use Filament\Support\Colors\Color;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||
use Illuminate\Routing\Middleware\SubstituteBindings;
|
||||
use Illuminate\Session\Middleware\StartSession;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
|
||||
class SupplierPanelProvider extends PanelProvider
|
||||
{
|
||||
public function panel(Panel $panel): Panel
|
||||
{
|
||||
return $panel
|
||||
->id('supplierPortal')
|
||||
->path('supplier-portal')
|
||||
->login()
|
||||
->brandName(fn () => auth()->check() && auth()->user()->supplier
|
||||
? 'Beszállítói Portál – ' . auth()->user()->supplier->name
|
||||
: 'Beszállítói Portál')
|
||||
->colors([
|
||||
'primary' => '#b83400',
|
||||
'gray' => [
|
||||
50 => '#f6f5f0',
|
||||
100 => '#eceadf',
|
||||
200 => '#d1cfc0',
|
||||
300 => '#b4b19b',
|
||||
400 => '#9e9b81',
|
||||
500 => '#7d775c',
|
||||
600 => '#6d6850',
|
||||
700 => '#453821',
|
||||
800 => '#3a301c',
|
||||
900 => '#2d2516',
|
||||
950 => '#1f1a0f',
|
||||
],
|
||||
'danger' => Color::Red,
|
||||
'info' => Color::Blue,
|
||||
'success' => Color::Emerald,
|
||||
'warning' => Color::Orange,
|
||||
])
|
||||
->font('Trebuchet MS')
|
||||
->discoverResources(
|
||||
in: app_path('Filament/SupplierPortal/Resources'),
|
||||
for: 'App\Filament\SupplierPortal\Resources'
|
||||
)
|
||||
->discoverPages(
|
||||
in: app_path('Filament/SupplierPortal/Pages'),
|
||||
for: 'App\Filament\SupplierPortal\Pages'
|
||||
)
|
||||
->pages([])
|
||||
->discoverWidgets(
|
||||
in: app_path('Filament/SupplierPortal/Widgets'),
|
||||
for: 'App\Filament\SupplierPortal\Widgets'
|
||||
)
|
||||
->widgets([])
|
||||
->middleware([
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartSession::class,
|
||||
AuthenticateSession::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
SubstituteBindings::class,
|
||||
DisableBladeIconComponents::class,
|
||||
DispatchServingFilamentEvent::class,
|
||||
])
|
||||
->authMiddleware([
|
||||
Authenticate::class,
|
||||
])
|
||||
->darkMode(false)
|
||||
->breadcrumbs(false)
|
||||
->navigation(false);
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ class SupplierRepository extends RepositoryBase implements SupplierRepositoryInt
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
private array $defaultRelations = ['contact', 'productGroup', 'attachment', 'service'];
|
||||
private array $defaultRelations = ['contact', 'productGroup', 'attachment', 'service', 'users'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@ -96,6 +96,16 @@ public function syncProfitCenter($supplierId, $profitCenterIds = []): bool
|
||||
return true;
|
||||
}
|
||||
|
||||
public function syncUsers($supplierId, $userIds = []): bool
|
||||
{
|
||||
\App\Models\User::where('supplier_id', $supplierId)->whereNotIn('id', $userIds)->update(['supplier_id' => null]);
|
||||
if (count($userIds) > 0) {
|
||||
\App\Models\User::whereIn('id', $userIds)->update(['supplier_id' => $supplierId]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's a record by it's ID
|
||||
*
|
||||
|
||||
@ -19,4 +19,6 @@ public function syncProductGroup($supplierId, $productGroupIds = []): bool;
|
||||
public function syncService($supplierId, $productGroupIds = []): bool;
|
||||
|
||||
public function syncProfitCenter($supplierId, $profitCenterIds = []): bool;
|
||||
|
||||
public function syncUsers($supplierId, $userIds = []): bool;
|
||||
}
|
||||
|
||||
@ -53,13 +53,19 @@ public function syncProfitCenter($supplierId, $profitCenterIds = []): bool
|
||||
return $this->Repository->syncProfitCenter($supplierId, $profitCenterIds);
|
||||
}
|
||||
|
||||
public function syncUsers($supplierId, $userIds = []): bool
|
||||
{
|
||||
return $this->Repository->syncUsers($supplierId, $userIds);
|
||||
}
|
||||
|
||||
public function add($data): ?int
|
||||
{
|
||||
$contactIds = $data['contactId'];
|
||||
$productGroupId = $data['productGroupId'];
|
||||
$serviceId = $data['serviceId'];
|
||||
$profitCenterId = $data['profitCenterId'];
|
||||
unset($data['contactId'],$data['productGroupId']);
|
||||
$userIds = $data['userId'] ?? [];
|
||||
unset($data['contactId'], $data['productGroupId'], $data['userId']);
|
||||
if (! $supplierId = parent::add($data)) {
|
||||
return false;
|
||||
}
|
||||
@ -67,6 +73,7 @@ public function add($data): ?int
|
||||
$this->addProductGroup($supplierId, $productGroupId);
|
||||
$this->syncService($supplierId, $serviceId);
|
||||
$this->syncProfitCenter($supplierId, $profitCenterId);
|
||||
$this->syncUsers($supplierId, $userIds);
|
||||
|
||||
return $supplierId;
|
||||
}
|
||||
@ -83,12 +90,14 @@ public function update($id, array $data): bool
|
||||
$productGroupId = $data['productGroupId'];
|
||||
$serviceId = $data['serviceId'];
|
||||
$profitCenterId = $data['profitCenterId'];
|
||||
unset($data['contactId'],$data['productGroupId']);
|
||||
$userIds = $data['userId'] ?? [];
|
||||
unset($data['contactId'], $data['productGroupId'], $data['userId']);
|
||||
if ($this->Repository->update($id, $data)) {
|
||||
$this->syncContact($id, $contactIds);
|
||||
$this->syncProductGroup($id, $productGroupId);
|
||||
$this->syncService($id, $serviceId);
|
||||
$this->syncProfitCenter($id, $profitCenterId);
|
||||
$this->syncUsers($id, $userIds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3,4 +3,5 @@
|
||||
return [
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\Filament\AdminPanelProvider::class,
|
||||
App\Providers\Filament\SupplierPanelProvider::class,
|
||||
];
|
||||
|
||||
@ -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('users', function (Blueprint $table) {
|
||||
$table->foreignId('supplier_id')->nullable()->after('id')->constrained('suppliers')->nullOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropForeign(['supplier_id']);
|
||||
$table->dropColumn('supplier_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -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('products', function (Blueprint $table) {
|
||||
$table->string('stock_status')->default('in_stock')->after('status');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->dropColumn('stock_status');
|
||||
});
|
||||
}
|
||||
};
|
||||
34
database/seeders/SupplierRoleSeeder.php
Normal file
34
database/seeders/SupplierRoleSeeder.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Permission;
|
||||
use App\Models\Role;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class SupplierRoleSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$permission = Permission::firstOrCreate(
|
||||
['name' => 'update_own_product_stock_status'],
|
||||
[
|
||||
'display_name' => 'Saját termék készlet státusz módosítása',
|
||||
'description' => 'A beszállító módosíthatja a saját termékei raktárkészlet státuszát',
|
||||
]
|
||||
);
|
||||
|
||||
$role = Role::firstOrCreate(
|
||||
['name' => 'supplier'],
|
||||
[
|
||||
'display_name' => 'Beszállító',
|
||||
'description' => 'Supplier Portal hozzáférés',
|
||||
]
|
||||
);
|
||||
|
||||
$role->givePermission($permission);
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
{
|
||||
"/js/app.js": "/js/app.js?id=8eebbb7cc03522e40f2a774f36c0d6b0",
|
||||
"/js/admin.js": "/js/admin.js?id=d76685d0f99353516174c9e2fe1b0f53",
|
||||
"/js/module.js": "/js/module.js?id=32c2ae0c49eb610fe11a304d1ca623f1",
|
||||
"/js/admin.js": "/js/admin.js?id=dff6f8df5f29b21dcf8daab2872577a2",
|
||||
"/js/module.js": "/js/module.js?id=b8f30ac658c1296e35f9210683fe57c9",
|
||||
"/js/components.js": "/js/components.js?id=34668cee8ac371c98657beffcff579b8",
|
||||
"/css/app.css": "/css/app.css?id=11474616a7ef31af1acf43a25d65f4b6",
|
||||
"/fonts/vendor/bootstrap-icons/bootstrap-icons.woff2?92ea18a81d737146ff044ddb52010366": "/fonts/vendor/bootstrap-icons/bootstrap-icons.woff2?92ea18a81d737146ff044ddb52010366?id=9ad5aa740d7d5e6a0191b309b9b1986c",
|
||||
|
||||
@ -42,6 +42,7 @@ window.SupplierAdmin=function (options,SupplierItem) {
|
||||
destroy:'',
|
||||
attachFile:'',
|
||||
detachFile:'',
|
||||
createUser:'',
|
||||
},
|
||||
dataTable:{
|
||||
orderDirective:[1, 'asc']
|
||||
@ -243,6 +244,9 @@ window.SupplierAdmin=function (options,SupplierItem) {
|
||||
if(typeof root.Supplier['logoFile']!='undefined' && (root.Supplier['logoFile'])){
|
||||
$(CSSSelectorForm+' img.imageLogo').attr('src',root.Supplier['logoFile']);
|
||||
}
|
||||
if(typeof root.Supplier.users !== 'undefined'){
|
||||
root.resetUserTable();
|
||||
}
|
||||
|
||||
//debug(APP.SupplierAdmin.formDataToDataObjectAPICall('.supplierForm')['productGroup']);
|
||||
//$('[name=productGroup]').val(['Büféáru_édesipari_termékek','Tojás']).change();
|
||||
@ -288,6 +292,7 @@ window.SupplierAdmin=function (options,SupplierItem) {
|
||||
$('form.supplierForm button.FormSaveButton').off('click');
|
||||
$('form.supplierForm button.FormSaveButton').on('click',root.clickSaveButton);
|
||||
root.setDetailsViewData();
|
||||
root.initUserCreate();
|
||||
$(".productCategorySelect").select2();
|
||||
$(".serviceSelect").select2({
|
||||
tags: true,
|
||||
@ -802,5 +807,93 @@ window.SupplierAdmin=function (options,SupplierItem) {
|
||||
}
|
||||
|
||||
|
||||
this.resetUserTable=function (){
|
||||
$('.supplierUserTable tbody tr').remove();
|
||||
root.renderUsers();
|
||||
}
|
||||
this.renderUsers=function (){
|
||||
let rowNum=1;
|
||||
let users=root.Supplier.users||[];
|
||||
$.each(users,function (){
|
||||
let userData=$.extend({},this);
|
||||
userData.rowNum=rowNum;
|
||||
let template=$('template[data-name="supplierUserTableRow"]').html();
|
||||
let render=Mustache.render(template,userData);
|
||||
$('.supplierUserTable tbody').append(render);
|
||||
rowNum++;
|
||||
});
|
||||
root.bindUserClickAction();
|
||||
}
|
||||
this.bindUserClickAction=function (){
|
||||
let node=$('.supplierUserTable .buttonDelete');
|
||||
node.unbind('click');
|
||||
node.bind('click',root.userDeleteClick);
|
||||
}
|
||||
this.userDeleteClick=function (){
|
||||
let row=$(this).closest('tr');
|
||||
let id=row.find('input[name=userId]').val()*1;
|
||||
root.Supplier.users=root.Supplier.users.filter(function (value){
|
||||
return value.id!==id;
|
||||
});
|
||||
row.remove();
|
||||
root.resetUserTable();
|
||||
}
|
||||
this.addUser=function (userData){
|
||||
if(!root.Supplier.users){ root.Supplier.users=[]; }
|
||||
let alreadyAdded=root.Supplier.users.some(function(u){ return u.id===userData.id; });
|
||||
if(alreadyAdded){ return; }
|
||||
root.Supplier.users.push(userData);
|
||||
userData.rowNum=root.Supplier.users.length;
|
||||
let template=$('template[data-name="supplierUserTableRow"]').html();
|
||||
let render=Mustache.render(template,userData);
|
||||
$('.supplierUserTable tbody').append(render);
|
||||
root.bindUserClickAction();
|
||||
Toast.enableTimers(false);
|
||||
Toast.create({ title: 'Felhasználó hozzáadva!', message: userData.name+' hozzárendelve', status: TOAST_STATUS.SUCCESS, timeout: 3000 });
|
||||
}
|
||||
this.initUserCreate=function (){
|
||||
let createUrl=Opts.URL.createUser||'';
|
||||
let container=$(Opts.containerCssSelector);
|
||||
function clearForm(){
|
||||
container.find('.supplierNewUserName').val('');
|
||||
container.find('.supplierNewUserEmail').val('');
|
||||
container.find('.supplierNewUserPassword').val('');
|
||||
container.find('.supplierNewUserError').hide().text('');
|
||||
}
|
||||
container.find('.buttonCreateUser').off('click').on('click',function(){
|
||||
let name=container.find('.supplierNewUserName').val().trim();
|
||||
let email=container.find('.supplierNewUserEmail').val().trim();
|
||||
let password=container.find('.supplierNewUserPassword').val();
|
||||
let errorEl=container.find('.supplierNewUserError');
|
||||
errorEl.hide().text('');
|
||||
if(!name||!email||!password){
|
||||
errorEl.text('Minden mező kitöltése kötelező!').show();
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url:createUrl,
|
||||
type:'POST',
|
||||
data:{name:name, email:email, password:password},
|
||||
headers:{'X-CSRF-TOKEN': $('input[name="_token"]').val()},
|
||||
success:function(data){
|
||||
if(data.success){
|
||||
root.addUser(data.user);
|
||||
clearForm();
|
||||
}else{
|
||||
errorEl.text('Hiba történt a felhasználó létrehozásakor!').show();
|
||||
}
|
||||
},
|
||||
error:function(xhr){
|
||||
let msg='Hiba történt!';
|
||||
if(xhr.responseJSON&&xhr.responseJSON.errors){
|
||||
let errors=xhr.responseJSON.errors;
|
||||
let firstKey=Object.keys(errors)[0];
|
||||
msg=errors[firstKey][0];
|
||||
}
|
||||
errorEl.text(msg).show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
this.construct(options,SupplierItem);
|
||||
};
|
||||
|
||||
@ -118,6 +118,71 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Supplier Portal felhasználók:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="card mb-2">
|
||||
<div class="card-header">Új felhasználó hozzáadása</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group row mb-2">
|
||||
<label class="col-sm-2 col-form-label col-form-label-sm">Név</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control form-control-sm supplierNewUserName" placeholder="Felhasználó neve">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label class="col-sm-2 col-form-label col-form-label-sm">E-mail</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="email" class="form-control form-control-sm supplierNewUserEmail" placeholder="E-mail cím">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-2">
|
||||
<label class="col-sm-2 col-form-label col-form-label-sm">Jelszó</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control form-control-sm supplierNewUserPassword" placeholder="Jelszó">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row mb-0">
|
||||
<div class="col-sm-10 offset-sm-2">
|
||||
<button type="button" class="btn btn-primary btn-sm buttonCreateUser">Felhasználó létrehozása</button>
|
||||
<span class="supplierNewUserError text-danger ml-2" style="display:none;"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col">
|
||||
<table class="table table-striped table-hover table-sm supplierUserTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col">Név</th>
|
||||
<th scope="col">E-mail</th>
|
||||
<th scope="col">Akció</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template data-name="supplierUserTableRow">
|
||||
<tr>
|
||||
<th scope="row">[[rowNum]]
|
||||
<input type="hidden" name="userId" value="[[id]]"/>
|
||||
</th>
|
||||
<td>[[name]]</td>
|
||||
<td>[[email]]</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-danger btn-sm buttonDelete" data-toggle="tooltip" data-placement="bottom" title="Törlés">
|
||||
<span class="fas fa-trash"></span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="OrderEmail" class="col-sm-2 col-form-label" >E-mail:</label>
|
||||
<div class="col-sm-10">
|
||||
|
||||
@ -81,6 +81,7 @@
|
||||
destroy:'{{route('admin.supplier.destroy',"%id%")}}',
|
||||
attachFile:'{{route('admin.supplier.attachFile',"%id%")}}',
|
||||
detachFile:'{{route('admin.supplier.detachFile',"%id%")}}',
|
||||
createUser:'{{route('admin.supplier.createUser')}}',
|
||||
},
|
||||
testMode:{{$testMode}}
|
||||
},APP.Supplier);
|
||||
|
||||
@ -185,6 +185,7 @@ function () {
|
||||
// Route::resource('/supplier', SupplierControllerAdmin::class);
|
||||
Route::prefix('supplier')->name('supplier.')->group(function () {
|
||||
Route::get('getDataTableContent', [SupplierControllerAdmin::class, 'getDataTableContent'])->name('getDataTableContent');
|
||||
Route::post('createUser', [SupplierControllerAdmin::class, 'createUser'])->name('createUser');
|
||||
Route::post('/{id}/attachFile', [SupplierControllerAdmin::class, 'attachFile'])->name('attachFile');
|
||||
Route::post('/{id}/detachFile', [SupplierControllerAdmin::class, 'detachFile'])->name('detachFile');
|
||||
Route::resource('/', SupplierControllerAdmin::class)->parameters(['' => 'supplier']);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user