Add recipient email and milestone notifications on transfer create.
Deploy Ladill Transfer / deploy (push) Successful in 44s
Deploy Ladill Transfer / deploy (push) Successful in 44s
Recipients can be emailed the download link immediately and at optional reminders (7/3/1 days before unavailable, or when grace period starts). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Transfer;
|
||||
|
||||
use App\Models\Transfer;
|
||||
use App\Notifications\TransferRecipientNotification;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
/** Sends milestone emails to transfer recipients (share link + reminders). */
|
||||
class TransferRecipientMailService
|
||||
{
|
||||
/** @return list<string> */
|
||||
public function allowedMilestones(): array
|
||||
{
|
||||
return array_keys((array) config('transfer.recipient_email_milestones', []));
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
public function milestoneOptions(): array
|
||||
{
|
||||
return (array) config('transfer.recipient_email_milestones', []);
|
||||
}
|
||||
|
||||
/** @param list<string> $milestones */
|
||||
public function normalizeMilestones(array $milestones): array
|
||||
{
|
||||
$allowed = $this->allowedMilestones();
|
||||
|
||||
return array_values(array_unique(array_filter(
|
||||
$milestones,
|
||||
static fn ($milestone) => in_array((string) $milestone, $allowed, true),
|
||||
)));
|
||||
}
|
||||
|
||||
public function notifyRecipient(Transfer $transfer, string $milestone): bool
|
||||
{
|
||||
$email = trim((string) $transfer->recipient_email);
|
||||
if ($email === '' || ! $transfer->wantsRecipientMilestone($milestone)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($transfer->recipientMilestoneSent($milestone)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Notification::route('mail', $email)->notify(
|
||||
new TransferRecipientNotification($transfer->loadMissing(['files', 'qrCode', 'user']), $milestone),
|
||||
);
|
||||
|
||||
$transfer->markRecipientMilestoneSent($milestone);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function processDueMilestones(): int
|
||||
{
|
||||
$sent = 0;
|
||||
|
||||
Transfer::query()
|
||||
->accessible()
|
||||
->whereNotNull('recipient_email')
|
||||
->whereNotNull('recipient_email_milestones')
|
||||
->with(['files', 'qrCode', 'user'])
|
||||
->chunkById(100, function ($transfers) use (&$sent) {
|
||||
foreach ($transfers as $transfer) {
|
||||
foreach ($this->dueDayMilestones($transfer) as $milestone) {
|
||||
if ($this->notifyRecipient($transfer, $milestone)) {
|
||||
$sent++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return $sent;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
private function dueDayMilestones(Transfer $transfer): array
|
||||
{
|
||||
if (! $transfer->paid_until instanceof CarbonInterface || $transfer->paid_until->isPast()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$daysRemaining = (int) now()->startOfDay()->diffInDays(
|
||||
$transfer->paid_until->copy()->startOfDay(),
|
||||
false,
|
||||
);
|
||||
|
||||
$due = [];
|
||||
foreach (['7', '3', '1'] as $milestone) {
|
||||
if ($daysRemaining === (int) $milestone && $transfer->wantsRecipientMilestone($milestone)) {
|
||||
$due[] = $milestone;
|
||||
}
|
||||
}
|
||||
|
||||
return $due;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user