доработка функционала регионального менеджера

This commit is contained in:
Thekindbull 2025-11-22 21:12:31 +08:00
parent 75b587131f
commit f28f58b742
15 changed files with 268 additions and 69 deletions

View File

@ -40,7 +40,7 @@ class Kernel extends HttpKernel
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
@ -53,16 +53,16 @@ class Kernel extends HttpKernel
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}

View File

@ -2,18 +2,24 @@
namespace Modules\Admin\Http\Controllers;
use Illuminate\Http\Request;
use Modules\Main\Models\City;
use Modules\Post\Models\Post;
use Modules\Post\Models\PostCategory;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\Post\Models\PostCategory;
use Illuminate\Support\Facades\Storage;
class AdminPostsController extends Controller
{
public function index()
{
$posts = Post::orderBy('id', 'desc')->get();
$posts = Post::orderBy('id', 'desc');
if (!auth()->user()->isAdmin() && auth()->user()->isCityManager())
{
}
$posts = $posts->get();
return view('admin::posts.index', [
'posts' => $posts
]);
@ -40,6 +46,15 @@ public function store(Request $request)
$post = Post::create(
$request->only(['name', 'short_text', 'text', 'category', 'image'])
);
if (array_key_exists('cities', $request->all()) && is_array($request['cities']))
{
foreach ($request->cities as $cityId)
{
$post->cities()->create([
'city_id' => $cityId,
]);
}
}
return to_route('admin.posts');
}

View File

@ -1,53 +1,44 @@
<div>
@if (in_array($roles::SUPER_ADMIN, $userRoles))
<ul class="nav flex flex-md-column">
<li class="d-none d-md-block">
<h6 class="dropdown-header text-uppercase">Основное</h6>
</li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.posts') }}">Новости</a>
</li>
<li class="nav-item text-center m-2 d-none"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4" href="#">Объекты</a></li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.users') }}">Пользователи</a>
</li>
<li>
<h6 class="dropdown-header text-uppercase">Справочники</h6>
</li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.cities', ['filter' => 'actual']) }}">Города</a></li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.complexes', ['filter' => 'actual']) }}">ЖК</a>
</li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.cities.managers') }}">Менеджеры</a>
</li>
<li>
<h6 class="dropdown-header text-uppercase">Агентства</h6>
</li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.companies') }}">Организации</a></li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.payments') }}">Вознаграждения</a></li>
<li>
<h6 class="dropdown-header text-uppercase">Прочее</h6>
</li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.docs') }}">Документы</a></li>
<li>
<h6 class="dropdown-header text-uppercase">Интеграции</h6>
</li>
<li class="nav-item text-center m-2"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.bitrix') }}">Битрикс24</a></li>
</ul>
@endif
<ul class="nav flex flex-md-column">
<li class="d-none d-md-block">
<h6 class="dropdown-header text-uppercase">Основное</h6>
</li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.posts') }}">Новости</a>
</li>
<li class="nav-item text-center m-2 d-none"><a
class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4" href="#">Объекты</a></li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.users') }}">Пользователи</a>
</li>
<li>
<h6 class="dropdown-header text-uppercase">Справочники</h6>
</li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.cities', ['filter' => 'actual']) }}">Города</a></li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.complexes', ['filter' => 'actual']) }}">ЖК</a>
</li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.cities.managers') }}">Менеджеры</a>
</li>
<li>
<h6 class="dropdown-header text-uppercase">Агентства</h6>
</li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.companies') }}">Организации</a></li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.payments') }}">Вознаграждения</a></li>
<li>
<h6 class="dropdown-header text-uppercase">Прочее</h6>
</li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.docs') }}">Документы</a></li>
<li>
<h6 class="dropdown-header text-uppercase">Интеграции</h6>
</li>
<li class="nav-item text-center m-2"><a class="nav-link d-flex align-items-center gap-2 fs-5 border rounded-4"
href="{{ route('admin.bitrix') }}">Битрикс24</a></li>
</ul>
</div>

View File

@ -49,6 +49,7 @@
<div class="text-danger">{{ $message }}</div>
@enderror
</div>
<input type="text" name="cities[0]" value="1" />
<button type="submit" class="btn btn-primary">Сохранить</button>
</form>
@endsection

View File

@ -17,6 +17,7 @@
<tr scope="row">
<td class="align-middle">
{{ $post->name }}
<br>{{ $post->city }}
</td>
<td>
{{ $post->created_at->diffForHumans() }}

View File

@ -81,6 +81,7 @@ protected static function booted()
}
throw new \Exception('Error of bitrix identifier getter for ' . $bitrixId->bitrixable_type . ' with id ' . $bitrixId->bitrixable_id);
});
static::created(function (BitrixId $bitrixId)
{
if (!$bitrixId->bx_id)

View File

@ -0,0 +1,31 @@
<?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::create('city_appends', function (Blueprint $table)
{
$table->id();
$table->morphs('append');
$table->foreignId('city_id')->references('id')->on('cities')->onDelete('cascade');
$table->text('data')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('client_contract');
}
};

View File

@ -1,7 +1,9 @@
<?php
use Modules\Contracts\Models\ContractStatus;
use Modules\Main\Models\Company\Company;
use Modules\Main\Models\Company\CompanyAdmin;
use Modules\CityManager\Models\CityManager;
use Modules\Main\Models\Agent\Agent;
use Modules\Main\Models\Complex;
@ -47,9 +49,16 @@ function GetAvailableAgents()
}
else
{
$agents = Agent::where('user_id', auth()->user()->id);
$cityManager = CityManager::where('user_id', auth()->user()->id);
if ($cityManager->count())
{
$agents = Agent::whereIn('company_id', Company::where('city_id', $cityManager->city_id)->get()->pluck('company_id'));
}
else
{
$agents = Agent::where('user_id', auth()->user()->id);
}
}
$agents->with('company:id,name');
$agents->with('user:id,name');
return $agents->get()->toArray();
@ -78,4 +87,31 @@ function GetAvailableComplexes()
}
return [];
}
}
if (!function_exists('GetAvailableCities'))
{
function GetAvailableAgents()
{
$agents = [];
if ($adminCompany = AdminCompanyOfUser())
{
$agents = Agent::where('company_id', $adminCompany->id);
}
else
{
$cityManager = CityManager::where('user_id', auth()->user()->id);
if ($cityManager->count())
{
$agents = Agent::whereIn('company_id', Company::where('city_id', $cityManager->city_id)->get()->pluck('company_id'));
}
else
{
$agents = Agent::where('user_id', auth()->user()->id);
}
}
$agents->with('company:id,name');
$agents->with('user:id,name');
return $agents->get()->toArray();
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace Modules\Main\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class CityAppend extends Model
{
use HasFactory;
protected $fillable = [
'city_id',
'data'
];
public function object(): MorphTo
{
return $this->morphTo();
}
}

View File

@ -19,13 +19,14 @@ public function register()
public function boot()
{
$this->registerPolicies();
$this->registerViews();
$this->registerLivewireViews();
$this->registerMigrations();
$this->registerConfig();
$this->registerComponent();
$this->registerLivewire();
$this->registerPolicies();
$this->registerHelpers();
}
protected function registerViews()
@ -77,4 +78,13 @@ protected function registerPolicies()
{
Gate::policy(\Modules\Main\Models\Company\Company::class, \Modules\Main\Http\Policies\CompanyPolicy::class);
}
protected function registerHelpers()
{
$files = glob(__DIR__ . '/../Helpers/' . "*.php");
foreach ($files as $key => $file)
{
require_once $file;
}
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Modules\Main\Traits;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Modules\Main\Models\CityAppend;
trait CityAppendTrait
{
public function cities(): MorphMany
{
return $this->MorphMany(CityAppend::class, 'append');
}
public function byCity(Builder $query, $cityId)
{
//return $query->where('category', $category);
}
}

View File

@ -2,11 +2,17 @@
namespace Modules\Post\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Modules\Main\Models\City;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Modules\Main\Traits\CityAppendTrait;
class Post extends Model
{
use HasFactory;
use CityAppendTrait;
protected $fillable = [
'name',

View File

@ -57,6 +57,30 @@ public function getPartialsName()
'familyName' => (array_key_exists(2, $name) ? $name[2] : '')
];
}
/**
* Функция проверят наличие роли у пользователя
* @param mixed $roleId - лучше брать из констант модели Modules\User\Models\Role
* @return bool
*/
public function hasRole($roleId)
{
$roles = $this->roles()->get();
if ($roles->where('id', $roleId)->count())
{
return true;
}
return false;
}
public function isAdmin()
{
return $this->hasRole(Role::SUPER_ADMIN);
}
public function isCityManager()
{
return $this->hasRole(Role::CITY_MANAGER);
}
public function roles(): HasManyThrough
{
@ -75,4 +99,5 @@ public function roles(): HasManyThrough
);
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Modules\User\Providers;
use Illuminate\Support\Facades\Blade;
use Livewire\Livewire;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Auth;
use Modules\User\Models\UserRole;
use Modules\User\Models\Role;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
Gate::define('admin', function ($user)
{
if (!Auth::check())
{
abort(403, 'Unauthorized action');
}
$user = Auth::user();
if (
!UserRole::where('user_id', $user->id)
->where('role_id', Role::SUPER_ADMIN)->count()
)
{
abort(403, 'Unauthorized action');
}
return true;
});
}
}

View File

@ -12,6 +12,7 @@ class ModuleServiceProvider extends ServiceProvider
public function register()
{
$this->app->register(AuthServiceProvider::class);
$this->app->register(RouteServiceProvider::class);
}