feat: finish removing console kernel, add expiring invite notification

Signed-off-by: Miguel Nogueira <me@nogueira.codes>
This commit is contained in:
2025-08-09 20:38:50 +01:00
parent 9e77205820
commit 627c619abf
6 changed files with 304 additions and 74 deletions

View File

@@ -1,74 +0,0 @@
<?php
/*
* Copyright © 2020 Miguel Nogueira
*
* This file is part of Raspberry Staff Manager.
*
* Raspberry Staff Manager is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Raspberry Staff Manager is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Raspberry Staff Manager. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Console;
use App\Jobs\ProcessDueSuspensions;
use App\Jobs\ProcessExpiredAbsences;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('vote:evaluate')
->daily();
// Production value: Every day
$schedule->job(new ProcessDueSuspensions)
->daily();
// Production value: Every day
// Development value: Every minute
$schedule->job(new ProcessExpiredAbsences)
->daily();
// Production value: Every day
// Development value: Every minute
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace App\Jobs;
use App\Invitation;
use Carbon\Carbon;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Mail;
use App\Mail\InviteExpiringSoon;
class ExpiredInviteCleanup implements ShouldQueue
{
use Queueable;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
// 1. Notify invites expiring within the next 24 hours that haven't been notified yet
Invitation::where('status', 'pending')
->where('notified', false)
->whereBetween('expiration', [Carbon::now(), Carbon::now()->addDay()])
->chunkById(100, function ($invites) {
foreach ($invites as $invite) {
Mail::to($invite->requestor_email)
->send(new InviteExpiringSoon($invite));
$invite->notified = true;
$invite->save();
}
});
// 2. Delete invites that have actually expired
Invitation::where('status', 'pending')
->where('expiration', '<', Carbon::now())
->chunkById(100, function ($invites) {
foreach ($invites as $invite) {
$invite->delete();
}
});
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace App\Jobs;
use App\Invitation;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
// General Housekeeping Job: Drop Approved and Completed Invites
class InviteLifecycleCleanup implements ShouldQueue
{
use Queueable;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
Invitation::whereIn('status', ['approved', 'completed'])
->chunkById(100, function ($invites) {
foreach ($invites as $invite) {
$invite->delete();
}
});
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace App\Mail;
use App\Invitation;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class InviteExpiringSoon extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
public Invitation $invite;
/**
* Create a new message instance.
*/
public function __construct($invite)
{
$this->invite = $invite;
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Your invitation to . ' . config('app.name') . ' is expiring soon',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.invite-expiring',
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}