From abae7d79b77303d037fe9f4c688cd8090b0ea569 Mon Sep 17 00:00:00 2001 From: panabonic Date: Mon, 11 Sep 2023 01:03:31 +0300 Subject: [PATCH] applications permissions and notifications major update --- .../Applications/ApplicationExpertChanged.php | 26 +++++++ ...dApplicationExpertChangedNotifications.php | 29 ++++++++ .../NotifyApplicationExpertChanged.php | 29 ++++++++ app/Models/Applications/Application.php | 9 +++ app/Models/User.php | 1 + app/Providers/AppServiceProvider.php | 3 +- app/Providers/EventServiceProvider.php | 5 ++ .../Applications/ApplicationFilters.php | 6 +- .../Applications/ApplicationFormsServices.php | 3 +- .../Forms/Applications/ConclusionForms.php | 10 ++- .../Forms/Applications/ExpertForms.php | 69 +++++++++++++++++++ .../applications/expert-changed.blade.php | 18 +++++ .../applications/status-changed.blade.php | 4 +- 13 files changed, 204 insertions(+), 8 deletions(-) create mode 100644 app/Events/Applications/ApplicationExpertChanged.php create mode 100644 app/Listeners/Applications/SendApplicationExpertChangedNotifications.php create mode 100644 app/Mail/Applications/NotifyApplicationExpertChanged.php create mode 100644 app/Services/Forms/Applications/ExpertForms.php create mode 100644 resources/views/mail/applications/expert-changed.blade.php diff --git a/app/Events/Applications/ApplicationExpertChanged.php b/app/Events/Applications/ApplicationExpertChanged.php new file mode 100644 index 0000000..fcb1dc7 --- /dev/null +++ b/app/Events/Applications/ApplicationExpertChanged.php @@ -0,0 +1,26 @@ +application = $application; + $this->previousExpert = $previousExpert; + } + + public function broadcastOn(): PrivateChannel { + return new PrivateChannel('channel-name'); + } +} diff --git a/app/Listeners/Applications/SendApplicationExpertChangedNotifications.php b/app/Listeners/Applications/SendApplicationExpertChangedNotifications.php new file mode 100644 index 0000000..e7aa293 --- /dev/null +++ b/app/Listeners/Applications/SendApplicationExpertChangedNotifications.php @@ -0,0 +1,29 @@ +application->submitter) $this->notify($v, $event->application); + if ($v = $event->application->expert()->first()) $this->notify($v->user, $event->application); + if ($v = $event->previousExpert) $this->notify($v->user, $event->application); + } + + public function notify(User $recipient, Application $application) { + try { + Mail::to($recipient->email)->send(new NotifyApplicationExpertChanged($application, $recipient)); + } catch (\Exception $exception) {} + } + + +} diff --git a/app/Mail/Applications/NotifyApplicationExpertChanged.php b/app/Mail/Applications/NotifyApplicationExpertChanged.php new file mode 100644 index 0000000..bebe384 --- /dev/null +++ b/app/Mail/Applications/NotifyApplicationExpertChanged.php @@ -0,0 +1,29 @@ +application = $application; + $this->recipient = $recipient; + } + + public function build(): NotifyApplicationExpertChanged { + $expert = $this->application->expert()->first(); + $subject = "Назначен эксперт по заявке №{$this->application->number}"; + if ($this->recipient->id === ($expert->user->id ?? null)) $subject = "Вы назначены экспертом по заявке №{$this->application->number}"; + return $this->subject($subject)->view("mail.applications.expert-changed"); + } +} diff --git a/app/Models/Applications/Application.php b/app/Models/Applications/Application.php index 5b5fdba..db4c8a1 100644 --- a/app/Models/Applications/Application.php +++ b/app/Models/Applications/Application.php @@ -2,6 +2,7 @@ namespace App\Models\Applications; +use App\Events\Applications\ApplicationExpertChanged; use App\Events\Applications\ApplicationStatusChanged; use App\Models\Companies\CompanyMember; use App\Models\Objects\Field; @@ -95,6 +96,14 @@ class Application extends Model { if (!$this->number) $this->update(['number' => self::generateNumber()]); } + public function setExpert(CompanyMember $expert) { + if ($this->expert->id !== $expert->id) { + $previousExpert = $this->expert; + $this->update(['expert_id' => $expert->id]); + event(new ApplicationExpertChanged($this, $previousExpert)); + } + } + public static function generateNumber($start = 100, $digits = 5): string { $res = intval(static::query()->max('number') ?? $start) + 1; while (strlen($res) < $digits) { diff --git a/app/Models/User.php b/app/Models/User.php index 5451a20..e285c59 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -121,6 +121,7 @@ class User extends Authenticatable { 'super_admin' => $this->isSuperAdmin, 'admin' => $this->isAdmin, 'expert' => $this->isExpert, + 'applications_manager' => $this->isApplicationsManager, 'main_company_member' => $this->isMainCompanyMember ]; } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 3dd2dc4..fa6612d 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -53,8 +53,7 @@ class AppServiceProvider extends ServiceProvider */ public function boot() { Carbon::setLocale(config('app.locale')); - - if ($this->app->environment('local')) Mail::alwaysTo('test@nirgroup.ru'); + if ($v = env('MAIL_ALWAYS_TO')) Mail::alwaysTo($v); Relation::enforceMorphMap([ 'asset' => Asset::class, diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index cf65602..b1d82ad 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -2,10 +2,12 @@ namespace App\Providers; +use App\Events\Applications\ApplicationExpertChanged; use App\Events\Applications\ApplicationStatusChanged; use App\Events\FeedbackSender; use App\Events\PasswordRecovered; use App\Events\UserRegistered; +use App\Listeners\Applications\SendApplicationExpertChangedNotifications; use App\Listeners\Applications\SendApplicationStatusChangedNotifications; use App\Listeners\SendFeedbackMessage; use App\Listeners\SendPasswordRecoveredNotification; @@ -31,6 +33,9 @@ class EventServiceProvider extends ServiceProvider { ApplicationStatusChanged::class => [ SendApplicationStatusChangedNotifications::class + ], + ApplicationExpertChanged::class => [ + SendApplicationExpertChangedNotifications::class ] ]; diff --git a/app/Services/Filters/Applications/ApplicationFilters.php b/app/Services/Filters/Applications/ApplicationFilters.php index 69f8990..4a40bab 100644 --- a/app/Services/Filters/Applications/ApplicationFilters.php +++ b/app/Services/Filters/Applications/ApplicationFilters.php @@ -98,7 +98,11 @@ class ApplicationFilters extends FiltersService { public function applyPermissionsFilters(Builder $query) { $user = Auth::user(); - if (!$user->isExpert && !$user->isAdmin) $query->where(['submitter_id' => $user->id ?? null]); + if (!$user->isApplicationsManager && !$user->isAdmin) $query->where(function($query) use($user) { + $query->where(['submitter_id' => $user->id ?? null])->orWhereHas('expert', function($query) use($user) { + $query->where(['user_id' => $user->id ?? null]); + }); + }); } } diff --git a/app/Services/Forms/Applications/ApplicationFormsServices.php b/app/Services/Forms/Applications/ApplicationFormsServices.php index ea9e1be..4465f6f 100644 --- a/app/Services/Forms/Applications/ApplicationFormsServices.php +++ b/app/Services/Forms/Applications/ApplicationFormsServices.php @@ -5,6 +5,7 @@ namespace App\Services\Forms\Applications; class ApplicationFormsServices { public static array $services = [ 'application' => ApplicationForms::class, - 'applicationConclusion' => ConclusionForms::class + 'applicationConclusion' => ConclusionForms::class, + 'applicationExpert' => ExpertForms::class ]; } diff --git a/app/Services/Forms/Applications/ConclusionForms.php b/app/Services/Forms/Applications/ConclusionForms.php index 0e85c96..918b977 100644 --- a/app/Services/Forms/Applications/ConclusionForms.php +++ b/app/Services/Forms/Applications/ConclusionForms.php @@ -47,14 +47,18 @@ class ConclusionForms extends FormsService { public function store(array $data): ?JsonResponse { $application = Application::byUuid($data['application'] ?? null)->firstOrFail(); - $model = $application->conclusions()->create(['author_id' => Auth::user()->id, 'message' => $data['message'] ?? null]); - $application->complete(); + $user = Auth::user(); + if (($application->expert->user->id ?? null) === ($user->id ?? null)) { + $model = $application->conclusions()->create(['author_id' => $user->id ?? null , 'message' => $data['message'] ?? null]); + $application->complete(); + } return fractal($model, new ConclusionTransformer())->respond(); } public function update(string $id, array $data): ?JsonResponse { $model = Conclusion::byUuid($id)->firstOrFail(); - $model->update(['message' => $data['message'] ?? null]); + $user = Auth::user(); + if (($model->application->expert->user->id ?? null) === ($user->id ?? null)) $model->update(['message' => $data['message'] ?? null]); return fractal($model, new ConclusionTransformer())->respond(); } diff --git a/app/Services/Forms/Applications/ExpertForms.php b/app/Services/Forms/Applications/ExpertForms.php new file mode 100644 index 0000000..4f2a16a --- /dev/null +++ b/app/Services/Forms/Applications/ExpertForms.php @@ -0,0 +1,69 @@ + 'Назначение эксперта', 'update' => 'Назначение эксперта']; + + public function form(?string $id = null, array $data = []): array { + $model = Application::byUuid($id)->first(); + return [ + 'title' => $this->formTitle($model), + 'frames' => [ + ['title' => 'Общие сведения', 'groups' => $this->form1Groups($model)] + ] + ]; + } + + public function form1Groups(?Application $model): array { + $groups = [ + ['name' => 'common', 'title' => '', 'fields' => $this->commonGroupFields($model)] + ]; + return ['data' => $groups]; + } + + public function commonGroupFields(?Application $model): array { + $fields = [ + [ + 'name' => 'expert', + 'title' => 'Эксперт', + 'type' => FieldType::RELATION, + 'required' => true, + 'options' => $this->getExperts(), + 'value' => ($v = $model->expert ?? null) ? fractal($v, new CompanyMemberTransformer()) : null + ] + ]; + return ['data' => $fields]; + } + + + public function getExperts(): Fractal { + return fractal(CompanyMember::query()->mainCompany()->whereHas('objects', function($query) { + Field::applyFilters($query, collect(['types' => 'company-member-properties', 'moderate-permissions' => 'applications'])); + })->get(), new CompanyMemberTransformer()); + } + + + public function store(array $data) { + } + + public function update(string $id, array $data): ?JsonResponse { + $model = Application::byUuid($id)->firstOrFail(); + if ($expert = CompanyMember::byUuid($data['expert'] ?? null)->first()) $model->setExpert($expert); + return fractal($model, new ApplicationTransformer())->respond(); + } +} diff --git a/resources/views/mail/applications/expert-changed.blade.php b/resources/views/mail/applications/expert-changed.blade.php new file mode 100644 index 0000000..47770b1 --- /dev/null +++ b/resources/views/mail/applications/expert-changed.blade.php @@ -0,0 +1,18 @@ +@extends('mail.layouts.layout') + +@php + $expert = $application->expert()->first(); +@endphp + +@section('content') + @if(($expert->user->id ?? null) === ($recipient->id ?? null)) +

Вы назначены экспертом по заявке №{{$application->number}} от {{$application->created_at->format('d.m.Y')}}

+

Заявитель: {{$application->applicant ?? 'не указано'}}

+

Наименование продукции: {{$application->product->name ?? 'не указано'}}

+

Назначение продукции: {{$application->product->purpose ?? 'не указано'}}

+ @else +

Назначен эксперт по заявке №{{$application->number}} от {{$application->created_at->format('d.m.Y')}}

+

Эксперт: {{$application->expert->user->name ?? ''}}. {{$application->expert->position ?? ''}}

+ @endif +

Перейти к журналу заявок

+@endsection \ No newline at end of file diff --git a/resources/views/mail/applications/status-changed.blade.php b/resources/views/mail/applications/status-changed.blade.php index d7597f6..8250e8d 100644 --- a/resources/views/mail/applications/status-changed.blade.php +++ b/resources/views/mail/applications/status-changed.blade.php @@ -9,6 +9,8 @@ @elseif($status === \App\Models\Applications\ApplicationStatus::COMPLETED)

{{$application->title}} выполнена.

Эксперт: {{$application->conclusion->author->name ?? 'не указан'}}

-

Мнение эксперта: {{$application->conclusion->message ?? 'не указано'}}

+

Мнение эксперта:

+ {!! $application->conclusion->message ?? 'не указано' !!} @endif +

Перейти к журналу заявок

@endsection \ No newline at end of file