last_performed_at ?? now(); return match ($schedule->frequency_type) { 'daily' => $base->copy()->addDays($schedule->frequency_value), 'weekly' => $base->copy()->addWeeks($schedule->frequency_value), 'monthly' => $base->copy()->addMonths($schedule->frequency_value), 'quarterly' => $base->copy()->addMonths(3 * $schedule->frequency_value), 'semi_annual' => $base->copy()->addMonths(6 * $schedule->frequency_value), 'annual' => $base->copy()->addYears($schedule->frequency_value), default => null, }; } public function updateNextDue(PreventiveSchedule $schedule): void { $next = $this->calculateNextDue($schedule); if ($next) { $schedule->update(['next_due_at' => $next]); } } public function generateEquipmentQrCode(Business $business, Equipment $equipment): string { $code = $equipment->qr_code ?: 'EQ-'.$business->id.'-'.$equipment->id.'-'.Str::upper(Str::random(6)); if (! $equipment->qr_code) { $equipment->update(['qr_code' => $code]); } return $code; } public function checkDueReminders(Business $business): int { $count = 0; $schedules = PreventiveSchedule::where('business_id', $business->id) ->where('is_active', true) ->whereNotNull('next_due_at') ->whereNotNull('assigned_user_id') ->with('assignedUser', 'equipment') ->get(); foreach ($schedules as $schedule) { $daysUntil = now()->diffInDays($schedule->next_due_at, false); if ($daysUntil <= $schedule->reminder_days_before && $schedule->assignedUser) { MaintenanceNotificationService::notify( $business, $schedule->assignedUser, 'preventive_due', 'یادآوری نگهداری پیشگیرانه', "نگهداری «{$schedule->title}» برای تجهیز «{$schedule->equipment?->name}» تا {$daysUntil} روز دیگر سررسید می‌شود.", ['schedule_id' => $schedule->id, 'equipment_id' => $schedule->equipment_id] ); $count++; } } return $count; } }