From bb46ebd255ddd22e5a73eb569a9d7e949c435368 Mon Sep 17 00:00:00 2001 From: Vladimir Fomichev Date: Tue, 11 Nov 2025 11:36:28 +0300 Subject: [PATCH] =?utf8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?utf8?q?=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=B7=D0=B8=D1=86=D0=B8=D0=B8=20?= =?utf8?q?=D0=B2=20=D0=B3=D1=80=D0=B5=D0=B9=D0=B4=D0=B0=D1=85=20=D0=B8=20?= =?utf8?q?=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD=D0=B8=D0=B7=D0=B0?= =?utf8?q?=D1=86=D0=B8=D1=8F=20=D1=81=D0=BE=20=D1=81=D1=82=D0=B0=D1=82?= =?utf8?q?=D1=83=D1=81=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- erp24/actions/grade/UpdateAction.php | 32 +++++---- erp24/records/Admin.php | 27 ++++++++ erp24/views/grade/update.php | 98 +++++++++++++++++++++++++--- 3 files changed, 138 insertions(+), 19 deletions(-) diff --git a/erp24/actions/grade/UpdateAction.php b/erp24/actions/grade/UpdateAction.php index 1a742558..abd85ac0 100755 --- a/erp24/actions/grade/UpdateAction.php +++ b/erp24/actions/grade/UpdateAction.php @@ -24,16 +24,20 @@ class UpdateAction extends Action $modelPosition = DynamicModel::validateData(['position_id' => null, 'action' => 'updatePosition'], [['position_id', 'integer'], ['action', 'string']]); if ($modelPosition->load(Yii::$app->request->post()) && $modelPosition->action == 'updatePosition') { - $positionStatus = EmployeePositionStatus::findOne(['admin_id' => $admin_id]); - if (!$positionStatus) { - $positionStatus = new EmployeePositionStatus(); - $positionStatus->admin_id = $admin_id; - $positionStatus->created_at = date('Y-m-d H:i:s'); + // Гибридный подход: обновляем основное поле (источник истины) + $admin->employee_position_id = $modelPosition->position_id; + + // Сохраняем Admin, что автоматически вызовет afterSave + // и создаст запись в EmployeePositionStatus для истории + if ($admin->save(false)) { + Yii::$app->session->setFlash('success', 'Грейд успешно сохранён'); + } else { + Yii::$app->session->setFlash('error', 'Ошибка при сохранении грейда'); } - $positionStatus->position_id = $modelPosition->position_id; - $positionStatus->save(false); + return $this->controller->redirect(['/grade/update', 'admin_id' => $admin_id]); } else { - $modelPosition->position_id = $admin->position ? $admin->position->id : null; + // Показываем текущий грейд из основного поля (источник истины) + $modelPosition->position_id = $admin->employee_position_id; $modelPosition->action = 'updatePosition'; $modelPosition->validate(); } @@ -55,10 +59,16 @@ class UpdateAction extends Action $skills = EmployeeSkill::find()->all(); $skillStatuses = ArrayHelper::map(EmployeeSkillStatus::find()->where(['admin_id' => $admin_id])->all(), 'skill_id', 'created_at'); - $nextPosition = EmployeePosition::findOne(EmployeePosition::findOne($modelPosition->position_id)->next_position_id ?? null) ?? null; + + // Получаем следующую должность на основе текущего грейда + $nextPosition = null; $requiredSkills = []; - if (isset($nextPosition)) { - $requiredSkills = $nextPosition->skills; + $currentPosition = EmployeePosition::findOne($modelPosition->position_id); + if ($currentPosition && $currentPosition->next_position_id) { + $nextPosition = EmployeePosition::findOne($currentPosition->next_position_id); + if ($nextPosition) { + $requiredSkills = $nextPosition->skills; + } } return $this->controller->render('/grade/update', diff --git a/erp24/records/Admin.php b/erp24/records/Admin.php index 65f295a0..157cc931 100755 --- a/erp24/records/Admin.php +++ b/erp24/records/Admin.php @@ -769,6 +769,7 @@ class Admin extends ActiveRecord implements IdentityInterface /** * После сохранения проверяем, изменилась ли должность, и создаем запись EmployeePayment + * А также синхронизируем историю в EmployeePositionStatus (гибридный подход) */ public function afterSave($insert, $changedAttributes) { @@ -779,6 +780,32 @@ class Admin extends ActiveRecord implements IdentityInterface $oldPositionId = $changedAttributes['employee_position_id'] ?? null; $newPositionId = $this->employee_position_id; + // === ГИБРИДНЫЙ ПОДХОД: Ведение истории в EmployeePositionStatus === + if ($newPositionId && $oldPositionId != $newPositionId) { + try { + // Закрыть предыдущую должность, если была + if ($oldPositionId) { + EmployeePositionStatus::updateAll( + ['closed_at' => date('Y-m-d H:i:s')], + ['admin_id' => $this->id, 'closed_at' => null] + ); + } + + // Создать новую запись об истории + $positionStatus = new EmployeePositionStatus(); + $positionStatus->admin_id = $this->id; + $positionStatus->position_id = $newPositionId; + $positionStatus->created_at = date('Y-m-d H:i:s'); + $positionStatus->save(false); + + Yii::info("История грейда обновлена для admin_id={$this->id}, position_id={$newPositionId}", 'grade-sync'); + } catch (\Exception $e) { + Yii::error("Ошибка при обновлении истории EmployeePositionStatus для admin_id={$this->id}: " . $e->getMessage(), 'grade-sync'); + // Не бросаем исключение, чтобы не прервать сохранение Admin + } + } + + // === СИНХРОНИЗАЦИЯ ЗАРПЛАТЫ === // Если должность была добавлена или изменена, и сотрудник не уволен if ($newPositionId && ($oldPositionId != $newPositionId || $insert) && $this->group_id != AdminGroup::GROUP_FIRED) { try { diff --git a/erp24/views/grade/update.php b/erp24/views/grade/update.php index 5f58c7c4..1ed05cae 100755 --- a/erp24/views/grade/update.php +++ b/erp24/views/grade/update.php @@ -33,23 +33,45 @@ use dosamigos\datetimepicker\DateTimePicker;
- Присвоение грейда и скиллов: name ?> +
Присвоение грейда и скиллов: name ?>
+
+
+ + +
+
+
'some_pjax_id']) ?> 'grade-form']); ?> -
-
- Позиция: +
+
+
-
+
+
+
field($modelPosition, 'position_id')->dropDownList( - ArrayHelper::map($positions, 'id', 'name'))->label(false); ?> + ['' => '-- Выберите грейд --'] + ArrayHelper::map($positions, 'id', 'name'), + ['class' => 'form-control'] + )->label(false); ?>
-
- 'btn btn-primary'])?> +
+ 'btn btn-primary'])?>
field($modelPosition, 'action')->hiddenInput()->label(false) ?> @@ -120,6 +142,66 @@ use dosamigos\datetimepicker\DateTimePicker; + +
+
+
📋 История назначений грейда
+
+
+ +where(['admin_id' => $admin->id]) + ->orderBy(['created_at' => SORT_DESC]) + ->with('employeePosition') + ->all(); + +if (!empty($positionHistory)): +?> +
+
+ + + + + + + + + + + + + + + + + +
ДолжностьНачалоОкончание
+ position_id): ?> + position_id)->name ?? 'Должность удалена') ?> + + — + + + formatter->asDatetime($history->created_at, 'php:d.m.Y H:i') ?> + + closed_at): ?> + formatter->asDatetime($history->closed_at, 'php:d.m.Y H:i') ?> + + Активный + +
+
+
+ +
+
+

История назначений грейда отсутствует

+
+
+ +
-- 2.39.5