Fixed #18959 - refresh data on checkout notification

This commit is contained in:
snipe
2026-05-07 11:59:01 +01:00
parent bd8e944e2f
commit 158e66f9c6
3 changed files with 68 additions and 11 deletions
+22 -11
View File
@@ -34,6 +34,7 @@ use App\Notifications\CheckoutLicenseSeatNotification;
use Exception;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notification as BaseNotification;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
@@ -126,12 +127,12 @@ class CheckoutableListener
if ($shouldSendWebhookNotification) {
try {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckoutNotification($event)->toMicrosoftTeams();
$message = $this->getCheckoutNotification($event, $acceptance, true)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event, $acceptance));
->notify($this->getCheckoutNotification($event, $acceptance, true));
}
} catch (ClientException $e) {
$status = $e->getResponse()->getStatusCode();
@@ -233,12 +234,12 @@ class CheckoutableListener
// Send Webhook notification
try {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckinNotification($event)->toMicrosoftTeams();
$message = $this->getCheckinNotification($event, true)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckinNotification($event));
->notify($this->getCheckinNotification($event, true));
}
} catch (ClientException $e) {
$status = $e->getResponse()->getStatusCode();
@@ -312,12 +313,12 @@ class CheckoutableListener
* @param CheckoutableCheckedIn $event
* @return Notification
*/
private function getCheckinNotification($event)
private function getCheckinNotification($event, bool $refreshCheckoutable = false): BaseNotification
{
$notificationClass = null;
$checkoutable = $this->getCheckoutableForNotification($event->checkoutable, $refreshCheckoutable);
switch (get_class($event->checkoutable)) {
switch (get_class($checkoutable)) {
case Accessory::class:
$notificationClass = CheckinAccessoryNotification::class;
break;
@@ -334,7 +335,7 @@ class CheckoutableListener
Log::debug('Notification class: '.$notificationClass);
return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
return new $notificationClass($checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
}
/**
@@ -344,11 +345,12 @@ class CheckoutableListener
* @param CheckoutAcceptance|null $acceptance
* @return Notification
*/
private function getCheckoutNotification($event, $acceptance = null)
private function getCheckoutNotification($event, $acceptance = null, bool $refreshCheckoutable = false): BaseNotification
{
$notificationClass = null;
$checkoutable = $this->getCheckoutableForNotification($event->checkoutable, $refreshCheckoutable);
switch (get_class($event->checkoutable)) {
switch (get_class($checkoutable)) {
case Accessory::class:
$notificationClass = CheckoutAccessoryNotification::class;
break;
@@ -366,7 +368,16 @@ class CheckoutableListener
break;
}
return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note);
return new $notificationClass($checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note);
}
private function getCheckoutableForNotification(Model $checkoutable, bool $shouldRefresh): Model
{
if (! $shouldRefresh) {
return $checkoutable;
}
return $checkoutable->fresh() ?? $checkoutable;
}
private function getCheckoutMailType($event, $acceptance)
@@ -16,6 +16,7 @@ use App\Notifications\CheckinAssetNotification;
use App\Notifications\CheckinComponentNotification;
use App\Notifications\CheckinLicenseSeatNotification;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Facades\Notification;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Group;
@@ -145,6 +146,28 @@ class SlackNotificationsUponCheckinTest extends TestCase
$this->assertSlackNotificationSent(CheckinAssetNotification::class);
}
public function test_asset_checkin_slack_notification_uses_updated_asset_location()
{
$this->settings->enableSlackWebhook();
$previousLocation = Location::factory()->create(['name' => 'Region B']);
$newLocation = Location::factory()->create(['name' => 'Office A']);
$target = User::factory()->create(['location_id' => $previousLocation->id]);
$asset = Asset::factory()->create(['location_id' => $previousLocation->id]);
// Simulate post-checkin state while keeping a stale in-memory relation loaded.
$asset->location_id = $newLocation->id;
$asset->save();
$this->fireCheckInEvent($asset, $target);
Notification::assertSentTo(
new AnonymousNotifiable,
CheckinAssetNotification::class,
fn (CheckinAssetNotification $notification): bool => $notification->item->location?->is($newLocation)
);
}
#[DataProvider('licenseCheckInTargets')]
public function test_license_checkin_sends_slack_notification_when_setting_enabled($checkoutTarget)
{
@@ -18,6 +18,7 @@ use App\Notifications\CheckoutComponentNotification;
use App\Notifications\CheckoutConsumableNotification;
use App\Notifications\CheckoutLicenseSeatNotification;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Notification;
use PHPUnit\Framework\Attributes\DataProvider;
@@ -159,6 +160,28 @@ class SlackNotificationsUponCheckoutTest extends TestCase
$this->assertSlackNotificationSent(CheckoutAssetNotification::class);
}
public function test_asset_checkout_slack_notification_uses_updated_asset_location()
{
$this->settings->enableSlackWebhook();
$previousLocation = Location::factory()->create(['name' => 'Office A']);
$newLocation = Location::factory()->create(['name' => 'Region B']);
$target = User::factory()->create(['location_id' => $newLocation->id, 'email' => null]);
$asset = Asset::factory()->create(['location_id' => $previousLocation->id]);
// Simulate post-checkout state while keeping a stale in-memory relation loaded.
$asset->location_id = $newLocation->id;
$asset->save();
$this->fireCheckOutEvent($asset, $target);
Notification::assertSentTo(
new AnonymousNotifiable,
CheckoutAssetNotification::class,
fn (CheckoutAssetNotification $notification): bool => $notification->item->location?->is($newLocation)
);
}
public function test_consumable_checkout_sends_slack_notification_when_setting_enabled()
{
$this->settings->enableSlackWebhook();