90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
import type { InferAttributes, InferCreationAttributes, Sequelize } from "sequelize";
|
|
import { DataTypes, Model, QueryTypes } from "sequelize";
|
|
|
|
import { relationshipColumns } from "./asset-relationship-schema";
|
|
|
|
export class RelationshipModel extends Model<
|
|
InferAttributes<RelationshipModel>,
|
|
InferCreationAttributes<RelationshipModel>
|
|
> {
|
|
declare id: string;
|
|
declare companyId: string;
|
|
declare sourceId: string;
|
|
declare targetId: string;
|
|
declare typeId: string;
|
|
declare name: string;
|
|
declare inverseName: string;
|
|
declare symmetric: boolean;
|
|
declare notes: string;
|
|
declare createdBy: string;
|
|
declare createdAt: string;
|
|
declare endedBy: string | null;
|
|
declare endedAt: string | null;
|
|
declare activeKey: string | null;
|
|
}
|
|
|
|
export async function migrateRelationships(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 columns = {
|
|
id: { type: DataTypes.UUID, primaryKey: true },
|
|
companyId: fk("companies"),
|
|
sourceId: fk("assets"),
|
|
targetId: fk("assets"),
|
|
typeId: fk("asset_definitions"),
|
|
...relationshipColumns,
|
|
createdBy: fk("users"),
|
|
createdAt: { type: DataTypes.STRING(30), allowNull: false },
|
|
endedBy: fk("users", true),
|
|
endedAt: { type: DataTypes.STRING(30), allowNull: true },
|
|
activeKey: { type: DataTypes.STRING(150), allowNull: true, unique: true },
|
|
};
|
|
|
|
if (!tables.some((table) => table.name === "asset_relationships")) {
|
|
await query.createTable("asset_relationships", 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='assets'",
|
|
{ type: QueryTypes.SELECT }
|
|
);
|
|
|
|
if (!indexes.some((index) => index.name === "assets_company_identity")) {
|
|
await query.addIndex("assets", ["companyId", "id"], {
|
|
unique: true,
|
|
name: "assets_company_identity",
|
|
});
|
|
}
|
|
const constraints = await database.query<{ name: string }>(
|
|
"SELECT CONSTRAINT_NAME AS name FROM information_schema.TABLE_CONSTRAINTS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='asset_relationships'",
|
|
{ type: QueryTypes.SELECT }
|
|
);
|
|
|
|
// Las FK compuestas impiden vínculos cruzados también ante escrituras externas al dominio.
|
|
for (const [column, name] of [
|
|
["sourceId", "relationship_source_company"],
|
|
["targetId", "relationship_target_company"],
|
|
] as const) {
|
|
if (!constraints.some((constraint) => constraint.name === name)) {
|
|
await database.query(
|
|
`ALTER TABLE asset_relationships ADD CONSTRAINT \`${name}\` FOREIGN KEY (companyId, \`${column}\`) REFERENCES assets(companyId,id)`
|
|
);
|
|
}
|
|
}
|
|
RelationshipModel.init(columns, {
|
|
sequelize: database,
|
|
tableName: "asset_relationships",
|
|
timestamps: false,
|
|
});
|
|
}
|