From: Vladimir Fomichev Date: Mon, 1 Dec 2025 06:39:49 +0000 (+0300) Subject: Оптимизация установки грейда X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=f2c51520e232a29d69b884a446d46e26d69eb9d3;p=erp24_rep%2Fyii-erp24%2F.git Оптимизация установки грейда --- diff --git a/erp24/actions/grade/AdminUpdateAction.php b/erp24/actions/grade/AdminUpdateAction.php index c086b25b..ed715243 100644 --- a/erp24/actions/grade/AdminUpdateAction.php +++ b/erp24/actions/grade/AdminUpdateAction.php @@ -20,9 +20,9 @@ class AdminUpdateAction extends Action /** * Обновляет данные администратора, включая назначение должности и группы * - * Для рабочих групп (group_id = 50 и все группы с parent_id = 50) при заполнении - * employee_position_id заполняет group_name значением из AdminGroup->name. - * Для остальных групп использует текстовое поле custom_position. + * Для специальных групп работников (флористы, администраторы, подработчики) + * устанавливает group_name из AdminGroup->name и сохраняет employee_position_id. + * Для остальных групп очищает employee_position_id и использует текстовое поле custom_position. * * @param int $id ID администратора * @return string|\yii\web\Response Отрендеренный вид или редирект @@ -32,6 +32,10 @@ class AdminUpdateAction extends Action return "Нет доступа"; } $model = Admin::findOne($id); + + // Определяем специальные группы работников (используется в POST обработке и при рендеринге) + $workersGroup = AdminGroup::getWorkersGroups(); + if (Yii::$app->user->can("updateAdminSettings", ['id' => $model->id])) { if (Yii::$app->request->isPost) { $attributes = Yii::$app->request->post()['Admin']; @@ -53,10 +57,15 @@ class AdminUpdateAction extends Action $attributes['store_arr_guid'] = empty($attributes['storeGuidArray']) ? '' : implode(',', $attributes['storeGuidArray']); unset($attributes['storeGuidArray']); - // Сохраняем флаг, можно ли изменять group_id вручную + // Проверяем права на изменение group_id $originalGroupId = $attributes['group_id'] ?? $model->group_id; $canChangeGroupId = Yii::$app->user->can("updateAdminSettingsGroupId", ['group_id' => $originalGroupId]); + // Если нет прав на изменение group_id - используем текущий group_id из модели + if (!$canChangeGroupId) { + $attributes['group_id'] = $model->group_id; + } + if (!Yii::$app->user->can("updateAdminSettingsOnlyByHrAndAdministrator")) { unset($attributes['store_dostup_all']); unset($attributes['store_id']); @@ -92,138 +101,30 @@ class AdminUpdateAction extends Action Yii::$app->cache->set("dirtyAuthSettings", true); } - // Определяем специальные группы с parent_id = 50 - $specialGroups = [ - AdminGroup::GROUP_FLORIST_DAY, // 30 - AdminGroup::GROUP_FLORIST_NIGHT, // 35 - AdminGroup::GROUP_FLORIST_SUPPORT_DAY, // 40 - AdminGroup::GROUP_WORKERS, // 45 - AdminGroup::GROUP_ADMINISTRATORS, // 50 - AdminGroup::GROUP_FLORIST_SUPPORT_NIGHT, // 72 - ]; - - // Ищем группу "Работники магазинов" по имени - $workersGroup = AdminGroup::find()->where(['name' => AdminGroup::GROUP_STORE_WORKERS_NAME])->one(); - if ($workersGroup) { - $specialGroups[] = $workersGroup->id; - } - - // Определяем рабочие группы: group_id = 50 и все группы с parent_id = 50 - $workGroups = [AdminGroup::GROUP_ADMINISTRATORS]; // 50 - $childGroups = AdminGroup::find()->where(['parent_id' => AdminGroup::GROUP_ADMINISTRATORS])->all(); - foreach ($childGroups as $childGroup) { - $workGroups[] = $childGroup->id; - } - - $isSpecialGroup = in_array((int)$attributes['group_id'], $specialGroups); - $isWorkGroup = in_array((int)$attributes['group_id'], $workGroups); - - // Сохраняем старое значение employee_position_id для проверки изменения - $oldPositionId = $model->employee_position_id; - $oldGroupId = $model->group_id; + // Получаем группу один раз для всех последующих операций + $currentGroup = AdminGroup::findOne($attributes['group_id']); + $isSpecialGroup = in_array((int)$attributes['group_id'], $workersGroup); - // При смене группы проставляем group_name из AdminGroup->name на основе group_id - if (isset($attributes['group_id']) && $oldGroupId != (int)$attributes['group_id']) { - $newAdminGroup = AdminGroup::findOne($attributes['group_id']); - if ($newAdminGroup) { - $attributes['group_name'] = $newAdminGroup->name; - } + // Устанавливаем group_name из AdminGroup->name + if ($currentGroup) { + $attributes['group_name'] = $currentGroup->name; + } else if (isset($attributes['custom_position'])) { + // Если группа не найдена, используем текстовое поле как fallback + $attributes['group_name'] = $attributes['custom_position']; } + // Обработка специфичных полей в зависимости от типа группы if ($isSpecialGroup) { - if ($isWorkGroup) { - // Для рабочих групп (group_id = 50 и parent_id = 50) при заполнении employee_position_id - // заполняем group_name значением из AdminGroup->name - if (!empty($attributes['employee_position_id'])) { - $adminGroup = AdminGroup::findOne($attributes['group_id']); - if ($adminGroup) { - $attributes['group_name'] = $adminGroup->name; - } - } - } else { - // Для остальных специальных групп синхронизируем группу с грейдом - if (!empty($attributes['employee_position_id'])) { - $employeePosition = EmployeePosition::findOne($attributes['employee_position_id']); - if ($employeePosition) { - $positionName = trim($employeePosition->name); - $currentGroup = AdminGroup::findOne($attributes['group_id']); - $currentGroupName = $currentGroup ? trim($currentGroup->name) : ''; - - // Проверяем частичное совпадение группы и грейда - $hasPartialMatch = false; - if ($currentGroupName) { - // Нормализуем названия для сравнения (убираем "день", "ночь" и лишние пробелы) - $normalizedGroupName = mb_strtolower(preg_replace('/\s*(день|ночь)\s*/iu', '', $currentGroupName)); - $normalizedPositionName = mb_strtolower($positionName); - - // Проверяем частичное совпадение - if (mb_strpos($normalizedGroupName, $normalizedPositionName) !== false || - mb_strpos($normalizedPositionName, $normalizedGroupName) !== false) { - $hasPartialMatch = true; - } - } - - // При назначении грейда проставляем group_name из AdminGroup->name на основе group_id - if ($currentGroup) { - $attributes['group_name'] = $currentGroup->name; - } - - if (!$hasPartialMatch) { - // Если не совпадают - ищем группу по названию грейда - $matchingGroup = self::findGroupByPositionName($positionName, $attributes['group_id']); - - if ($matchingGroup) { - // Найдена группа - меняем группу (только если есть права или группа не менялась вручную) - if ($canChangeGroupId || $originalGroupId == $oldGroupId) { - $attributes['group_id'] = $matchingGroup->id; - $attributes['group_name'] = $matchingGroup->name; - - if ($oldGroupId != $matchingGroup->id) { - Yii::$app->session->setFlash('info', - "Группа изменена с '{$currentGroupName}' на '{$matchingGroup->name}' в соответствии с грейдом '{$positionName}'" - ); - } - } else { - // Нет прав на изменение группы - group_name уже установлен из текущей группы выше - Yii::$app->session->setFlash('warning', - "Грейд '{$positionName}' не соответствует группе '{$currentGroupName}'. Недостаточно прав для автоматического изменения группы." - ); - } - } else { - // Группа не найдена - group_name уже установлен из текущей группы выше - if ($oldGroupId != $attributes['group_id']) { - Yii::$app->session->setFlash('warning', - "Группа для грейда '{$positionName}' не найдена. Текущая группа сохранена." - ); - } - } - } - } - } - } - - // Очищаем shift + // Для специальных групп работников сохраняем employee_position_id unset($attributes['shift']); } else { - // Для остальных групп group_name берем из AdminGroup->name на основе group_id - $adminGroup = AdminGroup::findOne($attributes['group_id']); - if ($adminGroup) { - $attributes['group_name'] = $adminGroup->name; - } else if (isset($attributes['custom_position'])) { - // Если группа не найдена, используем текстовое поле как fallback - $attributes['group_name'] = $attributes['custom_position']; - } - unset($attributes['custom_position']); - // Очищаем employee_position_id и shift для не-специальных групп + // Для остальных групп очищаем employee_position_id $attributes['employee_position_id'] = null; unset($attributes['shift']); } - - // Проверяем права на изменение group_id после всех автоматических изменений - if (!$canChangeGroupId) { - // Если нет прав - убираем group_id из атрибутов, чтобы не изменить его - unset($attributes['group_id']); - } + + // Очищаем custom_position в любом случае + unset($attributes['custom_position']); $model->setAttributes($attributes, false); @@ -304,113 +205,7 @@ class AdminUpdateAction extends Action $companies = ArrayHelper::map(Companies::find()->all(), 'id', 'name'); return $this->controller->render('admin-update', compact('model', 'adminGroups', 'admins', - 'cityStores', 'adminHistoryCategories', 'companies', 'positions')); + 'cityStores', 'adminHistoryCategories', 'companies', 'positions', 'workersGroup')); } - /** - * Поиск группы администраторов по названию грейда (должности) - * - * @param string $positionName Название грейда - * @param int|null $currentGroupId ID текущей группы (для приоритета) - * @return AdminGroup|null Найденная группа или null - */ - private static function findGroupByPositionName($positionName, $currentGroupId = null) { - $normalizedPositionName = mb_strtolower(trim($positionName)); - $exactMatches = []; // Точные совпадения (после нормализации) - $containsMatches = []; // Группы, содержащие полное название грейда - $partialMatches = []; // Частичные совпадения - - // Ищем все группы, соответствующие грейду - $groups = AdminGroup::find()->all(); - - foreach ($groups as $group) { - $groupName = mb_strtolower(trim($group->name)); - $normalizedGroupName = preg_replace('/\s*(день|ночь)\s*/iu', '', $groupName); - - // 1. Проверяем точное совпадение после нормализации - if ($normalizedGroupName === $normalizedPositionName) { - $exactMatches[] = $group; - continue; - } - - // 2. Проверяем, содержит ли группа полное название грейда (более специфичное совпадение) - if (mb_strpos($normalizedGroupName, $normalizedPositionName) === 0 || - mb_strpos($normalizedGroupName, ' ' . $normalizedPositionName) !== false || - mb_strpos($normalizedGroupName, $normalizedPositionName . ' ') !== false) { - $containsMatches[] = $group; - continue; - } - - // 3. Проверяем обратное - содержит ли грейд название группы (менее специфичное) - if (mb_strpos($normalizedPositionName, $normalizedGroupName) !== false) { - $partialMatches[] = $group; - } - } - - // Приоритет выбора: - // 1. Точные совпадения - if (!empty($exactMatches)) { - // Если текущая группа в точных совпадениях - оставляем её - if ($currentGroupId) { - foreach ($exactMatches as $group) { - if ($group->id == $currentGroupId) { - return $group; - } - } - } - // Ищем базовую группу без "день"/"ночь" среди точных совпадений - foreach ($exactMatches as $group) { - $groupName = mb_strtolower(trim($group->name)); - if (mb_stripos($groupName, 'день') === false && mb_stripos($groupName, 'ночь') === false) { - return $group; - } - } - // Если все с "день"/"ночь" - возвращаем первую - return $exactMatches[0]; - } - - // 2. Группы, содержащие полное название грейда (более специфичные) - if (!empty($containsMatches)) { - // Если текущая группа в списке - оставляем её - if ($currentGroupId) { - foreach ($containsMatches as $group) { - if ($group->id == $currentGroupId) { - return $group; - } - } - } - // Ищем базовую группу без "день"/"ночь" - foreach ($containsMatches as $group) { - $groupName = mb_strtolower(trim($group->name)); - if (mb_stripos($groupName, 'день') === false && mb_stripos($groupName, 'ночь') === false) { - return $group; - } - } - // Если все с "день"/"ночь" - возвращаем первую - return $containsMatches[0]; - } - - // 3. Частичные совпадения (менее приоритетные) - if (!empty($partialMatches)) { - // Если текущая группа в списке - оставляем её - if ($currentGroupId) { - foreach ($partialMatches as $group) { - if ($group->id == $currentGroupId) { - return $group; - } - } - } - // Ищем базовую группу без "день"/"ночь" - foreach ($partialMatches as $group) { - $groupName = mb_strtolower(trim($group->name)); - if (mb_stripos($groupName, 'день') === false && mb_stripos($groupName, 'ночь') === false) { - return $group; - } - } - // Если все с "день"/"ночь" - возвращаем первую - return $partialMatches[0]; - } - - return null; - } } diff --git a/erp24/records/AdminGroup.php b/erp24/records/AdminGroup.php index f5f1a3cb..f713c5ad 100755 --- a/erp24/records/AdminGroup.php +++ b/erp24/records/AdminGroup.php @@ -39,7 +39,22 @@ class AdminGroup extends ActiveRecord const GROUP_IT = 81; const GROUP_FINANCE_DIRECTOR = 9; - const GROUP_STORE_WORKERS_NAME = 'Работники магазинов'; + /** + * Возвращает список специальных групп работников (нужно для JS и логики грейдов) + * @return int[] + */ + public static function getWorkersGroups(): array + { + return [ + self::GROUP_FLORIST_DAY, // 30 + self::GROUP_FLORIST_NIGHT, // 35 + self::GROUP_FLORIST_SUPPORT_DAY, // 40 + self::GROUP_WORKERS, // 45 + self::GROUP_ADMINISTRATORS, // 50 + self::GROUP_FLORIST_SUPPORT_NIGHT, // 72 + self::GROUP_FLORIST, // 89 + ]; + } public static function getGroupsForEmployeeController() { return [ diff --git a/erp24/views/grade/admin-update.php b/erp24/views/grade/admin-update.php index 1d62b02a..eccb345a 100644 --- a/erp24/views/grade/admin-update.php +++ b/erp24/views/grade/admin-update.php @@ -21,17 +21,7 @@ use yii_app\services\FileService; /** @var array $adminHistoryCategories */ /** @var array $companies */ /** @var EmployeePosition[] $positions */ - -// Определяем специальные группы с parent_id = 50 (нужно для JS) -$specialGroups = [ - AdminGroup::GROUP_FLORIST_DAY, // 30 - AdminGroup::GROUP_FLORIST_NIGHT, // 35 - AdminGroup::GROUP_FLORIST_SUPPORT_DAY, // 40 - AdminGroup::GROUP_WORKERS, // 45 - AdminGroup::GROUP_ADMINISTRATORS, // 50 - AdminGroup::GROUP_FLORIST_SUPPORT_NIGHT, // 72 - AdminGroup::GROUP_FLORIST, // 89 -]; +/** @var array $workersGroup */ // Подключаем CSS и JS файлы $this->registerCssFile('/css/grade/admin-update.css'); @@ -40,7 +30,7 @@ $this->registerJsFile('/js/grade/admin-update.js', ['position' => View::POS_END, // Передаем PHP переменные в JavaScript $this->registerJs(" window.gradeAdminUpdateData = { - specialGroups: " . json_encode($specialGroups, JSON_NUMERIC_CHECK) . ", + specialGroups: " . json_encode($workersGroup, JSON_NUMERIC_CHECK) . ", adminGroups: " . json_encode($adminGroups ?? [], JSON_UNESCAPED_UNICODE) . ", positionsData: " . json_encode(ArrayHelper::map($positions ?? [], 'id', 'name'), JSON_UNESCAPED_UNICODE) . ", groupsData: " . json_encode($adminGroups ?? [], JSON_UNESCAPED_UNICODE) . " @@ -78,7 +68,7 @@ $this->registerJs(" ?> group_id, $specialGroups); + $isSpecialGroup = in_array((int)$model->group_id, $workersGroup); ?>