Initial backup

This commit is contained in:
Tesscorp
2026-07-15 19:58:30 -06:00
commit 6a5404819c
16 changed files with 8449 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
node_modules/
dist/
.env
*.zip
*.tar.gz
*.bak
+1
Submodule Trimape-backend added at 31ce688b3c
@@ -0,0 +1,3 @@
ALTER TABLE hr_person
ADD COLUMN position VARCHAR(150) NULL AFTER email,
ADD COLUMN signature_data MEDIUMTEXT NULL AFTER position;
+100
View File
@@ -0,0 +1,100 @@
-- 1. Eliminar tablas antiguas (El respaldo ya está hecho)
DROP TABLE IF EXISTS surveys_answers;
DROP TABLE IF EXISTS surveys_questions;
DROP TABLE IF EXISTS surveys;
-- 2. Crear tabla de configuracion de encuestas
CREATE TABLE surveys_questions (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
question VARCHAR(255) DEFAULT NULL,
levels INT DEFAULT 5,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
-- 3. Crear tabla de respuestas Historicas
CREATE TABLE surveys_answers (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
context_id INT DEFAULT NULL,
id_user INT DEFAULT NULL,
rh_name VARCHAR(255) DEFAULT NULL,
snapshot_json JSON DEFAULT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
-- 4. Reemplazar Stored Procedure: sp_upsert_survey
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_upsert_survey$$
CREATE PROCEDURE sp_upsert_survey(
IN p_id INT,
IN p_surveyType VARCHAR(255),
IN p_title VARCHAR(255),
IN p_checkboxes TEXT,
IN p_openQuestions TEXT,
IN p_ranges JSON
)
BEGIN
-- Limpiamos las preguntas actuales de forma definitiva
TRUNCATE TABLE surveys_questions;
-- Insertamos las nuevas preguntas iterando sobre el JSON p_ranges
-- El JSON tiene la forma: [{"question": "Pregunta 1", "levels": 5}, ...]
IF p_ranges IS NOT NULL THEN
INSERT INTO surveys_questions (question, levels)
SELECT
JSON_UNQUOTE(JSON_EXTRACT(value, '$.question')),
JSON_UNQUOTE(JSON_EXTRACT(value, '$.levels'))
FROM JSON_TABLE(p_ranges, '$[*]' COLUMNS (value JSON PATH '$')) AS jt;
END IF;
SELECT 1 AS success, 'Encuesta actualizada correctamente' AS message;
END$$
DELIMITER ;
-- 5. Reemplazar Stored Procedure: sp_get_all_surveys
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_get_all_surveys$$
CREATE PROCEDURE sp_get_all_surveys()
BEGIN
-- Forzamos la estructura que Vue espera en el frontend:
-- [{ id: 1, docType: 'SERVICE_ORDER', name: 'Encuesta', questions: '[...]' }]
-- En este caso los IDs no importan, agrupamos todo en un único objeto "Virtual".
SELECT
1 AS id,
'Encuesta de Satisfacción' AS title,
'SERVICE_ORDER' AS surveyType,
IFNULL(
(
SELECT JSON_ARRAYAGG(
JSON_OBJECT(
'id', id,
'typeQuestion', 'ranges',
'question', question,
'levels', levels
)
)
FROM surveys_questions
),
'[]'
) AS questions;
END$$
DELIMITER ;
-- 6. Reemplazar Stored Procedure: sp_save_survey_answers
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_save_survey_answers$$
CREATE PROCEDURE sp_save_survey_answers(
IN p_surveyId INT,
IN p_rhName VARCHAR(255),
IN p_answers_json JSON
)
BEGIN
-- P_answers_json debe contener la "fotografia" cruda enviada desde frontend
INSERT INTO surveys_answers (context_id, rh_name, snapshot_json)
VALUES (p_surveyId, p_rhName, p_answers_json);
SELECT 1 AS success;
END$$
DELIMITER ;
@@ -0,0 +1,16 @@
CREATE OR REPLACE VIEW engineer_ratings_view AS
SELECT
s.engineer_name,
s.id_user,
COUNT(DISTINCT s.id) AS total_surveys,
ROUND(AVG( (jt.answer / jt.levels) * 5 ), 2) AS average_rating
FROM surveys_answers s
JOIN JSON_TABLE(
s.snapshot_json,
'$[*]' COLUMNS (
answer DECIMAL(5,2) PATH '$.answer',
levels DECIMAL(5,2) PATH '$.levels'
)
) jt ON s.snapshot_json IS NOT NULL
WHERE s.id_user IS NOT NULL
GROUP BY s.id_user, s.engineer_name;
+26
View File
@@ -0,0 +1,26 @@
DELIMITER //
DROP PROCEDURE IF EXISTS sp_get_surveys_by_user;
//
CREATE PROCEDURE sp_get_surveys_by_user(IN p_id_user INT)
BEGIN
SELECT
s.*,
ROUND(
(
SELECT AVG((jt.answer / jt.levels) * 5)
FROM JSON_TABLE(
s.snapshot_json,
'$[*]' COLUMNS (
answer DECIMAL(5,2) PATH '$.answer',
levels DECIMAL(5,2) PATH '$.levels'
)
) jt
), 2
) AS average_rating
FROM surveys_answers s
WHERE s.id_user = p_id_user;
END //
DELIMITER ;
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_save_survey_answers$$
CREATE PROCEDURE sp_save_survey_answers(
IN p_surveyId INT,
IN p_idUser INT,
IN p_engineerName VARCHAR(255),
IN p_rhName VARCHAR(255),
IN p_answers_json JSON
)
BEGIN
INSERT INTO surveys_answers (context_id, id_user, engineer_name, rh_name, snapshot_json)
VALUES (p_surveyId, p_idUser, p_engineerName, p_rhName, p_answers_json);
SELECT 1 AS success;
END$$
DELIMITER ;
@@ -0,0 +1,16 @@
DELIMITER $$
DROP PROCEDURE IF EXISTS sp_save_survey_answers$$
CREATE PROCEDURE sp_save_survey_answers(
IN p_surveyId VARCHAR(50),
IN p_idUser INT,
IN p_engineerName VARCHAR(255),
IN p_rhName VARCHAR(255),
IN p_answers_json JSON
)
BEGIN
INSERT INTO surveys_answers (context_id, id_user, engineer_name, rh_name, snapshot_json)
VALUES (p_surveyId, p_idUser, p_engineerName, p_rhName, p_answers_json);
SELECT 1 AS success;
END$$
DELIMITER ;
+28
View File
@@ -0,0 +1,28 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Domain Default page</title>
<meta name="copyright" content="Copyright 1999-2025. WebPros International GmbH. All rights reserved.">
<script src="https://assets.plesk.com/static/default-website-content/public/default-website-index.js"></script>
</head>
<body>
<h2>What is Plesk</h2>
<p>
Plesk is a <a href="https://www.plesk.com">hosting panel</a> with simple and secure web server, website and web apps management tools. It is specially designed to help web professionals manage web, DNS, mail and other services through a comprehensive and user-friendly GUI. Plesk is about intelligently managing servers, apps, websites and hosting businesses, on both traditional and cloud hosting.
</p>
<p>
<a href="https://docs.plesk.com/try-plesk-now/">Try Plesk Now!</a>
</p>
<ul>
<li><a href="https://docs.plesk.com/en-US/obsidian/">Plesk Guides</a></li>
<li><a href="https://support.plesk.com/hc/en-us">Knowledge Base</a></li>
<li><a href="https://talk.plesk.com/">Forum</a></li>
<li><a href="https://www.plesk.com/blog/">Blog</a></li>
<li><a href="https://www.youtube.com/channel/UCeU-_6YHGQFcVSHLbEXLNlA/playlists">Video Guides</a></li>
<li><a href="https://www.facebook.com/Plesk">Facebook</a></li>
</ul>
<p>Do you host WordPress sites outside of Plesk? Try <a href="https://wpguardian.io/">WP Guardian</a> - it provides complete visibility into the health of your WordPress websites in one place and keeps them protected with flexible updates management</p>
</body>
</html>
+224
View File
@@ -0,0 +1,224 @@
{
"name": "api",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"multer": "^1.4.5-lts.1"
}
},
"node_modules/append-field": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
"license": "MIT"
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"license": "MIT"
},
"node_modules/busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
"dependencies": {
"streamsearch": "^1.1.0"
},
"engines": {
"node": ">=10.16.0"
}
},
"node_modules/concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"engines": [
"node >= 0.8"
],
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"license": "MIT",
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/multer": {
"version": "1.4.5-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
"integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
"license": "MIT",
"dependencies": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.4",
"object-assign": "^4.1.1",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"license": "MIT"
},
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"license": "MIT"
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"license": "MIT",
"engines": {
"node": ">=0.4"
}
}
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"dependencies": {
"multer": "^1.4.5-lts.1"
}
}
+184
View File
@@ -0,0 +1,184 @@
DELIMITER $$
DROP PROCEDURE IF EXISTS `sp_upsert_vehicle_movement_data`$$
CREATE DEFINER=`trimape_admin`@`%` PROCEDURE `sp_upsert_vehicle_movement_data`(
IN `p_movement_id` INT,
IN `p_event_type` VARCHAR(20),
IN `p_checks_snapshot_json` JSON,
IN `p_contract_ref` VARCHAR(100),
IN `p_time_out` TIME,
IN `p_time_in` TIME,
IN `p_observations` TEXT,
IN `p_route_summary` TEXT,
IN `p_authorized_drivers_json` LONGTEXT,
IN `p_user_id` INT
)
BEGIN
DECLARE v_item_id INT;
DECLARE v_engineer_id INT;
DECLARE v_item_type VARCHAR(50);
DECLARE v_prev_drivers LONGTEXT;
DECLARE v_prev_contract VARCHAR(100);
-- ===============================
-- Validaciones básicas
-- ===============================
IF p_movement_id IS NULL OR p_movement_id <= 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'movement_id inválido';
END IF;
IF p_checks_snapshot_json IS NULL OR JSON_VALID(p_checks_snapshot_json) = 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'checks_snapshot_json es requerido y debe ser JSON válido';
END IF;
IF p_event_type NOT IN ('SALIDA','DEVOLUCION') THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'event_type inválido';
END IF;
-- ELIMINADA: Validación estricta de contrato en SALIDA
-- A partir de ahora es opcional.
-- Drivers solo pueden venir en SALIDA
IF p_event_type = 'SALIDA' THEN
IF p_authorized_drivers_json IS NOT NULL AND JSON_VALID(p_authorized_drivers_json) = 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'authorized_drivers_json debe ser JSON válido';
END IF;
END IF;
-- ===============================
-- Resolver movimiento → vehículo
-- ===============================
SELECT m.item_id, m.engineer_id, i.type
INTO v_item_id, v_engineer_id, v_item_type
FROM inventory_movements m
JOIN inventory_items i ON i.id = m.item_id
WHERE m.id = p_movement_id
LIMIT 1;
IF v_item_id IS NULL THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Movimiento no existe';
END IF;
IF v_item_type <> 'vehículo' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Este movimiento no corresponde a un vehículo';
END IF;
-- ===============================
-- Resolver heredados en DEVOLUCION
-- ===============================
SET v_prev_drivers = NULL;
SET v_prev_contract = NULL;
IF p_event_type = 'DEVOLUCION' THEN
-- Heredar drivers de la última SALIDA del mismo vehículo
SELECT vmd.authorized_drivers_json
INTO v_prev_drivers
FROM vehicle_movement_data vmd
WHERE vmd.inventory_item_id = v_item_id
AND vmd.event_type = 'SALIDA'
AND vmd.authorized_drivers_json IS NOT NULL
ORDER BY vmd.created_at DESC
LIMIT 1;
-- Heredar contrato de la última SALIDA del mismo vehículo (ya no validamos que no sea N/A)
SELECT vmd.contract_ref
INTO v_prev_contract
FROM vehicle_movement_data vmd
WHERE vmd.inventory_item_id = v_item_id
AND vmd.event_type = 'SALIDA'
ORDER BY vmd.created_at DESC
LIMIT 1;
-- Si no hay SALIDA previa, fallar
IF v_prev_contract IS NULL AND NOT EXISTS (
SELECT 1 FROM vehicle_movement_data
WHERE inventory_item_id = v_item_id AND event_type = 'SALIDA'
) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No existe salida previa para esta DEVOLUCION';
END IF;
END IF;
-- ===============================
-- Bitácora (histórico)
-- ===============================
INSERT INTO vehicle_movement_data (
movement_id,
inventory_item_id,
engineer_id,
event_type,
checks_snapshot_json,
contract_ref,
time_out,
time_in,
observations,
route_summary,
authorized_drivers_json,
created_by
)
VALUES (
p_movement_id,
v_item_id,
v_engineer_id,
p_event_type,
p_checks_snapshot_json,
CASE
WHEN p_event_type = 'SALIDA' THEN p_contract_ref
ELSE v_prev_contract
END,
p_time_out,
p_time_in,
p_observations,
p_route_summary,
CASE
WHEN p_event_type = 'SALIDA' THEN p_authorized_drivers_json
ELSE v_prev_drivers
END,
p_user_id
)
ON DUPLICATE KEY UPDATE
event_type = VALUES(event_type),
checks_snapshot_json = VALUES(checks_snapshot_json),
contract_ref = VALUES(contract_ref),
time_out = VALUES(time_out),
time_in = VALUES(time_in),
observations = VALUES(observations),
route_summary = VALUES(route_summary),
authorized_drivers_json = VALUES(authorized_drivers_json),
updated_at = CURRENT_TIMESTAMP;
-- ===============================
-- Estado vivo del vehículo (SIN contract_ref)
-- ===============================
INSERT INTO vehicle_state (
inventory_item_id,
checks_json,
notes,
updated_by
)
VALUES (
v_item_id,
p_checks_snapshot_json,
p_observations,
p_user_id
)
ON DUPLICATE KEY UPDATE
checks_json = VALUES(checks_json),
notes = VALUES(notes),
updated_by = VALUES(updated_by),
updated_at = CURRENT_TIMESTAMP;
SELECT p_movement_id AS movement_id;
END$$
DELIMITER ;