From b44f9050a01b1a807268113993ccf43e350cd00f Mon Sep 17 00:00:00 2001 From: Vladimir Fomichev Date: Fri, 5 Dec 2025 14:33:11 +0300 Subject: [PATCH] =?utf8?q?=D0=BA=D0=BE=D1=80=D1=80=D0=B5=D0=BA=D1=82=D0=B8?= =?utf8?q?=D1=80=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=B4=D0=BD=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- erp24/api3/core/services/ReportService.php | 95 ++++++++++++++++++---- 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/erp24/api3/core/services/ReportService.php b/erp24/api3/core/services/ReportService.php index 90e8a5c7..06671c7c 100644 --- a/erp24/api3/core/services/ReportService.php +++ b/erp24/api3/core/services/ReportService.php @@ -1392,6 +1392,22 @@ class ReportService /** + * Генерирует отчет по дням за период + * + * Собирает статистику по продажам, сотрудникам, посетителям и другим метрикам + * за каждый день указанного периода. + * + * ВАЖНО: При расчете количества сотрудников на смене учитывается тип смены: + * - shift_type = 1 (дневная): учитываются только сотрудники с shift_id = 1 + * - shift_type = 2 (ночная): учитываются только сотрудники с shift_id = 2 + * - shift_type = 0 (обе смены): учитываются все смены, причем если сотрудник + * работает и в дневную, и в ночную смену, он учитывается как 2 человека (дважды) + * + * @param object $data Параметры запроса: + * - date: дата окончания периода (начало = первое число месяца) + * - stores: массив ID магазинов + * - shift_type: тип смены (0 = обе, 1 = дневная, 2 = ночная) + * @return array Массив отчетов по дням * @throws \yii\base\Exception * @throws Exception */ @@ -1430,18 +1446,39 @@ class ReportService } // Получаем все уникальные admin_id сотрудников за период из фактических смен - $allAdminsInPeriod = TimetableFactModel::find() - ->select(['admin_id']) - ->distinct() + $allAdminsInPeriodQuery = TimetableFactModel::find() ->where(['store_id' => $data->stores]) ->andWhere(['>=', 'date', date("Y-m-01", strtotime($data->date))]) ->andWhere(['<=', 'date', date("Y-m-d", strtotime($data->date))]) - ->andWhere(['>', 'work_time', 0]) - ->asArray() - ->all(); + ->andWhere(['>', 'work_time', 0]); - $adminIdsInPeriod = ArrayHelper::getColumn($allAdminsInPeriod, 'admin_id'); - $employeeCountTotal = count($adminIdsInPeriod); + // Для типа смены 0 (обе смены) считаем каждую смену отдельно + if ($data->shift_type == 0) { + // Для обеих смен нужны все записи смен + $allAdminsInPeriod = $allAdminsInPeriodQuery + ->select(['admin_id', 'shift_id']) + ->asArray() + ->all(); + $employeeCountTotal = count($allAdminsInPeriod); + + // Для карт нужны уникальные admin_id + $adminIdsInPeriod = array_unique(ArrayHelper::getColumn($allAdminsInPeriod, 'admin_id')); + } else { + // Для конкретной смены используем фильтр и distinct + if ($data->shift_type == 1) { + $allAdminsInPeriodQuery->andWhere(['shift_id' => \yii_app\records\Shift::DAY]); + } elseif ($data->shift_type == 2) { + $allAdminsInPeriodQuery->andWhere(['shift_id' => \yii_app\records\Shift::NIGHT]); + } + + $allAdminsInPeriod = $allAdminsInPeriodQuery + ->select(['admin_id']) + ->distinct() + ->asArray() + ->all(); + $adminIdsInPeriod = ArrayHelper::getColumn($allAdminsInPeriod, 'admin_id'); + $employeeCountTotal = count($adminIdsInPeriod); + } $positionMap = $this->buildPositionMap($adminIdsInPeriod); $adminSkillMap = $this->buildAdminSkillMap($adminIdsInPeriod); @@ -1454,14 +1491,35 @@ class ReportService // Получаем сотрудников из фактических смен за день foreach ($data->stores as $store_id) { - $employees = TimetableFactModel::find() - ->select(['admin_id']) - ->distinct() + $employeesQuery = TimetableFactModel::find() ->where(['store_id' => $store_id]) ->andWhere(['date' => $day]) - ->andWhere(['>', 'work_time', 0]) - ->asArray() - ->all(); + ->andWhere(['>', 'work_time', 0]); + + // Фильтрация по типу смены + if ($data->shift_type == 1) { + // Дневная смена + $employeesQuery->andWhere(['shift_id' => \yii_app\records\Shift::DAY]); + } elseif ($data->shift_type == 2) { + // Ночная смена + $employeesQuery->andWhere(['shift_id' => \yii_app\records\Shift::NIGHT]); + } + // Для shift_type == 0 не фильтруем по shift_id + + // Для shift_type == 0 считаем каждую смену отдельно + if ($data->shift_type == 0) { + $employees = $employeesQuery + ->select(['admin_id', 'shift_id']) + ->asArray() + ->all(); + } else { + // Для конкретной смены используем distinct + $employees = $employeesQuery + ->select(['admin_id']) + ->distinct() + ->asArray() + ->all(); + } $employeeCount[$store_id] = count($employees); @@ -1470,7 +1528,14 @@ class ReportService // Добавляем сотрудников этого магазина в общий массив за день foreach ($employees as $employee) { - $allDayEmployees[$employee['admin_id']] = $employee; + if ($data->shift_type == 0) { + // Для обеих смен создаем уникальный ключ с учетом shift_id + $key = $employee['admin_id'] . '_' . $employee['shift_id']; + $allDayEmployees[$key] = $employee; + } else { + // Для одной смены используем только admin_id + $allDayEmployees[$employee['admin_id']] = $employee; + } } } -- 2.39.5