Files
2026-04-28 21:14:25 +03:00

268 lines
8.9 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Carbon\Carbon;
class CheckNDTReminders extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'notifications:check-ndt';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check NDT tests and send reminder notifications for overdue or pending tests';
/**
* Execute the console command.
* Performance: Optimized with chunking and bulk operations
*
* @return int
*/
public function handle()
{
$this->info('Starting NDT reminder checks...');
$totalNotifications = 0;
// Check overdue NDT tests
$totalNotifications += $this->checkOverdueTests();
// Check missing test reports
$totalNotifications += $this->checkMissingReports();
// Check deadline approaching tests (within 3 days)
$totalNotifications += $this->checkDeadlineApproaching();
// Check pending results
$totalNotifications += $this->checkPendingResults();
$this->info("NDT reminder check completed. Sent {$totalNotifications} notifications.");
return 0;
}
/**
* Check for overdue NDT tests
* Performance: Single query with multiple conditions
*/
private function checkOverdueTests()
{
$overdueThreshold = Carbon::now()->subDays(7); // 7 days overdue
$nullableColumns = $this->availableColumns('weld_logs', [
'rt_testing_date',
'ut_testing_date',
'pt_testing_date',
'mt_testing_date'
]);
if (empty($nullableColumns)) {
$this->info('Skipping overdue check: weld_logs table lacks test date columns.');
return 0;
}
$ids = DB::table('weld_logs')
->where('welding_date', '<=', $overdueThreshold)
->where(function($query) use ($nullableColumns) {
foreach ($nullableColumns as $column) {
$query->orWhereNull($column);
}
})
->pluck('id')
->toArray();
return $this->sendWeldLogBatch(
'notification_ndt_test_overdue',
'NDT Test Overdue',
'%d weld log(s) have welding dates older than 7 days without NDT testing.',
$ids
);
}
/**
* Check for missing test reports
* Performance: Checks only records with test dates but no results
*/
private function checkMissingReports()
{
$checkDate = Carbon::now()->subDays(3); // 3 days after test date
$rtIds = [];
if ($this->columnsAvailable('weld_logs', ['rt_testing_date', 'rt_result'])) {
$rtIds = DB::table('weld_logs')
->whereNotNull('rt_testing_date')
->where('rt_testing_date', '<=', $checkDate)
->where(function($query) {
$query->whereNull('rt_result')
->orWhere('rt_result', '');
})
->pluck('id')
->toArray();
}
$utIds = [];
if ($this->columnsAvailable('weld_logs', ['ut_testing_date', 'ut_result'])) {
$utIds = DB::table('weld_logs')
->whereNotNull('ut_testing_date')
->where('ut_testing_date', '<=', $checkDate)
->where(function($query) {
$query->whereNull('ut_result')
->orWhere('ut_result', '');
})
->pluck('id')
->toArray();
}
$notifications = 0;
$notifications += $this->sendWeldLogBatch(
'notification_ndt_report_missing',
'RT Report Missing',
'%d RT test(s) have results pending more than 3 days.',
$rtIds
);
$notifications += $this->sendWeldLogBatch(
'notification_ndt_report_missing',
'UT Report Missing',
'%d UT test(s) have results pending more than 3 days.',
$utIds
);
return $notifications;
}
/**
* Check for tests with approaching deadlines
* Performance: Single query with date calculation
*/
private function checkDeadlineApproaching()
{
$warnDate = Carbon::now()->subDays(4); // Welded 4 days ago, should be tested within 7 days
$graceDate = Carbon::now()->subDays(7);
$dateColumns = array_filter($this->availableColumns('weld_logs', ['rt_testing_date', 'ut_testing_date']));
if (empty($dateColumns)) {
$this->info('Skipping deadline approaching check: weld_logs table lacks RT/UT testing date columns.');
return 0;
}
$ids = DB::table('weld_logs')
->whereBetween('welding_date', [$graceDate, $warnDate]) // Fixed: older date first, newer date second
->where(function($query) use ($dateColumns) {
foreach ($dateColumns as $column) {
$query->orWhereNull($column);
}
})
->pluck('id')
->toArray();
return $this->sendWeldLogBatch(
'notification_test_deadline_approaching',
'Test Deadline Approaching',
'%d weld log(s) are approaching the 7-day NDT testing deadline.',
$ids
);
}
/**
* Check for pending test results
* Performance: Optimized with specific conditions
*/
private function checkPendingResults()
{
$pendingThreshold = Carbon::now()->subDays(2);
$ids = [];
$rtColumnsAvailable = $this->columnsAvailable('weld_logs', ['rt_testing_date', 'rt_result']);
$utColumnsAvailable = $this->columnsAvailable('weld_logs', ['ut_testing_date', 'ut_result']);
if (!$rtColumnsAvailable && !$utColumnsAvailable) {
$this->info('Skipping pending results check: weld_logs table lacks RT/UT result columns.');
return 0;
}
$query = DB::table('weld_logs')
->where(function($query) use ($pendingThreshold) {
if ($this->columnsAvailable('weld_logs', ['rt_testing_date', 'rt_result'])) {
$query->orWhere(function($q) use ($pendingThreshold) {
$q->whereNotNull('rt_testing_date')
->where('rt_testing_date', '<=', $pendingThreshold)
->where(function($sq) {
$sq->whereNull('rt_result')
->orWhere('rt_result', '');
});
});
}
if ($this->columnsAvailable('weld_logs', ['ut_testing_date', 'ut_result'])) {
$query->orWhere(function($q) use ($pendingThreshold) {
$q->whereNotNull('ut_testing_date')
->where('ut_testing_date', '<=', $pendingThreshold)
->where(function($sq) {
$sq->whereNull('ut_result')
->orWhere('ut_result', '');
});
});
}
});
$ids = $query->pluck('id')->toArray();
return $this->sendWeldLogBatch(
'notification_ndt_result_pending',
'NDT Result Pending',
'%d weld log(s) have completed NDT tests but results are pending more than 2 days.',
$ids
);
}
private function sendWeldLogBatch(string $notificationCode, string $title, string $messageTemplate, array $ids): int
{
$ids = array_values(array_unique(array_filter($ids)));
if (empty($ids)) {
$this->info("No {$title} notifications to send.");
return 0;
}
$filterParams = [
'table' => 'weld_logs',
'conditions' => [
'id' => $ids
]
];
sendBatchNotificationWithFilter(
$notificationCode,
$title,
$messageTemplate,
$filterParams,
count($ids)
);
$this->info("Sent batch notification for {$title} (" . count($ids) . " joints).");
return 1;
}
private function availableColumns(string $table, array $columns): array
{
return array_values(array_filter($columns, function($column) use ($table) {
return Schema::hasColumn($table, $column);
}));
}
private function columnsAvailable(string $table, array $columns): bool
{
return count($this->availableColumns($table, $columns)) === count($columns);
}
}