добавлено редактирование вознаграждений в админку

This commit is contained in:
Thekindbull 2025-04-24 15:11:24 +08:00
parent f6828a0fa7
commit d2ceee50f5
18 changed files with 595 additions and 41 deletions

View File

@ -15,10 +15,13 @@
use App\Notifications\AgentCreated;
use Modules\Payment\Traits\Paymentable;
class Agent extends Model
{
use HasFactory;
use SoftDeletes;
use Paymentable;
public const STATUS_ACTIVE = "ACTIVE";
public const STATUS_DISMISSED = "DISMISSED";
protected $fillable = [

View File

@ -4,12 +4,12 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Modules\Payment\Traits\Paymentable;
class Company extends Model
{
{
use HasFactory;
const STATUS_NEW = 'new';
use Paymentable;
const STATUS_NEW = 'new';
const STATUS_ACCEPTED = 'accepted';
const STATUS_DECLINED = 'declined';
protected $fillable = [
@ -27,6 +27,6 @@ class Company extends Model
protected $casts = [
'details' => 'array',
'type' => CompanyType::class
'type' => CompanyType::class
];
}
}

View File

@ -8,19 +8,12 @@
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Company\Company;
use App\Models\Complex;
use App\Models\Agent\Agent;
class AdminPaymentsController extends Controller
{
public function index()
{
return view('admin::payments.index', [
'companies' => Company::orderBy('name')->get(),
'complexes' => Complex::orderBy('name')->get(),
'agents' => Agent::all()
]);
return view('admin::payments.index');
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace Modules\Admin\Http\Livewire;
use Livewire\Component;
use App\Models\Company\Company;
use App\Models\Complex;
use App\Models\Agent\Agent;
class Payments extends Component
{
public $value;
public $companyId;
public function mount()
{
}
public function setCompany(Company $company)
{
$this->companyId = $company->id;
}
public function back()
{
$this->companyId = null;
}
public function setPaymentValueForCompany(Company $company, Complex $complex)
{
$company->setPayment($complex, $this->value);
$this->value = null;
}
public function unsetPaymentForCompany(Company $company, Complex $complex)
{
$company->unsetPayment($complex);
}
public function setPaymentValueForAgent(Agent $agent, Complex $complex)
{
$agent->setPayment($complex, $this->value);
$this->value = null;
}
public function setPaymentAsParentForAgent(Agent $agent, Complex $complex)
{
$agent->setAsParentPayment($complex);
$this->value = null;
}
public function unsetPaymentForAgent(Agent $agent, Complex $complex)
{
$agent->unsetPayment($complex);
}
public function render()
{
if ($this->companyId)
{
return view('admin::payments.agents', [
'company' => Company::find($this->companyId),
'complexes' => Complex::orderBy('name')->get(),
'agents' => Agent::where('company_id', $this->companyId)->
with([
'user' => function ($query)
{
$query->orderBy('name', 'desc');
}
])->get()
]);
}
else
{
return view('admin::payments.companies', [
'companies' => Company::orderBy('name')->get(),
'complexes' => Complex::orderBy('name')->get(),
]);
}
}
}

View File

@ -63,6 +63,8 @@ protected function registerLivewire()
{
Livewire::component('admin.menu', \Modules\Admin\Http\Livewire\AdminMenu::class);
Livewire::component('admin.posts', \Modules\Admin\Http\Livewire\Posts::class);
Livewire::component('admin.payments', \Modules\Admin\Http\Livewire\Payments::class);
}
protected function registerComponent()

View File

@ -0,0 +1,124 @@
<div>
<button wire:click="back" class="btn border-0 icon-link icon-link-hover fs-5 mb-3 text-decoration-none text-primary"
style="--bs-icon-link-transform: translate3d(-.125rem, 0, 0);" href="#">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left"
viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0" />
</svg>
{{ $company->name }}
</button>
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 py-3">
<table class="table m-0">
<thead>
<tr scope="col">
<th>Агент</th>
@foreach ($complexes as $complex)
<th>
{{ $complex->name }}
<div>
@php($compPayment = $company->getPaymentable($complex))
<span class="badge bg-secondary">
@if ($compPayment->value === null)
Не установлено
@elseif($compPayment->value == -1)
Наследовать
@else
{{ $compPayment->value }} %
@endif
</span>
</div>
</th>
@endforeach
</tr>
</thead>
<tbody class=" ">
@foreach ($agents as $agent)
<tr scope="row">
<td class="align-middle">
{{ $agent->user->name }}
</td>
@foreach ($complexes as $complex)
@php($paymentable = $agent->getPaymentable($complex))
<td>
@if ($paymentable->value == null)
<div class="dropdown">
<button class="btn btn-light btn-sm" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
Не установлено
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#">
<input class="form-control form-control-sm" type="text"
placeholder="Процент вознаграждения" wire:model = "value"
wire:keydown.enter="setPaymentValueForAgent({{ $agent->id }}, {{ $complex->id }})">
</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li><button class="dropdown-item"
wire:click="setPaymentAsParentForAgent({{ $agent->id }}, {{ $complex->id }})">Наследовать</button>
</li>
</ul>
</div>
@elseif($paymentable->value == -1)
<div class="dropdown">
<button class="btn btn-light btn-sm" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
Наследовать
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#">
<input class="form-control form-control-sm" type="text"
placeholder="Процент вознаграждения" wire:model = "value"
wire:keydown.enter="setPaymentValueForAgent({{ $agent->id }}, {{ $complex->id }})">
</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li><button class="dropdown-item"
wire:click="unsetPaymentForAgent({{ $agent->id }}, {{ $complex->id }})">Без
вознаграждения</button></li>
</ul>
</div>
@else
<div class="dropdown">
<button class="btn btn-light" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
{{ $paymentable->value }} %
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#">
<input class="form-control form-control-sm" type="text"
placeholder="Процент вознаграждения"
value="{{ $paymentable->value }}" wire:model = "value"
wire:keydown.enter="setPaymentValueForAgent({{ $agent->id }}, {{ $complex->id }})">
</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item disabled" href="#">Наследовать</a></li>
<li><button class="dropdown-item"
wire:click="unsetPaymentForAgent({{ $agent->id }}, {{ $complex->id }})">Без
вознаграждения</button>
</li>
<li><button class="dropdown-item"
wire:click="setPaymentAsParentForAgent({{ $agent->id }}, {{ $complex->id }})">Наследовать</button>
</li>
</ul>
</div>
@endif
</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
</div>
</div>

View File

@ -0,0 +1,97 @@
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 py-3">
<table class="table m-0">
<thead>
<tr scope="col">
<th>Компания</th>
@foreach ($complexes as $complex)
<th>{{ $complex->name }}
</th>
@endforeach
<th></th>
</tr>
</thead>
<tbody class=" ">
@foreach ($companies as $company)
<tr scope="row">
<td class="align-middle">
{{ $company->name }}
</td>
@foreach ($complexes as $complex)
@php($paymentable = $company->getPaymentable($complex))
<td>
@if ($paymentable->value == null)
<div class="dropdown">
<button class="btn btn-light btn-sm" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
Не установлено
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#">
<input class="form-control form-control-sm" type="text"
placeholder="Процент вознаграждения" wire:model = "value"
wire:keydown.enter="setPaymentValueForCompany({{ $company->id }}, {{ $complex->id }})">
</a>
</li>
</ul>
</div>
@elseif($paymentable->value == -1)
<div class="dropdown">
<button class="btn btn-light btn-sm" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
Наследовать
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#">
<input class="form-control form-control-sm" type="text"
placeholder="Процент вознаграждения" wire:model = "value"
wire:keydown.enter="setPaymentValueForCompany({{ $company->id }}, {{ $complex->id }})">
</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li><button class="dropdown-item"
wire:click="unsetPaymentForCompany({{ $company->id }}, {{ $complex->id }})">Без
вознаграждения</button></li>
</ul>
</div>
@else
<div class="dropdown">
<button class="btn btn-light" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
{{ $paymentable->value }} %
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item" href="#">
<input class="form-control form-control-sm" type="text"
placeholder="Процент вознаграждения"
value="{{ $paymentable->value }}" wire:model = "value"
wire:keydown.enter="setPaymentValueForCompany({{ $company->id }}, {{ $complex->id }})">
</a>
</li>
<li>
<hr class="dropdown-divider">
</li>
<li><button class="dropdown-item"
wire:click="unsetPaymentForCompany({{ $company->id }}, {{ $complex->id }})">Без
вознаграждения</button>
</li>
<!--<li><a class="dropdown-item" href="#">Something else here</a></li>-->
</ul>
</div>
@endif
</td>
@endforeach
<td>
<button class="btn btn-light" wire:click="setCompany({{ $company->id }})">
<i class="bi bi-chevron-right"></i>
</button>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>

View File

@ -1,31 +1,5 @@
@php($title = 'Вознаграждения')
@extends('layouts.admin')
@section('content')
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 py-3">
<table class="table m-0">
<thead>
<tr scope="col">
<th>Компания</th>
@foreach ($complexes as $complex)
<th>{{ $complex->name }}
<div><a href="#" class="" style="text-decoration-style: dotted;">0 %</a>
</div>
</th>
@endforeach
</tr>
</thead>
<tbody class=" ">
@foreach ($companies as $company)
<tr scope="row">
<td class="align-middle">
{{ $company->name }}
</td>
@foreach ($complexes as $complex)
<td><a href="#" class="" style="text-decoration-style: dotted;">Наследовать</a></td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
</div>
@livewire('admin.payments')
@endsection

View File

@ -0,0 +1,5 @@
<?php
return [
];

View File

@ -0,0 +1,32 @@
<?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('payments', function (Blueprint $table)
{
$table->id();
$table->string('paymentable_type');
$table->integer('paymentable_id');
$table->foreignId('complex_id')->references('id')->on('complexes')->onDelete('cascade');
$table->integer('value')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('payments');
}
};

View File

@ -0,0 +1,17 @@
<?php
namespace Modules\Payment\Http\Controllers;
use Modules\Payment\Models\Payment;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class PaymentController extends Controller
{
public function index()
{
return view('payment::index');
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Modules\Payment\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Payment extends Model
{
use HasFactory;
protected $fillable = [
'paymentable_type',
'paymentable_id',
'complex_id',
'value'
];
}

View File

@ -0,0 +1,68 @@
<?php
namespace Modules\Payment\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
use Livewire\Livewire;
class ModuleServiceProvider extends ServiceProvider
{
protected String $moduleName = 'Payment';
public function register()
{
$this->app->register(RouteServiceProvider::class);
}
public function boot()
{
$this->registerViews();
$this->registerLivewireViews();
$this->registerMigrations();
$this->registerConfig();
$this->registerComponent();
$this->registerLivewire();
}
protected function registerViews()
{
$moduleViewsPath = __DIR__.'/../Views';
$this->loadViewsFrom(
$moduleViewsPath, strtolower($this->moduleName)
);
}
protected function registerLivewireViews()
{
$moduleViewsPath = __DIR__.'/../Views/livewire';
$this->loadViewsFrom(
$moduleViewsPath, strtolower($this->moduleName)
);
}
protected function registerMigrations()
{
$this->loadMigrationsFrom(
app_path('Modules/'.$this->moduleName.'/Database/Migrations')
);
}
protected function registerConfig()
{
$path = app_path('Modules/'.$this->moduleName.'/Config/config.php');
$this->mergeConfigFrom(
$path, strtolower($this->moduleName)
);
}
protected function registerLivewire()
{
//Livewire::component('<name>', \Modules\<NAME>\Http\Livewire\<NAME>::class);
}
protected function registerComponent()
{
//Blade::component('<name>', \Modules\<NAME>\Http\Components\<NAME>::class);
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace Modules\Payment\Providers;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
public function map()
{
$this->registerWebRoutes();
}
protected function registerWebRoutes()
{
//Add Web Routes with web Guard
Route::middleware('web')
//Set Default Controllers Namespace
->namespace('Modules\\Payment\\Http\\Controllers')
->group(app_path('Modules/Payment/Routes/web.php'));
}
}

View File

@ -0,0 +1,13 @@
<?php
use Illuminate\Support\Facades\Route;
use Modules\Payment\Http\Controllers\PaymentController;
Route::middleware(['auth'])->group(function() {
Route::get('/payment', [PaymentController::class, 'index']);
Route::middleware(['hasAccess'])->group(function() {
/** Routes that need to be protected - Маршруты которые нужно защитить */
});
});

View File

@ -0,0 +1,98 @@
<?php
namespace Modules\Payment\Traits;
use Illuminate\Http\Request;
use Modules\Payment\Models\Payment;
use App\Models\Complex;
trait Paymentable
{
private $defaultValue = null; // -1 || null
protected static function boot()
{
parent::boot();
static::created(function ($item)
{
});
static::deleted(function ($item)
{
});
}
private function getClassName()
{
$reflect = new \ReflectionClass($this);
return $reflect->getShortName();
}
public function getPaymentable(Complex $complex)
{
$paymentable = Payment::where('paymentable_type', $this->getClassName())
->where('paymentable_id', $this->id)
->where('complex_id', $complex->id);
switch ( $paymentable->count() )
{
case 0:
return Payment::create([
'paymentable_type' => $this->getClassName(),
'paymentable_id' => $this->id,
'complex_id' => $complex->id,
'value' => ($this->getClassName() == 'Company') ? null : ($this->defaultValue == -1 ? $this->setAsParentPayment($complex) : null)
]);
break;
case 1:
return $paymentable->first();
break;
default:
abort(404);
}
return false;
}
public function setPayment(Complex $complex, $value)
{
$paymentable = $this->getPaymentable($complex);
if ($value >= 0 && $value <= 100)
{
$paymentable->update([
'value' => $value //-1 значит, что значение наследуется от родительского
]);
return true;
}
return false;
}
public function setAsParentPayment(Complex $complex)
{
$value = -1;
if ($this->getClassName() == 'Agent')
{
$company = $this->company;
$companyPayment = $company->getPaymentable($complex);
if ($companyPayment->value === null || $companyPayment->value == -1)
{
$value = null;
}
}
$paymentable = $this->getPaymentable($complex);
$paymentable->update([
'value' => $value //-1 значит, что значение наследуется от родительского
]);
return true;
}
public function unsetPayment(Complex $complex)
{
$paymentable = $this->getPaymentable($complex);
$paymentable->update([
'value' => null
]);
return true;
}
}

View File

@ -0,0 +1,4 @@
@extends('layouts.app')
@section('content')
<h1> Example views </h1>
@endsection

View File

@ -5,3 +5,6 @@ $body-bg: #f8fafc;
$font-family-sans-serif: 'Nunito', sans-serif;
$font-size-base: 0.9rem;
$line-height-base: 1.6;
//colors
$primary: #e6662a;