copy()->startOfYear()->setHours(9); $startPreviousMonth = $endDate->copy()->startOfMonth()->setHours(9); $startCurrentMonth = $endDate->copy()->startOfMonth()->setHours(9); $currentMonth = $endDate->month; // Получаем фактические выписки с начала года по прошлый месяц $previousOutcomeMonth = DB::table('report_duties as r') ->join('duty_report_metric_results as mr', 'r.id', '=', 'mr.rf_report_id') ->whereIn('r.rf_department_id', $departmentIds) ->where('mr.rf_metrika_item_id', self::getMetricId()) ->where('r.period_end', '>=', $startYear) // Используем >= ->where('r.period_end', '<', $startPreviousMonth) // Используем < ->select('r.rf_department_id', DB::raw('SUM(CAST(mr.value AS DECIMAL)) as total')) ->groupBy('r.rf_department_id') ->get() ->keyBy('rf_department_id'); // Получаем фактические выписки за текущий месяц $actualCurrentMonth = DB::table('report_duties as r') ->join('duty_report_metric_results as mr', 'r.id', '=', 'mr.rf_report_id') ->whereIn('r.rf_department_id', $departmentIds) ->where('mr.rf_metrika_item_id', self::getMetricId()) ->where('r.period_end', '>', $startCurrentMonth) // Используем >= ->where('r.period_end', '<=', $endDate) ->select('r.rf_department_id', DB::raw('SUM(CAST(mr.value AS DECIMAL)) as total')) ->groupBy('r.rf_department_id') ->get() ->keyBy('rf_department_id'); $results = []; foreach ($departmentIds as $departmentId) { $department = Department::find($departmentId); // Получаем годовой план $annualPlanModel = $department->recipientPlanOfYear(); $annualPlan = $annualPlanModel ? (int) $annualPlanModel->value : 0; // План на 1 месяц (равномерно) $oneMonthPlan = $annualPlan > 0 ? ceil($annualPlan / 12) : 0; // ===== БЕЗОПАСНОЕ ПОЛУЧЕНИЕ ЗНАЧЕНИЙ ===== // Факт за прошлые месяцы (без текущего) $actualToLastMonth = (int) ($previousOutcomeMonth[$departmentId]->total ?? 0); // Факт за текущий месяц (с проверкой существования ключа) $actualCurrent = (int) ($actualCurrentMonth[$departmentId]->total ?? 0); // Общий факт с начала года $actualYearToDate = $actualToLastMonth + $actualCurrent; // ===== 1. План с начала года нарастающим ===== $cumulativePlan = $oneMonthPlan * $currentMonth; // ===== 2. Долг за прошлые месяцы ===== $expectedToLastMonth = $oneMonthPlan * ($currentMonth - 1); $debtFromYearStart = max(0, $expectedToLastMonth - $actualToLastMonth); // ===== 3. Остаток плана на текущий месяц (с безопасной проверкой) ===== $currentMonthPlanOnly = max(0, $oneMonthPlan - $actualCurrent); // ===== 4. ИТОГОВЫЙ ДОЛГ ===== $totalDebt = $currentMonthPlanOnly + $debtFromYearStart; // ===== 5. Процент выполнения плана ===== $cumulativePercent = $cumulativePlan > 0 ? round($actualYearToDate * 100 / $cumulativePlan) : 0; $results[$departmentId] = [ 'year_plan' => $annualPlan, 'month_plan' => $oneMonthPlan, 'total_debt' => $totalDebt, 'current_mouth_dept' => $currentMonthPlanOnly, 'cumulative_plan' => $cumulativePlan, 'debt_from_year' => $debtFromYearStart, 'actual_to_last_month' => $actualToLastMonth, 'outcome_in_current_month' => $actualCurrent, 'actual_year_to_date' => $actualYearToDate, 'cumulative_percent' => $cumulativePercent, ]; } return $results; } }