actualizar viaje padre

This commit is contained in:
abiandev 2026-04-13 11:27:30 +02:00
parent 5385841a62
commit e56ff9e2c8
3 changed files with 165 additions and 6 deletions

View File

@ -476,6 +476,60 @@ const logTripIncidenceAudit = ({ tripId, userId, result, emailStatus, errorCode
}); });
}; };
const normalizeParentTripId = (value) => {
const parsed = Number.parseInt(value, 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
};
const propagateTripStatusToParentTrips = async (
queryExecutor,
{ initialParentTripId, statusId, userId, requestId, flow }
) => {
let parentTripId = normalizeParentTripId(initialParentTripId);
const visitedParentTripIds = new Set();
const updatedParentTripIds = [];
while (parentTripId !== null) {
if (visitedParentTripIds.has(parentTripId)) {
throw new Error(`Detected c_viajes parent cycle at id_viaje ${parentTripId}`);
}
visitedParentTripIds.add(parentTripId);
const [updateParentTripResult] = await queryExecutor.query(
`UPDATE c_viajes
SET id_estado = ?,
ind_edi_app = 1,
fecha_ultima_edicion = NOW(),
id_usuarios_ultima_edicion = ?
WHERE id_viaje = ?`,
[statusId, userId, parentTripId]
);
updatedParentTripIds.push(parentTripId);
appendTripStatusDebugLog({
stage: 'trip_status:parent_trip_updated',
request_id: requestId || null,
flow: flow || null,
parent_trip_id: parentTripId,
id_estado: statusId,
affected_rows: updateParentTripResult?.affectedRows ?? null
});
const [parentTripRows] = await queryExecutor.query(
`SELECT id_viaje_padre
FROM c_viajes
WHERE id_viaje = ?
LIMIT 1`,
[parentTripId]
);
parentTripId = normalizeParentTripId(parentTripRows[0]?.id_viaje_padre);
}
return updatedParentTripIds;
};
const startTrip = async (req, res) => { const startTrip = async (req, res) => {
const dni = req.user?.dni; const dni = req.user?.dni;
const userId = req.user?.id || null; const userId = req.user?.id || null;
@ -509,7 +563,7 @@ const startTrip = async (req, res) => {
); );
const [tripRows] = await connection.query( const [tripRows] = await connection.query(
`SELECT id_viaje, cod_viaje, id_estado `SELECT id_viaje, cod_viaje, id_estado, id_viaje_padre
FROM c_viajes FROM c_viajes
WHERE id_viaje = ? WHERE id_viaje = ?
LIMIT 1 LIMIT 1
@ -591,12 +645,20 @@ const startTrip = async (req, res) => {
await connection.query( await connection.query(
`UPDATE c_viajes `UPDATE c_viajes
SET id_estado = ?, SET id_estado = ?,
ind_edi_app = 1,
fecha_inicio_real = ?, fecha_inicio_real = ?,
fecha_ultima_edicion = NOW(), fecha_ultima_edicion = NOW(),
id_usuarios_ultima_edicion = ? id_usuarios_ultima_edicion = ?
WHERE id_viaje = ?`, WHERE id_viaje = ?`,
[START_TRIP_TARGET_STATE, now, userId, tripId] [START_TRIP_TARGET_STATE, now, userId, tripId]
); );
await propagateTripStatusToParentTrips(connection, {
initialParentTripId: tripRows[0].id_viaje_padre,
statusId: START_TRIP_TARGET_STATE,
userId,
requestId,
flow: 'start_trip'
});
const [insertStartStatusResult] = await connection.query( const [insertStartStatusResult] = await connection.query(
`INSERT INTO c_cambios_estado `INSERT INTO c_cambios_estado
@ -1358,7 +1420,7 @@ const updateTripStatus = async (req, res) => {
await connection.beginTransaction(); await connection.beginTransaction();
const [tripRows] = await connection.query( const [tripRows] = await connection.query(
`SELECT id_viaje, id_estado `SELECT id_viaje, id_estado, id_viaje_padre
FROM c_viajes FROM c_viajes
WHERE id_viaje = ? WHERE id_viaje = ?
LIMIT 1 LIMIT 1
@ -1606,11 +1668,19 @@ const updateTripStatus = async (req, res) => {
await connection.query( await connection.query(
`UPDATE c_viajes `UPDATE c_viajes
SET id_estado = ?, SET id_estado = ?,
ind_edi_app = 1,
fecha_ultima_edicion = NOW(), fecha_ultima_edicion = NOW(),
id_usuarios_ultima_edicion = ? id_usuarios_ultima_edicion = ?
WHERE id_viaje = ?`, WHERE id_viaje = ?`,
[FAILED_TRIP_STATE, userId, tripId] [FAILED_TRIP_STATE, userId, tripId]
); );
await propagateTripStatusToParentTrips(connection, {
initialParentTripId: tripRows[0].id_viaje_padre,
statusId: FAILED_TRIP_STATE,
userId,
requestId,
flow: 'failed_branch_manual'
});
await connection.commit(); await connection.commit();
@ -1682,7 +1752,7 @@ const updateTripStatus = async (req, res) => {
} }
const [tripRows] = await db.query( const [tripRows] = await db.query(
`SELECT id_viaje `SELECT id_viaje, id_viaje_padre
FROM c_viajes FROM c_viajes
WHERE id_viaje = ? WHERE id_viaje = ?
LIMIT 1`, LIMIT 1`,
@ -1761,6 +1831,7 @@ const updateTripStatus = async (req, res) => {
await db.query( await db.query(
`UPDATE c_viajes `UPDATE c_viajes
SET id_estado = ?, SET id_estado = ?,
ind_edi_app = 1,
fecha_ultima_edicion = NOW(), fecha_ultima_edicion = NOW(),
id_usuarios_ultima_edicion = ? id_usuarios_ultima_edicion = ?
WHERE id_viaje = ?`, WHERE id_viaje = ?`,
@ -1797,6 +1868,13 @@ const updateTripStatus = async (req, res) => {
userId userId
] ]
); );
await propagateTripStatusToParentTrips(db, {
initialParentTripId: tripRows[0].id_viaje_padre,
statusId: idEstado,
userId,
requestId,
flow: 'normal_manual'
});
appendTripStatusDebugLog({ appendTripStatusDebugLog({
stage: 'update_trip_status:c_cambios_estado_persisted', stage: 'update_trip_status:c_cambios_estado_persisted',
request_id: requestId, request_id: requestId,
@ -2330,7 +2408,7 @@ const clearTripStatus = async (req, res) => {
} }
const [tripRows] = await db.query( const [tripRows] = await db.query(
`SELECT id_viaje, id_estado `SELECT id_viaje, id_estado, id_viaje_padre
FROM c_viajes FROM c_viajes
WHERE id_viaje = ? WHERE id_viaje = ?
LIMIT 1`, LIMIT 1`,
@ -2666,11 +2744,19 @@ const clearTripStatus = async (req, res) => {
await connection.query( await connection.query(
`UPDATE c_viajes `UPDATE c_viajes
SET id_estado = ?, SET id_estado = ?,
ind_edi_app = 1,
fecha_ultima_edicion = NOW(), fecha_ultima_edicion = NOW(),
id_usuarios_ultima_edicion = ? id_usuarios_ultima_edicion = ?
WHERE id_viaje = ?`, WHERE id_viaje = ?`,
[currentStatusId, userId, tripId] [currentStatusId, userId, tripId]
); );
await propagateTripStatusToParentTrips(connection, {
initialParentTripId: tripRows[0].id_viaje_padre,
statusId: currentStatusId,
userId,
requestId,
flow: 'clear_status_manual'
});
await connection.commit(); await connection.commit();

View File

@ -177,8 +177,8 @@ test('POST /api/trips/:tripId/start inicia viaje asignado sin otro activo => 200
assert.equal(params[1], 1); assert.equal(params[1], 1);
assert.equal(params[2], '58045340X'); assert.equal(params[2], '58045340X');
assert.equal(params[3], 2); assert.equal(params[3], 2);
assert.ok(params[7] instanceof Date); assert.ok(params[8] instanceof Date);
assert.equal(params[9], 1); assert.equal(params[10], 1);
return [{ insertId: 10, affectedRows: 1 }]; return [{ insertId: 10, affectedRows: 1 }];
} }

View File

@ -1048,6 +1048,79 @@ test('POST /api/trips/:id/status estado 5 sin id_punto usa flujo global legacy =
assert.equal(step, 6); assert.equal(step, 6);
}); });
test('POST /api/trips/:id/status propaga estado global al viaje padre', async () => {
let step = 0;
db.query = async (sql, params) => {
step += 1;
if (step === 1) {
assert.match(sql, /FROM t_viaje_estados/);
assert.deepEqual(params, [6]);
return [[{ id_estado: 6 }]];
}
if (step === 2) {
assert.match(sql, /FROM c_viajes/);
assert.deepEqual(params, [248230]);
return [[{ id_viaje: 248230, id_viaje_padre: 196854 }]];
}
if (step === 3) {
assert.match(sql, /FROM c_viajes_proveedor/);
assert.deepEqual(params, [248230, '58045340X']);
return [[{ n_proveedor: 1, id_proveedor: 675 }]];
}
if (step === 4) {
assert.match(sql, /UPDATE c_viajes/);
assert.match(sql, /ind_edi_app = 1/);
assert.deepEqual(params, [6, 1, 248230]);
return [{ affectedRows: 1 }];
}
if (step === 5) {
assert.match(sql, /INSERT INTO c_cambios_estado/);
assert.equal(params[0], 248230);
assert.equal(params[3], 6);
return [{ insertId: 6, affectedRows: 1 }];
}
if (step === 6) {
assert.match(sql, /UPDATE c_viajes/);
assert.match(sql, /ind_edi_app = 1/);
assert.deepEqual(params, [6, 1, 196854]);
return [{ affectedRows: 1 }];
}
if (step === 7) {
assert.match(sql, /SELECT id_viaje_padre/);
assert.deepEqual(params, [196854]);
return [[{ id_viaje_padre: 0 }]];
}
throw new Error(`Unexpected query step ${step}: ${sql}`);
};
const response = await withServer(async (server) =>
requestJson({
port: server.address().port,
method: 'POST',
path: '/api/trips/248230/status',
authorization: `Bearer ${createToken()}`,
body: {
id_estado: 6
}
})
);
assert.equal(response.statusCode, 200);
assert.equal(response.body.success, true);
assert.equal(response.body.trip_id, 248230);
assert.equal(response.body.id_estado, 6);
assert.equal(step, 7);
});
test('POST /api/trips/:id/status estado intermedio con id_punto inválido => 400', async () => { test('POST /api/trips/:id/status estado intermedio con id_punto inválido => 400', async () => {
db.query = async () => { db.query = async () => {
throw new Error('db.query should not run for invalid id_punto'); throw new Error('db.query should not run for invalid id_punto');