›
›
›
  1. docs
  2. ›
  3. byrcsc/laravel-assignment
1.x
Browse documentationOpenClose

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Assignments and slots
  • Assigning and offering
  • Selection policies
  • Scopes and rotation
  • Profiles
  • The queue
  • Offer cascades

Operations

  • Expiry and scheduling
  • Reading assignments
  • Notifications
  • Events and listeners
  • Concurrency guarantees

Reference

  • Configuration
  • API reference
  • Console commands
  • Exceptions
  • Testing
  • Troubleshooting

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • Assignments and slots
  • Assigning and offering
  • Selection policies
  • Scopes and rotation
  • Profiles
  • The queue
  • Offer cascades

Operations

  • Expiry and scheduling
  • Reading assignments
  • Notifications
  • Events and listeners
  • Concurrency guarantees

Reference

  • Configuration
  • API reference
  • Console commands
  • Exceptions
  • Testing
  • Troubleshooting

byrcsc/laravel-assignment · 1.x

Notifications.

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.

When the assignee is notified

MomentNotificationSent to
An offer is madeOfferReceivedThe assignee the offer names
An offer expiresOfferExpiredThe assignee who let it lapse
An assignment becomes activeAssignmentReceivedThe new holder
An assignment is taken awayAssignmentRemovedThe 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:

  • Declining. The assignee chose not to take the work, so the package sends them nothing. The next candidate in the cascade gets their offer notification as normal.
  • Completion. Finishing work is not news to the person who finished it.

Reassignment sends exactly two notifications: AssignmentRemoved to the outgoing assignee and AssignmentReceived to the incoming one.

Channels

// 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 migrate

The 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.

Assignees that cannot be notified

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));
    }
}

Swapping a notification

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.

Silencing one

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.

Changing the wording

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.

Changing the mail markup

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
@endcomponent

The package renders the messages as markdown mail, so the mail:: components are available.

Queueing

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.

What it does not do

  • Notify anyone but the assignee. This is a permanent design decision. Notify anyone else from an event listener.
  • Fan out to a team's members. The package skips a non-notifiable assignee.
  • Digest or throttle. A cascade of ten offers sends ten notifications, one to each candidate as the engine asks them.
  • Notify on decline or completion. See above.

What to read next

  • Events and listeners for everything beyond the assignee.
  • Configuration for the keys and defaults.
  • Offer cascades for what a declined offer sends next.
PreviousReading assignmentsNextEvents and listeners
View source

On this page

  1. When the assignee is notified
  2. Channels
  3. Assignees that cannot be notified
  4. Swapping a notification
  5. Silencing one
  6. Changing the wording
  7. Changing the mail markup
  8. Queueing
  9. What it does not do
  10. What to read next