diff --git a/app/Modules/CRM/Config/Routes.php b/app/Modules/CRM/Config/Routes.php index e39068c..f9283bc 100644 --- a/app/Modules/CRM/Config/Routes.php +++ b/app/Modules/CRM/Config/Routes.php @@ -43,6 +43,7 @@ $routes->group('crm', ['filter' => ['org', 'subscription:crm'], 'namespace' => ' // Stages $routes->get('stages', 'DealsController::stages'); $routes->post('stages', 'DealsController::storeStage'); + $routes->post('stages/reorder', 'DealsController::reorderStages'); $routes->post('stages/(:num)', 'DealsController::updateStage/$1'); $routes->get('stages/(:num)/delete', 'DealsController::destroyStage/$1'); }); diff --git a/app/Modules/CRM/Controllers/DealsController.php b/app/Modules/CRM/Controllers/DealsController.php index b30c132..813ad0d 100644 --- a/app/Modules/CRM/Controllers/DealsController.php +++ b/app/Modules/CRM/Controllers/DealsController.php @@ -494,6 +494,59 @@ class DealsController extends BaseController return redirect()->to('/crm/deals/stages')->with('success', 'Этап удалён'); } + /** + * API: Изменить порядок этапов (drag-n-drop) + * POST /crm/deals/stages/reorder + */ + public function reorderStages() + { + $organizationId = $this->requireActiveOrg(); + + // Получаем массив stages[] из form-urlencoded + $stageOrders = $this->request->getPost('stages'); + + if (empty($stageOrders) || !is_array($stageOrders)) { + return $this->response + ->setHeader('X-CSRF-TOKEN', csrf_hash()) + ->setHeader('X-CSRF-HASH', csrf_token()) + ->setJSON([ + 'success' => false, + 'message' => 'Не передан список этапов', + ])->setStatusCode(422); + } + + // Приводим к int (приходят как строки из form-urlencoded) + $stageOrders = array_map('intval', $stageOrders); + + // Проверяем что все этапы принадлежат организации + foreach ($stageOrders as $stageId) { + $stage = $this->stageService->getStage($stageId); + // Все поля из БД возвращаются как строки, поэтому сравниваем через intval + if (!$stage || intval($stage['organization_id'] ?? 0) !== intval($organizationId)) { + return $this->response + ->setJSON([ + 'success' => false, + 'message' => 'Этап не найден или принадлежит другой организации', + 'debug' => [ + 'stageId' => $stageId, + 'stage' => $stage, + 'organizationId' => $organizationId, + ], + ])->setStatusCode(422); + } + } + + $this->stageService->reorderStages($organizationId, $stageOrders); + + return $this->response + ->setJSON([ + 'success' => true, + 'message' => 'Порядок этапов обновлён', + 'csrf_token' => csrf_hash(), + 'csrf_hash' => csrf_token(), + ]); + } + /** * API: получить контакты клиента */ diff --git a/app/Modules/CRM/Views/deals/stages.twig b/app/Modules/CRM/Views/deals/stages.twig index 1d50500..9dadc65 100644 --- a/app/Modules/CRM/Views/deals/stages.twig +++ b/app/Modules/CRM/Views/deals/stages.twig @@ -6,7 +6,7 @@