From 4eae476d2ffb464b6345197bf59e34466df26a2a Mon Sep 17 00:00:00 2001 From: mac Date: Sun, 21 Jun 2026 11:40:06 +0300 Subject: [PATCH] Add close step in funnel --- ajax/ajax_vue_requisitions.php | 39 +++++++++++++++++++ engine/classes/Requisitions.php | 26 +++++++++++++ js/crm_vue.js | 67 ++++++++++++++++++++++++++++++++- templates/footer.php | 49 ++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 2 deletions(-) diff --git a/ajax/ajax_vue_requisitions.php b/ajax/ajax_vue_requisitions.php index d34d51a..f10f44e 100644 --- a/ajax/ajax_vue_requisitions.php +++ b/ajax/ajax_vue_requisitions.php @@ -2395,4 +2395,43 @@ if($request == 'get_deal_data'){ exit(); } +if($request == 'get_deals_linked_reqs'){ + $req_ids = isset($data->req_ids) ? $data->req_ids : []; + $req_ids = array_map('intval', $req_ids); + $reqs = []; + if (count($req_ids) > 0) { + $ids_str = implode(',', $req_ids); + $sql = "SELECT id, name, deleted, stage FROM requisitions WHERE id IN ($ids_str)"; + $q = $pdo->query($sql); + if($q && $pdo->num_rows($q) > 0){ + while($r = $pdo->fetch_assoc($q)){ + $r['id'] = (int)$r['id']; + $r['deleted'] = (int)$r['deleted']; + $reqs[] = $r; + } + } + } + echo json_encode(['reqs' => $reqs]); + exit(); +} + +if($request == 'get_deals_linked_objects'){ + $object_ids = isset($data->object_ids) ? $data->object_ids : []; + $object_ids = array_map('intval', $object_ids); + $objects = []; + if (count($object_ids) > 0) { + $ids_str = implode(',', $object_ids); + $sql = "SELECT id, nazv, adres FROM objects WHERE id IN ($ids_str)"; + $q = $pdo->query($sql); + if($q && $pdo->num_rows($q) > 0){ + while($r = $pdo->fetch_assoc($q)){ + $r['id'] = (int)$r['id']; + $objects[] = $r; + } + } + } + echo json_encode(['objects' => $objects]); + exit(); +} + ?> diff --git a/engine/classes/Requisitions.php b/engine/classes/Requisitions.php index cc5fcbd..67a7ab7 100644 --- a/engine/classes/Requisitions.php +++ b/engine/classes/Requisitions.php @@ -4858,6 +4858,32 @@ if (!$this->db->query($sql)) $errors[] = $this->db->errorInfo(); + // Обновление статуса сделки при закрытии заявки + if (!empty($requisistion['deal_id']) && $requisistion['deal_id'] > 0) { + $dealId = intval($requisistion['deal_id']); + // Проверяем, есть ли другие заявки в сделке, которые ещё не закрыты + $otherReqsSql = "SELECT COUNT(*) as cnt FROM requisitions WHERE deal_id = $dealId AND deleted = 0 AND id != $id"; + $otherReqsRow = $this->db->fetch_assoc($this->db->query($otherReqsSql)); + $otherReqsOpen = $otherReqsRow['cnt'] > 0; + + if ($is_deal || !$otherReqsOpen) { + // Если сделка (is_deal=true) ИЛИ все заявки закрыты — ставим статус 1 (успешная) + $this->db->query("UPDATE deals SET status = 1 WHERE id = $dealId AND status != 2"); + + // Запись в историю сделки + $userObj = new User; + $userObj->get($user_id); + $comment = "Заявка #$id закрыта."; + if ($is_deal && isset($post['summa'])) { + $comment .= " Совершена сделка на ".$post['summa']." руб."; + } + if (!$otherReqsOpen) { + $comment .= " Все заявки сделки закрыты. Сделка завершена."; + } + $this->db->query("INSERT INTO user_client_events (user_id, req_id, type, name, comment, create_date) VALUES ($user_id, $id, 'deal', 'Закрытие сделки', '".addslashes($comment)."', NOW())"); + } + } + // Удаление фильтра автопоиска $autosearch_instce = $this->autosearch_instce; $autosearch_instce->deleteFilterByReq($id, $user_id); diff --git a/js/crm_vue.js b/js/crm_vue.js index f9b57d3..6c21cb1 100644 --- a/js/crm_vue.js +++ b/js/crm_vue.js @@ -119,7 +119,12 @@ var ac = new Vue({ penthouse: 'Пентхаус', duplex: 'Дуплекс', cottage: 'Коттедж', - } + }, + dealCloseData: null, + dealCloseReqs: [], + dealCloseObjects: [], + dealCloseAgentCommission: 0, + dealCloseSumma: 0, }, methods: { closedStep: function(id, clientId) { @@ -492,6 +497,11 @@ var ac = new Vue({ this.open_step_load = true; ac.pole_dop_close_step = []; this.is_looad = false; + this.dealCloseData = null; + this.dealCloseReqs = []; + this.dealCloseObjects = []; + this.dealCloseAgentCommission = 0; + this.dealCloseSumma = 0; if ($('#client-history__bg').css('display') == 'block') { $('#client-history__bg').css('zIndex', '99988'); } @@ -705,7 +715,60 @@ var ac = new Vue({ }) .catch(function(error) { console.log(error); - }); + }); + + // Загрузка данных сделки для блока закрытия + if (ac.step.is_deal === 1) { + axios.post('/ajax/ajax_vue_requisitions.php', { + request: 'get_deal_by_req', + req_id: ac.reqId, + }) + .then(function(response) { + var res = typeof response.data === 'string' ? JSON.parse(response.data) : response.data; + if (res.deal_id) { + axios.post('/ajax/ajax_vue_requisitions.php', { + request: 'get_deal_data', + deal_id: res.deal_id, + }) + .then(function(dealRes) { + var dealData = dealRes.data.deal; + if (dealData) { + ac.dealCloseData = dealData; + ac.dealCloseAgentCommission = dealData.agent_commission || 0; + ac.dealCloseSumma = dealData.contract_price || 0; + + // Загрузка связанных заявок + var reqIds = []; + if (dealData.side_one_requisition_id) reqIds.push(dealData.side_one_requisition_id); + if (dealData.side_two_requisition_id) reqIds.push(dealData.side_two_requisition_id); + if (reqIds.length > 0) { + axios.post('/ajax/ajax_vue_requisitions.php', { + request: 'get_deals_linked_reqs', + req_ids: reqIds, + }) + .then(function(reqRes) { + ac.dealCloseReqs = reqRes.data.reqs || []; + }); + } + + // Загрузка связанных объектов + var objIds = []; + if (dealData.side_one_object_id) objIds.push(dealData.side_one_object_id); + if (dealData.side_two_object_id) objIds.push(dealData.side_two_object_id); + if (objIds.length > 0) { + axios.post('/ajax/ajax_vue_requisitions.php', { + request: 'get_deals_linked_objects', + object_ids: objIds, + }) + .then(function(objRes) { + ac.dealCloseObjects = objRes.data.objects || []; + }); + } + } + }); + } + }); + } }, IsJsonString(str) { diff --git a/templates/footer.php b/templates/footer.php index bbd3ff4..5749087 100644 --- a/templates/footer.php +++ b/templates/footer.php @@ -5400,6 +5400,55 @@ $user_id = $_SESSION['id']; + + +
+
Информация о сделке
+
+
+ Название: {{ dealCloseData.title }} +
+ + +
+ Связанные заявки: +
+ {{ req.name }} + ✓ закрыта + открыта +
+
+ + +
+ Связанные объекты: +
+ {{ obj.nazv }} + {{ obj.adres }} +
+
+ + +
+
Фактические данные
+
+
Комиссия агента (руб.)
+
+ +
+
+
+
Сумма сделки (руб.)
+
+ +
+
+
+
+
Загрузка данных сделки...
+
+ +