Files
hqland-app/app/Console/Commands/SendPaymentDueNotifications.php

77 lines
2.5 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Models\PaymentScheduleItem;
use App\Models\User;
use App\Notifications\PaymentDueNotification;
use Illuminate\Console\Command;
class SendPaymentDueNotifications extends Command
{
protected $signature = 'notifications:send-due-payments
{--days=7 : Số ngày trước hạn để cảnh báo}
{--dry-run : Chỉ liệt kê, không gửi}';
protected $description = 'Gửi cảnh báo đợt thanh toán sắp đến hạn cho tất cả users';
public function handle(): int
{
$days = (int) $this->option('days');
$dryRun = $this->option('dry-run');
$from = now();
$to = now()->addDays($days);
$items = PaymentScheduleItem::query()
->with(['schedule.contract', 'payments'])
->whereHas('schedule.contract')
->whereDate('due_date', '>=', $from)
->whereDate('due_date', '<=', $to)
->whereRaw('amount > (SELECT COALESCE(SUM(amount), 0) FROM payments WHERE payments.schedule_item_id = payment_schedule_items.id)')
->orderBy('due_date')
->get();
if ($items->isEmpty()) {
$this->warn('Không có đợt thanh toán nào sắp đến hạn trong ' . $days . ' ngày tới.');
return self::SUCCESS;
}
$this->info("Tìm thấy {$items->count()} đợt thanh toán sắp đến hạn.");
$users = User::all();
if ($users->isEmpty()) {
$this->warn('Không có user nào trong hệ thống để nhận thông báo.');
return self::FAILURE;
}
foreach ($items as $item) {
$contract = $item->schedule?->contract;
$remaining = (float) $item->remaining_amount;
$this->line(sprintf(
'- HĐ %s | Đợt %d | Ngày %s | Còn thiếu: %s VNĐ',
$contract?->contract_number ?? 'N/A',
$item->installment_no,
$item->due_date?->format('d/m/Y'),
number_format($remaining)
));
if (! $dryRun) {
foreach ($users as $user) {
$user->notify(new PaymentDueNotification($item));
}
}
}
if ($dryRun) {
$this->info('Chế độ dry-run: Không có thông báo nào được gửi.');
} else {
$this->info("Đã gửi thông báo cho {$users->count()} user(s).");
}
return self::SUCCESS;
}
}