›
byrcsc/laravel-assignment · 1.x
The engine notifies the assignee when their work changes, and config can swap or remove each notification.
The package notifies one person: the assignee whose work changed. To reach managers, watchers, or dashboards, listen to events instead.
| Moment | Notification | Sent to |
|---|---|---|
| An offer is made | OfferReceived | The assignee the offer names |
| An offer expires | OfferExpired | The assignee who let it lapse |
| An assignment becomes active | AssignmentReceived | The new holder |
| An assignment is taken away | AssignmentRemoved | The holder who lost it |
AssignmentReceived covers both routes to active work: a direct assign() and
an accepted offer. A listener does not need to tell them apart.
These cases send nothing, by design:
Reassignment sends exactly two notifications: AssignmentRemoved to the
outgoing assignee and AssignmentReceived to the incoming one.
// config/assignment.php
'notification_channels' => ['mail'],Mail is the only channel on by default, because it needs nothing installed. The list applies to every notification.
Adding 'database' requires Laravel's notifications table:
php artisan make:notifications-table
php artisan migrateThe database payload has five keys:
[
'assignment_id' => 41,
'assignable_type' => 'App\Models\Callout',
'assignable_id' => 7,
'role' => 'crew',
'status' => 'offered',
]Any channel Laravel supports works, as long as your notifiable can route to it.
Set ['mail', 'database', 'broadcast'] and all three are used.
The package skips an assignee that does not use Laravel's Notifiable trait,
and raises no error. A Team model with no inbox is a normal assignee. To
notify its members, send the notification yourself from a listener:
public function handle(Assigned $event): void
{
$team = $event->assignment->assignee;
if ($team instanceof Team) {
Notification::send($team->members, new WorkArrived($event->assignment));
}
}Point the config key at your own class:
// config/assignment.php
'notifications' => [
'offered' => App\Notifications\CrewOfferReceived::class,
'offer_expired' => ByRcsc\LaravelAssignment\Notifications\OfferExpired::class,
'assigned' => ByRcsc\LaravelAssignment\Notifications\AssignmentReceived::class,
'unassigned' => ByRcsc\LaravelAssignment\Notifications\AssignmentRemoved::class,
],The container builds the class and passes the assignment as assignment. The
shortest replacement extends the shipped base class:
use ByRcsc\LaravelAssignment\Notifications\AssignmentNotification;
final class CrewOfferReceived extends AssignmentNotification
{
protected function name(): string
{
return 'offer_received';
}
public function via(object $notifiable): array
{
return ['mail', 'sms'];
}
}name() chooses which translation keys and which mail view the notification
uses. Overriding via(), toMail(), or toArray() on your subclass changes
one notification without touching the others.
A class that does not extend AssignmentNotification works too, as long as it
is a notification and its constructor accepts assignment.
Set the key to null:
'notifications' => [
'offered' => ByRcsc\LaravelAssignment\Notifications\OfferReceived::class,
'offer_expired' => null,
'assigned' => null,
'unassigned' => ByRcsc\LaravelAssignment\Notifications\AssignmentRemoved::class,
],The package sends nothing for a moment set to null, and no listener runs.
php artisan vendor:publish --tag="assignment-translations"The command writes lang/vendor/assignment/en/notifications.php, keyed by
moment:
return [
'offer_received' => [
'subject' => 'You have received an assignment offer',
'body' => 'A new assignment offer is waiting for your response.',
],
'offer_expired' => [...],
'assignment_received' => [...],
'assignment_removed' => [...],
];Add a directory per locale to translate them.
php artisan vendor:publish --tag="assignment-views"The command writes the Blade files to
resources/views/vendor/assignment/mail/, one per moment. Each receives
$assignment and $body, and builds on Laravel's own mail::message
component:
@component('mail::message')
# {{ __('assignment::notifications.assignment_received.subject') }}
{{ $body }}
@component('mail::button', ['url' => route('callouts.show', $assignment->assignable)])
View the callout
@endcomponent
@endcomponentThe package renders the messages as markdown mail, so the mail:: components
are available.
The shipped notifications use Laravel's Queueable trait but do not implement
ShouldQueue, so they are sent inline. To move them off the request, extend
one and add the interface:
final class QueuedOfferReceived extends OfferReceived implements ShouldQueue
{
}Point the config key at it. You cannot queue the events themselves. Queue a listener instead, as events shows.