wip
This commit is contained in:
		| @@ -9,13 +9,13 @@ use Illuminate\Notifications\ChannelManager; | ||||
| use Illuminate\Support\Carbon; | ||||
| use Illuminate\Support\Facades\Notification; | ||||
| use Illuminate\Support\ServiceProvider; | ||||
| use Toby\Domain\Slack\Channels\SlackApiChannel; | ||||
| use Toby\Domain\Slack\SlackApiChannel; | ||||
|  | ||||
| class AppServiceProvider extends ServiceProvider | ||||
| { | ||||
|     public function register() | ||||
|     public function register(): void | ||||
|     { | ||||
|         Notification::resolved(function (ChannelManager $service) { | ||||
|         Notification::resolved(function (ChannelManager $service): void { | ||||
|             $service->extend("slack", fn(Application $app) => $app->make(SlackApiChannel::class)); | ||||
|         }); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										45
									
								
								app/Domain/DailySummaryRetriever.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Domain/DailySummaryRetriever.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain; | ||||
|  | ||||
| use Illuminate\Support\Carbon; | ||||
| use Illuminate\Support\Collection; | ||||
| use Toby\Domain\Enums\VacationType; | ||||
| use Toby\Eloquent\Models\User; | ||||
| use Toby\Eloquent\Models\Vacation; | ||||
|  | ||||
| class DailySummaryRetriever | ||||
| { | ||||
|     public function __construct( | ||||
|         protected VacationTypeConfigRetriever $configRetriever, | ||||
|     ) {} | ||||
|  | ||||
|     public function getAbsences(Carbon $date): Collection | ||||
|     { | ||||
|         return Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $date) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $this->configRetriever->isVacation($type))) | ||||
|             ->get(); | ||||
|     } | ||||
|  | ||||
|     public function getRemoteDays(Carbon $date): Collection | ||||
|     { | ||||
|         return Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $date) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$this->configRetriever->isVacation($type))) | ||||
|             ->get(); | ||||
|     } | ||||
|  | ||||
|     public function getBirthdays(Carbon $date): Collection | ||||
|     { | ||||
|         return User::query() | ||||
|             ->whereRelation("profile", "birthday", $date) | ||||
|             ->get(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										42
									
								
								app/Domain/Notifications/KeyHasBeenGivenNotification.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/Domain/Notifications/KeyHasBeenGivenNotification.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Notifications; | ||||
|  | ||||
| use Illuminate\Bus\Queueable; | ||||
| use Illuminate\Notifications\Notification; | ||||
| use Toby\Eloquent\Models\User; | ||||
|  | ||||
| class KeyHasBeenGivenNotification extends Notification | ||||
| { | ||||
|     use Queueable; | ||||
|  | ||||
|     public function __construct( | ||||
|         protected User $sender, | ||||
|         protected User $recipient, | ||||
|     ) {} | ||||
|  | ||||
|     public function via(): array | ||||
|     { | ||||
|         return ["slack"]; | ||||
|     } | ||||
|  | ||||
|     public function toSlack($notifiable): string | ||||
|     { | ||||
|         return __(":sender gives key no :key to :recipient", [ | ||||
|             "sender" => $this->getName($this->sender), | ||||
|             "recipient" => $this->getName($this->recipient), | ||||
|             "key" => $notifiable->id, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     protected function getName(User $user): string | ||||
|     { | ||||
|         if ($user->profile->slack_id !== null) { | ||||
|             return "<@{$user->profile->slack_id}>"; | ||||
|         } | ||||
|  | ||||
|         return $user->profile->full_name; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										42
									
								
								app/Domain/Notifications/KeyHasBeenTakenNotification.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/Domain/Notifications/KeyHasBeenTakenNotification.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Notifications; | ||||
|  | ||||
| use Illuminate\Bus\Queueable; | ||||
| use Illuminate\Notifications\Notification; | ||||
| use Toby\Eloquent\Models\User; | ||||
|  | ||||
| class KeyHasBeenTakenNotification extends Notification | ||||
| { | ||||
|     use Queueable; | ||||
|  | ||||
|     public function __construct( | ||||
|         protected User $recipient, | ||||
|         protected User $sender, | ||||
|     ) {} | ||||
|  | ||||
|     public function via(): array | ||||
|     { | ||||
|         return ["slack"]; | ||||
|     } | ||||
|  | ||||
|     public function toSlack($notifiable): string | ||||
|     { | ||||
|         return __(":recipient takes key no :key from :sender", [ | ||||
|             "recipient" => $this->getName($this->recipient), | ||||
|             "sender" => $this->getName($this->sender), | ||||
|             "key" => $notifiable->id, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     protected function getName(User $user): string | ||||
|     { | ||||
|         if ($user->profile->slack_id !== null) { | ||||
|             return "<@{$user->profile->slack_id}>"; | ||||
|         } | ||||
|  | ||||
|         return $user->profile->full_name; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										55
									
								
								app/Domain/Slack/Controller.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								app/Domain/Slack/Controller.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack; | ||||
|  | ||||
| use Exception; | ||||
| use Illuminate\Http\Request as IlluminateRequest; | ||||
| use Illuminate\Http\Response as IlluminateResponse; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Controller as SlackController; | ||||
| use Spatie\SlashCommand\Exceptions\RequestCouldNotBeHandled; | ||||
| use Spatie\SlashCommand\Exceptions\SlackSlashCommandException; | ||||
| use Spatie\SlashCommand\Response; | ||||
|  | ||||
| class Controller extends SlackController | ||||
| { | ||||
|     /** | ||||
|      * @throws RequestCouldNotBeHandled | ||||
|      */ | ||||
|     public function getResponse(IlluminateRequest $request): IlluminateResponse | ||||
|     { | ||||
|         $this->guardAgainstInvalidRequest($request); | ||||
|  | ||||
|         $handler = $this->determineHandler(); | ||||
|  | ||||
|         try { | ||||
|             $response = $handler->handle($this->request); | ||||
|         } catch (SlackSlashCommandException $exception) { | ||||
|             $response = $exception->getResponse($this->request); | ||||
|         } catch (ValidationException $exception) { | ||||
|             $response = $this->prepareValidationResponse($exception); | ||||
|         } catch (Exception $exception) { | ||||
|             $response = $this->convertToResponse($exception); | ||||
|         } | ||||
|  | ||||
|         return $response->getIlluminateResponse(); | ||||
|     } | ||||
|  | ||||
|     protected function prepareValidationResponse(ValidationException $exception): Response | ||||
|     { | ||||
|         $errors = (new Collection($exception->errors())) | ||||
|             ->map( | ||||
|                 fn(array $message) => Attachment::create() | ||||
|                     ->setColor("danger") | ||||
|                     ->setText($message[0]), | ||||
|             ); | ||||
|  | ||||
|         return Response::create($this->request) | ||||
|             ->withText(":x: Komenda `/{$this->request->command} {$this->request->text}` jest niepoprawna:") | ||||
|             ->withAttachments($errors->all()); | ||||
|     } | ||||
| } | ||||
| @@ -4,48 +4,32 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\AttachmentField; | ||||
| use Spatie\SlashCommand\Handlers\CatchAll as BaseCatchAllHandler; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Spatie\SlashCommand\Handlers\BaseHandler; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\Slack\Traits\ListsHandlers; | ||||
|  | ||||
| class CatchAll extends BaseCatchAllHandler | ||||
| class CatchAll extends BaseHandler | ||||
| { | ||||
|     use ListsHandlers; | ||||
|  | ||||
|     public function canHandle(Request $request): bool | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $response = $this->respondToSlack("Nie rozpoznaję tej komendy: `/{$request->command} {$request->text}`"); | ||||
|         $handlers = $this->findAvailableHandlers(); | ||||
|         $attachmentFields = $this->mapHandlersToAttachments($handlers); | ||||
|  | ||||
|         [$command] = explode(' ', $this->request->text ?? ""); | ||||
|  | ||||
|         $alternativeHandlers = $this->findAlternativeHandlers($command); | ||||
|  | ||||
|         if ($alternativeHandlers->count()) { | ||||
|             $response->withAttachment($this->getCommandListAttachment($alternativeHandlers)); | ||||
|         } | ||||
|  | ||||
|         if ($this->containsHelpHandler($alternativeHandlers)) { | ||||
|             $response->withAttachment(Attachment::create() | ||||
|                 ->setText("Aby wyświetlić wszystkie komendy, napisz: `/toby pomoc`") | ||||
|         return $this->respondToSlack(":x: Nie rozpoznaję tej komendy. Lista wszystkich komend:") | ||||
|             ->withAttachment( | ||||
|                 Attachment::create() | ||||
|                     ->setColor("danger") | ||||
|                     ->useMarkdown() | ||||
|                     ->setFields($attachmentFields), | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return $response; | ||||
|     } | ||||
|  | ||||
|     protected function getCommandListAttachment(Collection $handlers): Attachment | ||||
|     { | ||||
|         $attachmentFields = $handlers | ||||
|             ->map(function (SignatureHandler $handler) { | ||||
|                 return AttachmentField::create($handler->getFullCommand(), $handler->getDescription()); | ||||
|             }) | ||||
|             ->all(); | ||||
|  | ||||
|         return Attachment::create() | ||||
|             ->setColor('warning') | ||||
|             ->setTitle('Czy miałeś na myśli:') | ||||
|             ->setFields($attachmentFields); | ||||
|     } | ||||
| } | ||||
| @@ -5,70 +5,52 @@ declare(strict_types=1); | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Carbon; | ||||
| use Illuminate\Support\Collection; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Toby\Domain\Enums\VacationType; | ||||
| use Toby\Domain\VacationTypeConfigRetriever; | ||||
| use Toby\Domain\DailySummaryRetriever; | ||||
| use Toby\Domain\Slack\SignatureHandler; | ||||
| use Toby\Eloquent\Models\User; | ||||
| use Toby\Eloquent\Models\Vacation; | ||||
|  | ||||
| class DailySummary extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby dzisiaj"; | ||||
|  | ||||
|     protected $description = "Podsumowanie"; | ||||
|     protected $description = "Codzienne podsumowanie"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $configRetriever = app(VacationTypeConfigRetriever::class); | ||||
|         $dailySummaryRetriever = app()->make(DailySummaryRetriever::class); | ||||
|  | ||||
|         $now = Carbon::today(); | ||||
|  | ||||
|         /** @var Collection $absences */ | ||||
|         $absences = Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $now) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type))) | ||||
|             ->get() | ||||
|         $absences = $dailySummaryRetriever->getAbsences($now) | ||||
|             ->map(fn(Vacation $vacation) => $vacation->user->profile->full_name); | ||||
|  | ||||
|         /** @var Collection $remoteDays */ | ||||
|         $remoteDays = Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $now) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type))) | ||||
|             ->get() | ||||
|         $remoteDays = $dailySummaryRetriever->getRemoteDays($now) | ||||
|             ->map(fn(Vacation $vacation) => $vacation->user->profile->full_name); | ||||
|  | ||||
|         $birthdays = User::query() | ||||
|             ->whereRelation("profile", "birthday", $now) | ||||
|             ->get() | ||||
|         $birthdays = $dailySummaryRetriever->getBirthdays($now) | ||||
|             ->map(fn(User $user) => $user->profile->full_name); | ||||
|  | ||||
|         $absencesAttachment = Attachment::create() | ||||
|             ->setTitle("Nieobecności :palm_tree:") | ||||
|             ->setColor('#eab308') | ||||
|             ->setColor("#eab308") | ||||
|             ->setText($absences->isNotEmpty() ? $absences->implode("\n") : "Wszyscy dzisiaj pracują :muscle:"); | ||||
|  | ||||
|         $remoteAttachment = Attachment::create() | ||||
|             ->setTitle("Praca zdalna :house_with_garden:") | ||||
|             ->setColor('#d946ef') | ||||
|             ->setColor("#d946ef") | ||||
|             ->setText($remoteDays->isNotEmpty() ? $remoteDays->implode("\n") : "Wszyscy dzisiaj są w biurze :boom:"); | ||||
|  | ||||
|         $birthdayAttachment = Attachment::create() | ||||
|             ->setTitle("Urodziny :birthday:") | ||||
|             ->setColor('#3C5F97') | ||||
|             ->setColor("#3C5F97") | ||||
|             ->setText($birthdays->isNotEmpty() ? $birthdays->implode("\n") : "Dzisiaj nikt nie ma urodzin :cry:"); | ||||
|  | ||||
|         return $this->respondToSlack("Podsumowanie dla dnia {$now->toDisplayString()}") | ||||
|             ->withAttachment($absencesAttachment) | ||||
|             ->withAttachment($remoteAttachment) | ||||
|             ->withAttachment($birthdayAttachment) | ||||
|             ->displayResponseToEveryoneOnChannel(); | ||||
|             ->withAttachment($birthdayAttachment); | ||||
|     } | ||||
| } | ||||
| @@ -4,46 +4,69 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Str; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Toby\Domain\Notifications\KeyHasBeenGivenNotification; | ||||
| use Toby\Domain\Slack\SignatureHandler; | ||||
| use Toby\Domain\Slack\SlackUserExistsRule; | ||||
| use Toby\Domain\Slack\Traits\FindsUserBySlackId; | ||||
| use Toby\Domain\Slack\UserNotFoundException; | ||||
| use Toby\Eloquent\Models\Key; | ||||
| use Toby\Eloquent\Models\User; | ||||
|  | ||||
| class GiveKeysTo extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby klucze:dla {użytkownik}"; | ||||
|     use FindsUserBySlackId; | ||||
|  | ||||
|     protected $description = "Daj klucze wskazanemu użytkownikowi"; | ||||
|     protected $signature = "toby klucze:dla {user}"; | ||||
|     protected $description = "Przekaż klucze wskazanemu użytkownikowi"; | ||||
|  | ||||
|     /** | ||||
|      * @throws UserNotFoundException | ||||
|      * @throws ValidationException | ||||
|      */ | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $to = $this->getArgument('użytkownik'); | ||||
|         ["user" => $from] = $this->validate(); | ||||
|  | ||||
|         $id = Str::between($to, "@", "|"); | ||||
|  | ||||
|         $authUser = $this->findUserBySlackId($request->userId); | ||||
|         $user = $this->findUserBySlackId($id); | ||||
|         $authUser = $this->findUserBySlackIdOrFail($request->userId); | ||||
|         $user = $this->findUserBySlackId($from); | ||||
|  | ||||
|         /** @var Key $key */ | ||||
|         $key = $authUser->keys()->first(); | ||||
|  | ||||
|         if (!$key) { | ||||
|             throw ValidationException::withMessages(["key" => "Nie masz żadnego klucza do przekazania"]); | ||||
|         } | ||||
|  | ||||
|         if ($user->is($authUser)) { | ||||
|             throw ValidationException::withMessages([ | ||||
|                 "key" => "Nie możesz przekazać sobie kluczy :dzban:", | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $key->user()->associate($user); | ||||
|  | ||||
|         $key->save(); | ||||
|  | ||||
|         return $this->respondToSlack("<@{$authUser->profile->slack_id}> daje klucz nr {$key->id} użytkownikowi <@{$user->profile->slack_id}>") | ||||
|             ->displayResponseToEveryoneOnChannel(); | ||||
|         $key->notify(new KeyHasBeenGivenNotification($authUser, $user)); | ||||
|  | ||||
|         return $this->respondToSlack( | ||||
|             ":white_check_mark: Klucz nr {$key->id} został przekazany użytkownikowi <@{$user->profile->slack_id}>", | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     protected function findUserBySlackId(string $slackId): User | ||||
|     protected function getRules(): array | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user = User::query() | ||||
|             ->whereRelation("profile", "slack_id", $slackId) | ||||
|             ->first(); | ||||
|         return [ | ||||
|             "user" => ["required", new SlackUserExistsRule()], | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|         return $user; | ||||
|     protected function getMessages(): array | ||||
|     { | ||||
|         return [ | ||||
|             "user.required" => "Musisz podać użytkownika, któremu chcesz przekazać klucze", | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
| @@ -4,42 +4,31 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\AttachmentField; | ||||
| use Spatie\SlashCommand\Handlers\Help as BaseHelpHandler; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Toby\Domain\Slack\SignatureHandler; | ||||
| use Toby\Domain\Slack\Traits\ListsHandlers; | ||||
|  | ||||
| class Help extends BaseHelpHandler | ||||
| class Help extends SignatureHandler | ||||
| { | ||||
|     use ListsHandlers; | ||||
|  | ||||
|     protected $signature = "toby pomoc"; | ||||
|     protected $description = "Wyświetl wszystkie dostępne komendy tobiego"; | ||||
|     protected $description = "Wyświetl wszystkie dostępne komendy"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $handlers = $this->findAvailableHandlers(); | ||||
|  | ||||
|         return $this->displayListOfAllCommands($handlers); | ||||
|     } | ||||
|         $attachmentFields = $this->mapHandlersToAttachments($handlers); | ||||
|  | ||||
|     protected function displayListOfAllCommands(Collection $handlers): Response | ||||
|     { | ||||
|         $attachmentFields = $handlers | ||||
|             ->sort(function (SignatureHandler $handlerA, SignatureHandler $handlerB) { | ||||
|                 return strcmp($handlerA->getFullCommand(), $handlerB->getFullCommand()); | ||||
|             }) | ||||
|             ->map(function (SignatureHandler $handler) { | ||||
|                 return AttachmentField::create("/{$handler->getSignature()}", $handler->getDescription()); | ||||
|             }) | ||||
|             ->all(); | ||||
|  | ||||
|         return $this->respondToSlack('Dostępne komendy') | ||||
|         return $this->respondToSlack("Dostępne komendy:") | ||||
|             ->withAttachment( | ||||
|                 Attachment::create() | ||||
|                     ->setColor('good') | ||||
|                     ->setFields($attachmentFields) | ||||
|                     ->setColor("good") | ||||
|                     ->useMarkdown() | ||||
|                     ->setFields($attachmentFields), | ||||
|             ); | ||||
|     } | ||||
| } | ||||
| @@ -7,22 +7,31 @@ namespace Toby\Domain\Slack\Handlers; | ||||
| use Illuminate\Support\Carbon; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Toby\Domain\Actions\VacationRequest\CreateAction; | ||||
| use Toby\Domain\Enums\VacationType; | ||||
| use Toby\Domain\Slack\SignatureHandler; | ||||
| use Toby\Domain\Slack\Traits\FindsUserBySlackId; | ||||
| use Toby\Eloquent\Models\User; | ||||
| use Toby\Eloquent\Models\YearPeriod; | ||||
|  | ||||
| class HomeOffice extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby zdalnie {kiedy?}"; | ||||
|     protected $description = "Pracuj zdalnie wybranego dnia (domyślnie dzisiaj)"; | ||||
|     use FindsUserBySlackId; | ||||
|  | ||||
|     protected $signature = "toby zdalnie"; | ||||
|     protected $description = "Pracuj dzisiaj zdalnie"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $date = $this->getDateFromArgument($this->getArgument('kiedy') ?? "dzisiaj"); | ||||
|         $user = $this->findUserBySlackId($request->userId); | ||||
|  | ||||
|         $this->createRemoteday($user, Carbon::today()); | ||||
|  | ||||
|         return $this->respondToSlack(":white_check_mark: Pracujesz dzisiaj zdalnie"); | ||||
|     } | ||||
|  | ||||
|     protected function createRemoteday(User $user, Carbon $date): void | ||||
|     { | ||||
|         $yearPeriod = YearPeriod::findByYear($date->year); | ||||
|  | ||||
|         app(CreateAction::class)->execute([ | ||||
| @@ -33,27 +42,5 @@ class HomeOffice extends SignatureHandler | ||||
|             "year_period_id" => $yearPeriod->id, | ||||
|             "flow_skipped" => false, | ||||
|         ], $user); | ||||
|  | ||||
|         return $this->respondToSlack("Praca zdalna dnia {$date->toDisplayString()} została utworzona pomyślnie.") | ||||
|             ->displayResponseToEveryoneOnChannel(); | ||||
|     } | ||||
|  | ||||
|     protected function getDateFromArgument(string $argument): Carbon | ||||
|     { | ||||
|         return match ($argument) { | ||||
|             "dzisiaj" => Carbon::today(), | ||||
|             "jutro" => Carbon::tomorrow(), | ||||
|             default => Carbon::create($argument), | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     protected function findUserBySlackId(string $slackId): User | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user = User::query() | ||||
|             ->whereRelation("profile", "slack_id", $slackId) | ||||
|             ->first(); | ||||
|  | ||||
|         return $user; | ||||
|     } | ||||
| } | ||||
| @@ -7,13 +7,12 @@ namespace Toby\Domain\Slack\Handlers; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Toby\Domain\Slack\SignatureHandler; | ||||
| use Toby\Eloquent\Models\Key; | ||||
|  | ||||
| class KeyList extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby klucze"; | ||||
|  | ||||
|     protected $description = "Lista wszystkich kluczy"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
| @@ -23,11 +22,11 @@ class KeyList extends SignatureHandler | ||||
|             ->get() | ||||
|             ->map(fn(Key $key) => "Klucz nr {$key->id} - <@{$key->user->profile->slack_id}>"); | ||||
|  | ||||
|         return $this->respondToSlack("Lista kluczy") | ||||
|         return $this->respondToSlack("Lista kluczy :key:") | ||||
|             ->withAttachment( | ||||
|                 Attachment::create() | ||||
|                     ->setColor('#3C5F97') | ||||
|                     ->setText($keys->implode("\n")) | ||||
|                     ->setColor("#3C5F97") | ||||
|                     ->setText($keys->isNotEmpty() ? $keys->implode("\n") : "Nie ma żadnych kluczy w tobym"), | ||||
|             ); | ||||
|     } | ||||
| } | ||||
| @@ -1,24 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
|  | ||||
| class SaySomething extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby powiedz {zdanie}"; | ||||
|  | ||||
|     protected $description = "Powiedz zdanie"; | ||||
|  | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $sentence = $this->getArgument("zdanie"); | ||||
|  | ||||
|         return $this->respondToSlack($sentence) | ||||
|             ->displayResponseToEveryoneOnChannel(); | ||||
|     } | ||||
| } | ||||
| @@ -4,46 +4,68 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Handlers; | ||||
|  | ||||
| use Illuminate\Support\Str; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Spatie\SlashCommand\Request; | ||||
| use Spatie\SlashCommand\Response; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Toby\Domain\Notifications\KeyHasBeenTakenNotification; | ||||
| use Toby\Domain\Slack\SignatureHandler; | ||||
| use Toby\Domain\Slack\SlackUserExistsRule; | ||||
| use Toby\Domain\Slack\Traits\FindsUserBySlackId; | ||||
| use Toby\Domain\Slack\UserNotFoundException; | ||||
| use Toby\Eloquent\Models\Key; | ||||
| use Toby\Eloquent\Models\User; | ||||
|  | ||||
| class TakeKeysFrom extends SignatureHandler | ||||
| { | ||||
|     protected $signature = "toby klucze:od {użytkownik}"; | ||||
|     use FindsUserBySlackId; | ||||
|  | ||||
|     protected $signature = "toby klucze:od {user}"; | ||||
|     protected $description = "Zabierz klucze wskazanemu użytkownikowi"; | ||||
|  | ||||
|     /** | ||||
|      * @throws UserNotFoundException|ValidationException | ||||
|      */ | ||||
|     public function handle(Request $request): Response | ||||
|     { | ||||
|         $from = $this->getArgument("użytkownik"); | ||||
|         ["user" => $from] = $this->validate(); | ||||
|  | ||||
|         $id = Str::between($from, "@", "|"); | ||||
|  | ||||
|         $authUser = $this->findUserBySlackId($request->userId); | ||||
|         $user = $this->findUserBySlackId($id); | ||||
|         $authUser = $this->findUserBySlackIdOrFail($request->userId); | ||||
|         $user = $this->findUserBySlackId($from); | ||||
|  | ||||
|         /** @var Key $key */ | ||||
|         $key = $user->keys()->first(); | ||||
|  | ||||
|         if (!$key) { | ||||
|             throw ValidationException::withMessages([ | ||||
|                 "key" => "Użytkownik <@{$user->profile->slack_id}> nie ma żadnych kluczy", | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         if ($key->user()->is($authUser)) { | ||||
|             throw ValidationException::withMessages([ | ||||
|                 "key" => "Nie możesz zabrać sobie kluczy :dzban:", | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $key->user()->associate($authUser); | ||||
|  | ||||
|         $key->save(); | ||||
|  | ||||
|         return $this->respondToSlack("<@{$authUser->profile->slack_id}> zabiera klucz nr {$key->id} użytkownikowi <@{$user->profile->slack_id}>") | ||||
|             ->displayResponseToEveryoneOnChannel(); | ||||
|         $key->notify(new KeyHasBeenTakenNotification($authUser, $user)); | ||||
|  | ||||
|         return $this->respondToSlack(":white_check_mark: Klucz nr {$key->id} został zabrany użytkownikowi <@{$user->profile->slack_id}>"); | ||||
|     } | ||||
|  | ||||
|     protected function findUserBySlackId(string $slackId): User | ||||
|     protected function getRules(): array | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user = User::query() | ||||
|             ->whereRelation("profile", "slack_id", $slackId) | ||||
|             ->first(); | ||||
|         return [ | ||||
|             "user" => ["required", new SlackUserExistsRule()], | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|         return $user; | ||||
|     protected function getMessages(): array | ||||
|     { | ||||
|         return [ | ||||
|             "user.required" => "Musisz podać użytkownika, któremu chcesz zabrać klucze", | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								app/Domain/Slack/SignatureHandler.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Domain/Slack/SignatureHandler.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack; | ||||
|  | ||||
| use Illuminate\Support\Facades\Validator; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler as BaseSignatureHandler; | ||||
|  | ||||
| abstract class SignatureHandler extends BaseSignatureHandler | ||||
| { | ||||
|     public function validate() | ||||
|     { | ||||
|         return Validator::validate($this->getArguments(), $this->getRules(), $this->getMessages()); | ||||
|     } | ||||
|  | ||||
|     protected function getRules(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     protected function getMessages(): array | ||||
|     { | ||||
|         return []; | ||||
|     } | ||||
| } | ||||
| @@ -2,7 +2,7 @@ | ||||
| 
 | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace Toby\Domain\Slack\Channels; | ||||
| namespace Toby\Domain\Slack; | ||||
| 
 | ||||
| use Illuminate\Http\Client\Response; | ||||
| use Illuminate\Notifications\Notification; | ||||
| @@ -14,12 +14,12 @@ class SlackApiChannel | ||||
|     { | ||||
|         $baseUrl = config("services.slack.url"); | ||||
|         $url = "{$baseUrl}/chat.postMessage"; | ||||
|         $channel = $notifiable->routeNotificationFor('slack', $notification); | ||||
|         $channel = $notifiable->routeNotificationFor("slack", $notification); | ||||
| 
 | ||||
|         return Http::withToken(config("services.slack.client_token")) | ||||
|             ->post($url, [ | ||||
|                 "channel" => $channel, | ||||
|                 "text" => $notification->toSlack(), | ||||
|                 "text" => $notification->toSlack($notifiable), | ||||
|             ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										24
									
								
								app/Domain/Slack/SlackUserExistsRule.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Domain/Slack/SlackUserExistsRule.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack; | ||||
|  | ||||
| use Illuminate\Contracts\Validation\Rule; | ||||
| use Illuminate\Support\Str; | ||||
| use Toby\Eloquent\Models\Profile; | ||||
|  | ||||
| class SlackUserExistsRule implements Rule | ||||
| { | ||||
|     public function passes($attribute, $value): bool | ||||
|     { | ||||
|         $slackId = Str::between($value, "<@", "|"); | ||||
|  | ||||
|         return Profile::query()->where("slack_id", $slackId)->exists(); | ||||
|     } | ||||
|  | ||||
|     public function message(): string | ||||
|     { | ||||
|         return "Użytkownik :input nie istnieje w tobym"; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										43
									
								
								app/Domain/Slack/Traits/FindsUserBySlackId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/Domain/Slack/Traits/FindsUserBySlackId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Traits; | ||||
|  | ||||
| use Illuminate\Support\Str; | ||||
| use Toby\Domain\Slack\UserNotFoundException; | ||||
| use Toby\Eloquent\Models\User; | ||||
|  | ||||
| trait FindsUserBySlackId | ||||
| { | ||||
|     protected function findUserBySlackId(string $slackId): ?User | ||||
|     { | ||||
|         $id = $this->prepareSlackIdFromString($slackId); | ||||
|  | ||||
|         /** @var User $user */ | ||||
|         $user = User::query() | ||||
|             ->whereRelation("profile", "slack_id", $id) | ||||
|             ->first(); | ||||
|  | ||||
|         return $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @throws UserNotFoundException | ||||
|      */ | ||||
|     protected function findUserBySlackIdOrFail(string $slackId): ?User | ||||
|     { | ||||
|         $user = $this->findUserBySlackId($slackId); | ||||
|  | ||||
|         if (!$user) { | ||||
|             throw new UserNotFoundException("Użytkownik {$slackId} nie istnieje w tobym"); | ||||
|         } | ||||
|  | ||||
|         return $user; | ||||
|     } | ||||
|  | ||||
|     protected function prepareSlackIdFromString(string $slackId): string | ||||
|     { | ||||
|         return Str::between($slackId, "<@", "|"); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								app/Domain/Slack/Traits/ListsHandlers.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Domain/Slack/Traits/ListsHandlers.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack\Traits; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Str; | ||||
| use Spatie\SlashCommand\AttachmentField; | ||||
| use Spatie\SlashCommand\Handlers\SignatureHandler; | ||||
| use Spatie\SlashCommand\Handlers\SignatureParts; | ||||
| use Spatie\SlashCommand\HandlesSlashCommand; | ||||
|  | ||||
| trait ListsHandlers | ||||
| { | ||||
|     protected function findAvailableHandlers(): Collection | ||||
|     { | ||||
|         return collect(config("laravel-slack-slash-command.handlers")) | ||||
|             ->map(fn(string $handlerClassName) => new $handlerClassName($this->request)) | ||||
|             ->filter(fn(HandlesSlashCommand $handler) => $handler instanceof SignatureHandler) | ||||
|             ->filter(function (SignatureHandler $handler) { | ||||
|                 $signatureParts = new SignatureParts($handler->getSignature()); | ||||
|  | ||||
|                 return Str::is($signatureParts->getSlashCommandName(), $this->request->command); | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     protected function mapHandlersToAttachments(Collection $handlers): array | ||||
|     { | ||||
|         return $handlers | ||||
|             ->sort( | ||||
|                 fn(SignatureHandler $handlerA, SignatureHandler $handlerB) => strcmp( | ||||
|                     $handlerA->getFullCommand(), | ||||
|                     $handlerB->getFullCommand(), | ||||
|                 ), | ||||
|             ) | ||||
|             ->map( | ||||
|                 fn(SignatureHandler $handler) => AttachmentField::create( | ||||
|                     $handler->getDescription(), | ||||
|                     "`/{$handler->getSignature()}`", | ||||
|                 ), | ||||
|             ) | ||||
|             ->all(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								app/Domain/Slack/UserNotFoundException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/Domain/Slack/UserNotFoundException.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Toby\Domain\Slack; | ||||
|  | ||||
| use Spatie\SlashCommand\Exceptions\SlackSlashCommandException; | ||||
|  | ||||
| class UserNotFoundException extends SlackSlashCommandException | ||||
| { | ||||
| } | ||||
| @@ -8,6 +8,7 @@ use Database\Factories\KeyFactory; | ||||
| use Illuminate\Database\Eloquent\Factories\HasFactory; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | ||||
| use Illuminate\Notifications\Notifiable; | ||||
|  | ||||
| /** | ||||
|  * @property int $id | ||||
| @@ -16,6 +17,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; | ||||
| class Key extends Model | ||||
| { | ||||
|     use HasFactory; | ||||
|     use Notifiable; | ||||
|  | ||||
|     protected $guarded = []; | ||||
|  | ||||
| @@ -24,6 +26,11 @@ class Key extends Model | ||||
|         return $this->belongsTo(User::class); | ||||
|     } | ||||
|  | ||||
|     public function routeNotificationForSlack(): string | ||||
|     { | ||||
|         return config("services.slack.default_channel"); | ||||
|     } | ||||
|  | ||||
|     protected static function newFactory(): KeyFactory | ||||
|     { | ||||
|         return KeyFactory::new(); | ||||
|   | ||||
| @@ -7,11 +7,9 @@ namespace Toby\Infrastructure\Console\Commands; | ||||
| use Carbon\CarbonInterface; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Carbon; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\Facades\Http; | ||||
| use Spatie\SlashCommand\Attachment; | ||||
| use Toby\Domain\Enums\VacationType; | ||||
| use Toby\Domain\VacationTypeConfigRetriever; | ||||
| use Toby\Domain\DailySummaryRetriever; | ||||
| use Toby\Eloquent\Models\Holiday; | ||||
| use Toby\Eloquent\Models\User; | ||||
| use Toby\Eloquent\Models\Vacation; | ||||
| @@ -21,7 +19,7 @@ class SendDailySummaryToSlack extends Command | ||||
|     protected $signature = "toby:slack:daily-summary {--f|force}"; | ||||
|     protected $description = "Sent daily summary to slack"; | ||||
|  | ||||
|     public function handle(VacationTypeConfigRetriever $configRetriever): void | ||||
|     public function handle(DailySummaryRetriever $dailySummaryRetriever): void | ||||
|     { | ||||
|         $now = Carbon::today(); | ||||
|  | ||||
| @@ -29,42 +27,28 @@ class SendDailySummaryToSlack extends Command | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         /** @var Collection $absences */ | ||||
|         $absences = Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $now) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type))) | ||||
|             ->get() | ||||
|         $absences = $dailySummaryRetriever->getAbsences($now) | ||||
|             ->map(fn(Vacation $vacation) => $vacation->user->profile->full_name); | ||||
|  | ||||
|         /** @var Collection $remoteDays */ | ||||
|         $remoteDays = Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $now) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type))) | ||||
|             ->get() | ||||
|         $remoteDays = $dailySummaryRetriever->getRemoteDays($now) | ||||
|             ->map(fn(Vacation $vacation) => $vacation->user->profile->full_name); | ||||
|  | ||||
|         $birthdays = User::query() | ||||
|             ->whereRelation("profile", "birthday", $now) | ||||
|             ->get() | ||||
|         $birthdays = $dailySummaryRetriever->getBirthdays($now) | ||||
|             ->map(fn(User $user) => $user->profile->full_name); | ||||
|  | ||||
|         $absencesAttachment = Attachment::create() | ||||
|             ->setTitle("Nieobecności :palm_tree:") | ||||
|             ->setColor('#eab308') | ||||
|             ->setColor("#eab308") | ||||
|             ->setText($absences->isNotEmpty() ? $absences->implode("\n") : "Wszyscy dzisiaj pracują :muscle:"); | ||||
|  | ||||
|         $remoteAttachment = Attachment::create() | ||||
|             ->setTitle("Praca zdalna :house_with_garden:") | ||||
|             ->setColor('#d946ef') | ||||
|             ->setColor("#d946ef") | ||||
|             ->setText($remoteDays->isNotEmpty() ? $remoteDays->implode("\n") : "Wszyscy dzisiaj są w biurze :boom:"); | ||||
|  | ||||
|         $birthdayAttachment = Attachment::create() | ||||
|             ->setTitle("Urodziny :birthday:") | ||||
|             ->setColor('#3C5F97') | ||||
|             ->setColor("#3C5F97") | ||||
|             ->setText($birthdays->isNotEmpty() ? $birthdays->implode("\n") : "Dzisiaj nikt nie ma urodzin :cry:"); | ||||
|  | ||||
|         $baseUrl = config("services.slack.url"); | ||||
| @@ -74,8 +58,8 @@ class SendDailySummaryToSlack extends Command | ||||
|             ->post($url, [ | ||||
|                 "channel" => config("services.slack.default_channel"), | ||||
|                 "text" => "Podsumowanie dla dnia {$now->toDisplayString()}", | ||||
|                 'attachments' => collect([$absencesAttachment, $remoteAttachment, $birthdayAttachment])->map( | ||||
|                     fn(Attachment $attachment) => $attachment->toArray() | ||||
|                 "attachments" => collect([$absencesAttachment, $remoteAttachment, $birthdayAttachment])->map( | ||||
|                     fn(Attachment $attachment) => $attachment->toArray(), | ||||
|                 )->toArray(), | ||||
|             ]); | ||||
|     } | ||||
|   | ||||
| @@ -7,12 +7,11 @@ namespace Toby\Infrastructure\Http\Controllers; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Carbon; | ||||
| use Inertia\Response; | ||||
| use Toby\Domain\Enums\VacationType; | ||||
| use Toby\Domain\DailySummaryRetriever; | ||||
| use Toby\Domain\UserVacationStatsRetriever; | ||||
| use Toby\Domain\VacationRequestStatesRetriever; | ||||
| use Toby\Domain\VacationTypeConfigRetriever; | ||||
| use Toby\Eloquent\Helpers\YearPeriodRetriever; | ||||
| use Toby\Eloquent\Models\Vacation; | ||||
| use Toby\Eloquent\Models\VacationRequest; | ||||
| use Toby\Infrastructure\Http\Resources\HolidayResource; | ||||
| use Toby\Infrastructure\Http\Resources\VacationRequestResource; | ||||
| @@ -25,24 +24,14 @@ class DashboardController extends Controller | ||||
|         YearPeriodRetriever $yearPeriodRetriever, | ||||
|         UserVacationStatsRetriever $vacationStatsRetriever, | ||||
|         VacationTypeConfigRetriever $configRetriever, | ||||
|         DailySummaryRetriever $dailySummaryRetriever, | ||||
|     ): Response { | ||||
|         $user = $request->user(); | ||||
|         $now = Carbon::now(); | ||||
|         $yearPeriod = $yearPeriodRetriever->selected(); | ||||
|  | ||||
|         $absences = Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $now) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type))) | ||||
|             ->get(); | ||||
|  | ||||
|         $remoteDays = Vacation::query() | ||||
|             ->with(["user", "vacationRequest"]) | ||||
|             ->whereDate("date", $now) | ||||
|             ->approved() | ||||
|             ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type))) | ||||
|             ->get(); | ||||
|         $absences = $dailySummaryRetriever->getAbsences($now); | ||||
|         $remoteDays = $dailySummaryRetriever->getRemoteDays($now); | ||||
|  | ||||
|         if ($user->can("listAll", VacationRequest::class)) { | ||||
|             $vacationRequests = $yearPeriod->vacationRequests() | ||||
|   | ||||
| @@ -8,6 +8,8 @@ use Illuminate\Auth\Access\AuthorizationException; | ||||
| use Illuminate\Http\Request; | ||||
| use Inertia\Response; | ||||
| use Symfony\Component\HttpFoundation\RedirectResponse; | ||||
| use Toby\Domain\Notifications\KeyHasBeenGivenNotification; | ||||
| use Toby\Domain\Notifications\KeyHasBeenTakenNotification; | ||||
| use Toby\Eloquent\Models\Key; | ||||
| use Toby\Eloquent\Models\User; | ||||
| use Toby\Infrastructure\Http\Requests\GiveKeyRequest; | ||||
| @@ -60,6 +62,8 @@ class KeysController extends Controller | ||||
|  | ||||
|         $key->save(); | ||||
|  | ||||
|         $key->notify(new KeyHasBeenTakenNotification($request->user(), $previousUser)); | ||||
|  | ||||
|         return redirect() | ||||
|             ->back() | ||||
|             ->with("success", __("Key no :number has been taken from :user.", [ | ||||
| @@ -81,6 +85,8 @@ class KeysController extends Controller | ||||
|  | ||||
|         $key->save(); | ||||
|  | ||||
|         $key->notify(new KeyHasBeenGivenNotification($request->user(), $recipient)); | ||||
|  | ||||
|         return redirect() | ||||
|             ->back() | ||||
|             ->with("success", __("Key no :number has been given to :user.", [ | ||||
|   | ||||
| @@ -62,7 +62,8 @@ | ||||
|     "extra": { | ||||
|         "laravel": { | ||||
|             "dont-discover": [ | ||||
|                 "laravel/telescope" | ||||
|                 "laravel/telescope", | ||||
|                 "spatie/laravel-slack-slash-command" | ||||
|             ] | ||||
|         } | ||||
|     }, | ||||
|   | ||||
| @@ -8,21 +8,18 @@ use Toby\Domain\Slack\Handlers\GiveKeysTo; | ||||
| use Toby\Domain\Slack\Handlers\Help; | ||||
| use Toby\Domain\Slack\Handlers\HomeOffice; | ||||
| use Toby\Domain\Slack\Handlers\KeyList; | ||||
| use Toby\Domain\Slack\Handlers\SaySomething; | ||||
| use Toby\Domain\Slack\Handlers\TakeKeysFrom; | ||||
|  | ||||
| return [ | ||||
|     'url' => 'api/slack', | ||||
|     'signing_secret' => env('SLACK_SIGNING_SECRET'), | ||||
|     'verify_with_signing' => true, | ||||
|     'handlers' => [ | ||||
|     "signing_secret" => env("SLACK_SIGNING_SECRET"), | ||||
|     "verify_with_signing" => true, | ||||
|     "handlers" => [ | ||||
|         TakeKeysFrom::class, | ||||
|         GiveKeysTo::class, | ||||
|         KeyList::class, | ||||
|         HomeOffice::class, | ||||
|         DailySummary::class, | ||||
|         SaySomething::class, | ||||
|         Help::class, | ||||
|         CatchAll::class | ||||
|         CatchAll::class, | ||||
|     ], | ||||
| ]; | ||||
|   | ||||
| @@ -23,11 +23,11 @@ | ||||
|   "cancelled": "anulowany", | ||||
|   "rejected": "odrzucony", | ||||
|   "approved": "zatwierdzony", | ||||
|   "You have pending vacation request in this range.": "Masz oczekujący wniosek urlopowy w tym zakresie dat.", | ||||
|   "You have approved vacation request in this range.": "Masz zaakceptowany wniosek urlopowy w tym zakresie dat.", | ||||
|   "You have pending vacation request in this range.": "Masz oczekujący wniosek w tym zakresie dat.", | ||||
|   "You have approved vacation request in this range.": "Masz zaakceptowany wniosek w tym zakresie dat.", | ||||
|   "Vacation limit has been exceeded.": "Limit urlopu został przekroczony.", | ||||
|   "Vacation needs minimum one day.": "Urlop musi być co najmniej na jeden dzień.", | ||||
|   "The vacation request cannot be created at the turn of the year.": "Wniosek urlopowy nie może zostać złożony na przełomie roku.", | ||||
|   "The vacation request cannot be created at the turn of the year.": "Wniosek nie może zostać złożony na przełomie roku.", | ||||
|   "User has been created.": "Użytkownik został utworzony.", | ||||
|   "User has been updated.": "Użytkownik został zaktualizowany.", | ||||
|   "User has been deleted.": "Użytkownik został usunięty.", | ||||
| @@ -37,11 +37,11 @@ | ||||
|   "Holiday has been deleted.": "Dzień wolny został usunięty.", | ||||
|   "Selected year period has been changed.": "Wybrany rok został zmieniony.", | ||||
|   "Vacation limits have been updated.": "Limity urlopów zostały zaktualizowane.", | ||||
|   "Vacation request has been created.": "Wniosek urlopowy został utworzony.", | ||||
|   "Vacation request has been accepted.": "Wniosek urlopowy został zaakceptowany.", | ||||
|   "Vacation request has been approved.": "Wniosek urlopowy został zatwierdzony.", | ||||
|   "Vacation request has been rejected.": "Wniosek urlopowy został odrzucony.", | ||||
|   "Vacation request has been cancelled.": "Wniosek urlopowy został anulowany.", | ||||
|   "Vacation request has been created.": "Wniosek został utworzony.", | ||||
|   "Vacation request has been accepted.": "Wniosek został zaakceptowany.", | ||||
|   "Vacation request has been approved.": "Wniosek został zatwierdzony.", | ||||
|   "Vacation request has been rejected.": "Wniosek został odrzucony.", | ||||
|   "Vacation request has been cancelled.": "Wniosek został anulowany.", | ||||
|   "Sum:": "Suma:", | ||||
|   "Date": "Data", | ||||
|   "Day of week": "Dzień tygodnia", | ||||
| @@ -71,5 +71,7 @@ | ||||
|   "Key no :number has been created.": "Klucz nr :number został utworzony.", | ||||
|   "Key no :number has been deleted.": "Klucz nr :number został usunięty.", | ||||
|   "Key no :number has been taken from :user.": "Klucz nr :number został zabrany użytkownikowi :user.", | ||||
|   "Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user." | ||||
|   "Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user.", | ||||
|   ":sender gives key no :key to :recipient": ":sender przekazuje klucz nr :key :recipient", | ||||
|   ":recipient takes key no :key from :sender": ":recipient zabiera klucz nr :key :sender" | ||||
| } | ||||
|   | ||||
| @@ -3,11 +3,14 @@ | ||||
| declare(strict_types=1); | ||||
|  | ||||
| use Illuminate\Support\Facades\Route; | ||||
| use Toby\Domain\Slack\Controller as SlackController; | ||||
| use Toby\Infrastructure\Http\Controllers\Api\CalculateUserUnavailableDaysController; | ||||
| use Toby\Infrastructure\Http\Controllers\Api\CalculateUserVacationStatsController; | ||||
| use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController; | ||||
| use Toby\Infrastructure\Http\Controllers\Api\GetAvailableVacationTypesController; | ||||
|  | ||||
| Route::post("slack", [SlackController::class, "getResponse"]); | ||||
|  | ||||
| Route::middleware("auth:sanctum")->group(function (): void { | ||||
|     Route::post("vacation/calculate-days", CalculateVacationDaysController::class); | ||||
|     Route::post("vacation/calculate-stats", CalculateUserVacationStatsController::class); | ||||
|   | ||||
| @@ -5,6 +5,7 @@ declare(strict_types=1); | ||||
| namespace Tests\Feature; | ||||
|  | ||||
| use Illuminate\Foundation\Testing\DatabaseMigrations; | ||||
| use Illuminate\Support\Facades\Notification; | ||||
| use Inertia\Testing\AssertableInertia as Assert; | ||||
| use Tests\FeatureTestCase; | ||||
| use Toby\Eloquent\Models\Key; | ||||
| @@ -14,6 +15,13 @@ class KeyTest extends FeatureTestCase | ||||
| { | ||||
|     use DatabaseMigrations; | ||||
|  | ||||
|     protected function setUp(): void | ||||
|     { | ||||
|         parent::setUp(); | ||||
|  | ||||
|         Notification::fake(); | ||||
|     } | ||||
|  | ||||
|     public function testUserCanSeeKeyList(): void | ||||
|     { | ||||
|         Key::factory()->count(10)->create(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user