92 lines
3.3 KiB
PHP
92 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Enums\Invoice\InvoiceStatus;
|
|
use App\Enums\Order\OrderStatus;
|
|
use App\Models\Invoice;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class CheckOverdueInvoices extends Command
|
|
{
|
|
protected $signature = 'invoices:check-overdue {--dry-run : Preview invoices without updating data}';
|
|
protected $description = 'Mark unpaid invoices past due date as overdue and keep related orders unpaid.';
|
|
|
|
public function handle(): int
|
|
{
|
|
$today = now()->toDateString();
|
|
$dryRun = (bool) $this->option('dry-run');
|
|
|
|
$overdueByStatus = Invoice::query()
|
|
->whereNotNull('due_date')
|
|
->whereDate('due_date', '<', $today)
|
|
->selectRaw('status, count(*) as total')
|
|
->groupBy('status')
|
|
->orderBy('status')
|
|
->get();
|
|
|
|
if ($overdueByStatus->isNotEmpty()) {
|
|
$this->line('invoices:check-overdue | Past-due invoices by current status:');
|
|
foreach ($overdueByStatus as $row) {
|
|
$label = InvoiceStatus::tryFrom((int) $row->status)?->label() ?? 'Không xác định';
|
|
$this->line(" - {$label} ({$row->status}): {$row->total}");
|
|
}
|
|
}
|
|
|
|
$invoices = Invoice::query()
|
|
->with('order:id,status')
|
|
->whereNotNull('due_date')
|
|
->whereDate('due_date', '<', $today)
|
|
->whereIn('status', [InvoiceStatus::UNPAID->value, InvoiceStatus::OVERDUE->value])
|
|
->get();
|
|
|
|
$this->info("invoices:check-overdue | Found {$invoices->count()} invoice(s) due before {$today}.");
|
|
|
|
$updatedInvoices = 0;
|
|
$updatedOrders = 0;
|
|
|
|
foreach ($invoices as $invoice) {
|
|
$needsInvoiceUpdate = (int) $invoice->status !== InvoiceStatus::OVERDUE->value;
|
|
$order = $invoice->order;
|
|
$needsOrderUpdate = $order
|
|
&& ! in_array((int) $order->status, [OrderStatus::PENDING->value, OrderStatus::CANCELLED->value], true);
|
|
|
|
$this->line(sprintf(
|
|
' [%s] Invoice #%s due %s%s',
|
|
$dryRun ? 'dry-run' : 'check',
|
|
$invoice->invoice_number,
|
|
$invoice->due_date?->format('Y-m-d') ?? '-',
|
|
$order ? " | order #{$invoice->order_id}" : ''
|
|
));
|
|
|
|
if ($dryRun || (! $needsInvoiceUpdate && ! $needsOrderUpdate)) {
|
|
continue;
|
|
}
|
|
|
|
DB::transaction(function () use ($invoice, $order, $needsInvoiceUpdate, $needsOrderUpdate, &$updatedInvoices, &$updatedOrders) {
|
|
if ($needsInvoiceUpdate) {
|
|
$invoice->update(['status' => InvoiceStatus::OVERDUE->value]);
|
|
$updatedInvoices++;
|
|
}
|
|
|
|
if ($needsOrderUpdate && $order) {
|
|
$order->update(['status' => OrderStatus::PENDING->value]);
|
|
$updatedOrders++;
|
|
}
|
|
});
|
|
|
|
Log::info('Invoice marked overdue', [
|
|
'invoice_id' => $invoice->id,
|
|
'invoice_number' => $invoice->invoice_number,
|
|
'order_id' => $invoice->order_id,
|
|
]);
|
|
}
|
|
|
|
$this->info("invoices:check-overdue | Updated {$updatedInvoices} invoice(s), {$updatedOrders} order(s).");
|
|
|
|
return Command::SUCCESS;
|
|
}
|
|
}
|