metis-desk/modules/assets/src/api/infrastructure/persistence/asset.model.ts

90 lines
3.2 KiB
TypeScript
Raw Normal View History

import type { InferAttributes, InferCreationAttributes, Sequelize } from "sequelize";
import { DataTypes, Model, QueryTypes } from "sequelize";
export class AssetModel extends Model<
InferAttributes<AssetModel>,
InferCreationAttributes<AssetModel>
> {
declare id: string;
declare companyId: string;
declare templateId: string;
declare siteId: string | null;
declare personId: string | null;
declare specification: unknown;
declare values: unknown;
}
export class AssetRevisionModel extends Model<
InferAttributes<AssetRevisionModel>,
InferCreationAttributes<AssetRevisionModel>
> {
declare id: string;
declare assetId: string;
declare actorId: string;
declare recordedAt: string;
declare values: unknown;
declare position: number;
declare siteId: string | null;
declare personId: string | null;
}
const id = { type: DataTypes.UUID, primaryKey: true };
const fk = (model: string, nullable = false) => ({
type: DataTypes.UUID,
allowNull: nullable,
references: { model, key: "id" },
onDelete: "RESTRICT",
});
export async function migrateInventory(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 asset = {
id,
companyId: fk("companies"),
templateId: fk("asset_definitions"),
siteId: fk("company_sites", true),
personId: fk("company_contacts", true),
specification: { type: DataTypes.JSON, allowNull: false },
values: { type: DataTypes.JSON, allowNull: false },
};
const revision = {
id,
assetId: fk("assets"),
actorId: fk("users"),
siteId: fk("company_sites", true),
personId: fk("company_contacts", true),
recordedAt: { type: DataTypes.STRING(30), allowNull: false },
values: { type: DataTypes.JSON, allowNull: false },
position: { type: DataTypes.INTEGER, allowNull: false },
};
if (!tables.some((table) => table.name === "assets")) {
await query.createTable("assets", asset);
}
if (!tables.some((table) => table.name === "asset_revisions")) {
await query.createTable("asset_revisions", revision);
}
const revisionColumns = await query.describeTable("asset_revisions");
for (const [column, reference] of [
["siteId", "company_sites"],
["personId", "company_contacts"],
] as const) {
if (!(column in revisionColumns)) {
await query.addColumn("asset_revisions", column, fk(reference, true));
}
// Reconstruye las referencias de instalaciones que ya hubieran registrado revisiones.
const source =
column === "siteId"
? "UPDATE asset_revisions SET siteId = NULLIF(JSON_UNQUOTE(JSON_EXTRACT(`values`, '$.siteId')), 'null')"
: "UPDATE asset_revisions SET personId = NULLIF(JSON_UNQUOTE(JSON_EXTRACT(`values`, '$.personId')), 'null')";
await database.query(
source + (column === "siteId" ? " WHERE siteId IS NULL" : " WHERE personId IS NULL")
);
}
AssetModel.init(asset, { sequelize: database, tableName: "assets", timestamps: false });
AssetRevisionModel.init(revision, {
sequelize: database,
tableName: "asset_revisions",
timestamps: false,
});
}