import type { InferAttributes, InferCreationAttributes, Sequelize } from "sequelize"; import { DataTypes, Model, QueryTypes } from "sequelize"; import { initializeWorkstationMembers } from "./workstation-relational"; /** Proyección técnica de referencias históricas y reserva vigente; no representa otra entidad de negocio. */ export class WorkstationAssetModel extends Model< InferAttributes, InferCreationAttributes > { declare workstationId: string; declare companyId: string; declare assetId: string; declare activeKey: string | null; } export async function migrateWorkstations(database: Sequelize) { const query = database.getQueryInterface(); const tables = await database.query<{ name: string }>( "SELECT TABLE_NAME AS name FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE()", { type: QueryTypes.SELECT } ); const fk = (model: string, nullable = false) => ({ type: DataTypes.UUID, allowNull: nullable, references: { model, key: "id" }, onDelete: "RESTRICT", }); const root = { id: { type: DataTypes.UUID, primaryKey: true }, companyId: fk("companies"), siteId: fk("company_sites", true), personId: fk("company_contacts", true), name: { type: DataTypes.STRING(100), allowNull: false }, active: { type: DataTypes.BOOLEAN, allowNull: false }, }; const revision = { id: { type: DataTypes.UUID, primaryKey: true }, workstationId: fk("workstations"), actorId: fk("users"), siteId: fk("company_sites", true), personId: fk("company_contacts", true), name: { type: DataTypes.STRING(100), allowNull: false }, active: { type: DataTypes.BOOLEAN, allowNull: false }, recordedAt: { type: DataTypes.STRING(30), allowNull: false }, position: { type: DataTypes.INTEGER, allowNull: false }, }; const reference = { workstationId: { ...fk("workstations"), primaryKey: true }, companyId: fk("companies"), assetId: { ...fk("assets"), primaryKey: true }, activeKey: { type: DataTypes.STRING(80), unique: true, allowNull: true }, }; for (const [table, columns] of [ ["workstations", root], ["workstation_revisions", revision], ["workstation_assets", reference], ] as const) { if (!tables.some((item) => item.name === table)) { await query.createTable(table, columns); } } const indexes = await database.query<{ name: string }>( "SELECT DISTINCT INDEX_NAME AS name FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='workstations'", { type: QueryTypes.SELECT } ); if (!indexes.some((item) => item.name === "workstations_company_identity")) { await query.addIndex("workstations", ["companyId", "id"], { name: "workstations_company_identity", unique: true, }); } const constraints = await database.query<{ name: string }>( "SELECT CONSTRAINT_NAME AS name FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='workstation_assets'", { type: QueryTypes.SELECT } ); if (!constraints.some((item) => item.name === "workstation_asset_company")) { await database.query( "ALTER TABLE workstation_assets ADD CONSTRAINT workstation_asset_company FOREIGN KEY (companyId, assetId) REFERENCES assets(companyId,id)" ); } if (!constraints.some((item) => item.name === "workstation_owner_company")) { await database.query( "ALTER TABLE workstation_assets ADD CONSTRAINT workstation_owner_company FOREIGN KEY (companyId, workstationId) REFERENCES workstations(companyId,id)" ); } WorkstationAssetModel.init(reference, { sequelize: database, tableName: "workstation_assets", timestamps: false, }); await initializeWorkstationMembers(database); }