›
›
›
  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 at four moments, and each notification is swappable or removable.

The package notifies one person: the assignee whose work changed. Managers, watchers, and dashboards are not its business, and hang off events instead.

The four moments

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.

Two cases are deliberately quiet:

  • Declining. The assignee chose not to take it, so nothing is sent to them. 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 all four notifications.

Adding 'database' requires Laravel's notifications table:

php artisan make:notifications-table
php artisan migrate

The database payload is small and stable:

[
    '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

An assignee that does not use Laravel's Notifiable trait is skipped without an error. A Team model with no inbox is a normal assignee, and fanning out to its members is your application's decision:

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 class is built through the container with the assignment passed as assignment, so the simplest replacement extends the shipped base:

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 other three.

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,
],

Nothing is sent for a null moment, and no listener runs.

Changing the wording

php artisan vendor:publish --tag="assignment-translations"

That 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"

That writes four 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 messages are rendered 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. The events themselves cannot be queued; see events.

What it does not do

  • Notify anyone but the assignee. Permanently. Everything else is an event listener.
  • Fan out to a team's members. A non-notifiable assignee is skipped.
  • Digest or throttle. A cascade of ten offers sends ten notifications, one per candidate as they are asked.
  • 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. The four moments
  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