[Изменено]: столбец Выбыло в статистике #3

This commit is contained in:
brusnitsyn
2026-06-05 16:20:35 +09:00
parent cb046516af
commit 2c82f488a1
4 changed files with 177 additions and 69 deletions

View File

@@ -0,0 +1,115 @@
<?php
namespace App\Services\MetricCalculators;
use App\Contracts\MetricCalculatorInterface;
use App\Models\Department;
use App\Services\Base\BaseMetricService;
use App\Services\DateRange;
use App\Services\DateRangeService;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
class PlanCalculator extends BaseMetricService implements MetricCalculatorInterface
{
public function __construct(
) {
}
public function getMetricId(): int
{
return 7;
}
public function calculate(array $departmentIds, string $startDate, string $endDate): array
{
$startDate = Carbon::parse($startDate);
$endDate = Carbon::parse($endDate);
$startYear = $startDate->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;
}
}