Refactor funciones de verificación y migración de activos para mejorar la legibilidad y eliminar parámetros innecesarios

This commit is contained in:
David Arranz 2026-10-10 11:09:34 +02:00
parent 4edc1268b4
commit 0996db18c7
4 changed files with 29 additions and 35 deletions

View File

@ -787,12 +787,7 @@ test("HTTP y MariaDB: configuración única, usuarios, sesiones y protección de
secondCompany.id, secondCompany.id,
database database
); );
await verifyInventory( await verifyInventory((...args) => operator.request(...args), customer.id, secondCompany.id);
(...args) => operator.request(...args),
customer.id,
secondCompany.id,
database
);
await verifyRelationships( await verifyRelationships(
(...args) => operator.request(...args), (...args) => operator.request(...args),
customer.id, customer.id,

View File

@ -7,15 +7,13 @@ import {
SaveDefinitionResponseSchema, SaveDefinitionResponseSchema,
} from "@metis/assets/common"; } from "@metis/assets/common";
import { CompanyResponseSchema } from "@metis/companies/common"; import { CompanyResponseSchema } from "@metis/companies/common";
import type { Sequelize } from "sequelize";
import { z } from "zod/v4"; import { z } from "zod/v4";
import { UniqueID } from "../../../packages/rdx-ddd/src/index"; import { UniqueID } from "../../../packages/rdx-ddd/src/index";
export async function verifyInventory( export async function verifyInventory(
request: (path: string, body?: unknown, origin?: string, token?: string) => Promise<Response>, request: (path: string, body?: unknown, origin?: string, token?: string) => Promise<Response>,
companyId: string, companyId: string,
otherId: string, otherId: string
database: Sequelize
) { ) {
const path = `/assets/${companyId}`; const path = `/assets/${companyId}`;
async function save(url: string, values: unknown) { async function save(url: string, values: unknown) {

View File

@ -41,7 +41,9 @@ export async function verifyWorkstations(
assert.ok(person); assert.ok(person);
const otherPersonResponse = await request(`/companies/${otherId}/people`, personFields); const otherPersonResponse = await request(`/companies/${otherId}/people`, personFields);
assert.equal(otherPersonResponse.status, 201); assert.equal(otherPersonResponse.status, 201);
const otherPerson = CompanyResponseSchema.parse(await otherPersonResponse.json()).company.people.at(-1); const otherPerson = CompanyResponseSchema.parse(
await otherPersonResponse.json()
).company.people.at(-1);
assert.ok(otherPerson); assert.ok(otherPerson);
const input = { const input = {
name: "Puesto Ana", name: "Puesto Ana",

View File

@ -102,17 +102,17 @@ export async function migrateLegacyAssetAssignments(database: Sequelize) {
if (!("personId" in assetColumns)) { if (!("personId" in assetColumns)) {
return; return;
} }
const legacy = await database.query<LegacyAssignment>( const legacyAssignments = await database.query<LegacyAssignment>(
"SELECT a.id,a.companyId,a.siteId,a.personId,p.name AS personName,s.name AS siteName,(SELECT r.actorId FROM asset_revisions r WHERE r.assetId=a.id ORDER BY r.position DESC LIMIT 1) AS actorId FROM assets a JOIN company_contacts p ON p.id=a.personId AND p.companyId=a.companyId LEFT JOIN company_sites s ON s.id=a.siteId AND s.companyId=a.companyId WHERE a.personId IS NOT NULL AND JSON_UNQUOTE(JSON_EXTRACT(a.`values`,'$.status')) <> 'retired'", "SELECT a.id,a.companyId,a.siteId,a.personId,p.name AS personName,s.name AS siteName,(SELECT r.actorId FROM asset_revisions r WHERE r.assetId=a.id ORDER BY r.position DESC LIMIT 1) AS actorId FROM assets a JOIN company_contacts p ON p.id=a.personId AND p.companyId=a.companyId LEFT JOIN company_sites s ON s.id=a.siteId AND s.companyId=a.companyId WHERE a.personId IS NOT NULL AND JSON_UNQUOTE(JSON_EXTRACT(a.`values`,'$.status')) <> 'retired'",
{ type: QueryTypes.SELECT } { type: QueryTypes.SELECT }
); );
const active = await database.query<ActiveWorkstationAsset>( const activeWorkstationAssets = await database.query<ActiveWorkstationAsset>(
"SELECT wa.assetId,w.personId FROM workstation_assets wa JOIN workstations w ON w.id=wa.workstationId WHERE wa.activeKey IS NOT NULL", "SELECT wa.assetId,w.personId FROM workstation_assets wa JOIN workstations w ON w.id=wa.workstationId WHERE wa.activeKey IS NOT NULL",
{ type: QueryTypes.SELECT } { type: QueryTypes.SELECT }
); );
const activeByAsset = new Map(active.map((item) => [item.assetId, item])); const activeByAsset = new Map(activeWorkstationAssets.map((item) => [item.assetId, item]));
const groups = new Map<string, LegacyAssignment[]>(); const groups = new Map<string, LegacyAssignment[]>();
for (const assignment of legacy) { for (const assignment of legacyAssignments) {
const existing = activeByAsset.get(assignment.id); const existing = activeByAsset.get(assignment.id);
if (existing) { if (existing) {
if (existing.personId !== assignment.personId) { if (existing.personId !== assignment.personId) {
@ -197,25 +197,24 @@ export async function migrateLegacyAssetAssignments(database: Sequelize) {
transaction, transaction,
}); });
}); });
const revisionColumns = await query.describeTable("asset_revisions"); await removeLegacyPersonColumn(database, "asset_revisions");
for (const [table, columns] of [ await removeLegacyPersonColumn(database, "assets");
["asset_revisions", revisionColumns], }
["assets", assetColumns],
] as const) { async function removeLegacyPersonColumn(database: Sequelize, table: "assets" | "asset_revisions") {
if (!("personId" in columns)) { const columns = await database.getQueryInterface().describeTable(table);
continue; if (!("personId" in columns)) {
} return;
const constraints = await database.query<{ constraintName: string }>( }
"SELECT CONSTRAINT_NAME AS constraintName FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:table AND COLUMN_NAME='personId' AND REFERENCED_TABLE_NAME IS NOT NULL", const constraints = await database.query<{ constraintName: string }>(
{ replacements: { table }, type: QueryTypes.SELECT } "SELECT CONSTRAINT_NAME AS constraintName FROM information_schema.KEY_COLUMN_USAGE WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=:table AND COLUMN_NAME='personId' AND REFERENCED_TABLE_NAME IS NOT NULL",
); { replacements: { table }, type: QueryTypes.SELECT }
for (const { constraintName } of constraints) { );
await database.query( for (const { constraintName } of constraints) {
`ALTER TABLE \`${table}\` DROP FOREIGN KEY \`${constraintName.replaceAll("`", "``")}\`` await database.query(
); `ALTER TABLE \`${table}\` DROP FOREIGN KEY \`${constraintName.replaceAll("`", "``")}\``
} );
// Sequelize 6 y mariadb 3 devuelven una matriz inmutable para ALTER TABLE, }
// que hace fallar QueryInterface.removeColumn después de ejecutar correctamente la migración. // QueryInterface.removeColumn is incompatible with Sequelize 6 and mariadb 3 here.
await database.query(`ALTER TABLE \`${table}\` DROP COLUMN personId`); await database.query(`ALTER TABLE \`${table}\` DROP COLUMN personId`);
}
} }