import assert from "node:assert/strict"; import { test } from "node:test"; import { Asset } from "../../../modules/assets/src/api/domain/asset.aggregate"; import { AssetSpecification, AssetValues, } from "../../../modules/assets/src/api/domain/value-objects/asset-values.vo"; import { readInventory, writeInventory, } from "../../../modules/assets/src/api/infrastructure/persistence/asset-inventory-relational"; import { AssetPersistenceMapper } from "../../../modules/assets/src/api/infrastructure/persistence/asset-persistence.mapper"; import { UniqueID } from "../../../packages/rdx-ddd/src/index"; import { createDatabase, readDatabaseEnvironment } from "./config/database"; // Tablas temporales de la conexión: no se modifica el esquema ni el inventario de la base de pruebas. const TABLES = { assets: "id CHAR(36) PRIMARY KEY, companyId CHAR(36), templateId CHAR(36), siteId CHAR(36), brandId CHAR(36), name VARCHAR(100), registeredOn DATE, status VARCHAR(15), notes TEXT, brandDefined BOOLEAN, templateName VARCHAR(100), sectionsDefined BOOLEAN", asset_revisions: "id CHAR(36) PRIMARY KEY, assetId CHAR(36), actorId CHAR(36), recordedAt VARCHAR(30), position INTEGER, templateId CHAR(36), siteId CHAR(36), brandId CHAR(36), name VARCHAR(100), registeredOn DATE, status VARCHAR(15), notes TEXT, brandDefined BOOLEAN", asset_specification_fields: "assetId CHAR(36), fieldId CHAR(36), name VARCHAR(100), fieldType VARCHAR(12), unit VARCHAR(30), required BOOLEAN, sectionId CHAR(36), position INTEGER, PRIMARY KEY (assetId,fieldId)", asset_specification_sections: "assetId CHAR(36), id CHAR(36), name VARCHAR(100), description TEXT, position INTEGER, PRIMARY KEY (assetId,id)", asset_specification_field_choices: "assetId CHAR(36), fieldId CHAR(36), position INTEGER, value VARCHAR(100), PRIMARY KEY (assetId,fieldId,position)", asset_characteristics: "assetId CHAR(36), fieldId CHAR(36), valueType VARCHAR(12), textValue TEXT, numberValue DOUBLE, booleanValue BOOLEAN, dateValue DATE, PRIMARY KEY (assetId,fieldId)", asset_revision_characteristics: "revisionId CHAR(36), assetId CHAR(36), fieldId CHAR(36), valueType VARCHAR(12), textValue TEXT, numberValue DOUBLE, booleanValue BOOLEAN, dateValue DATE, PRIMARY KEY (revisionId,fieldId)", }; test("MariaDB: lectura de activos e historial con fecha de alta ISO y nula sin columnas duplicadas", async () => { const environment = readDatabaseEnvironment(process.env); assert.equal(environment.NODE_ENV, "test"); assert.equal(environment.DB_NAME, "metis_desk_test"); const database = createDatabase(environment); try { await database.transaction(async (transaction) => { try { for (const [table, columns] of Object.entries(TABLES)) { await database.query(`CREATE TEMPORARY TABLE ${table} (${columns})`, { transaction }); } const companyId = UniqueID.generateNewID(); const actorId = UniqueID.generateNewID(); const templateId = UniqueID.generateNewID().toPrimitive(); const fieldId = UniqueID.generateNewID().toPrimitive(); const specification = AssetSpecification.create({ templateId, templateName: "Equipo", fields: [ { fieldId, name: "Compra", type: "date", unit: "", choices: [], required: false }, ], }); assert.ok(specification.isSuccess); const expected: Asset[] = []; const mapper = new AssetPersistenceMapper(); for (const registeredOn of ["2024-02-29", null]) { const values = AssetValues.create( { name: registeredOn ? "Con fecha" : "Sin fecha", templateId, siteId: null, registeredOn, status: "operational", notes: "", characteristics: { [fieldId]: "2024-01-15" }, }, specification.data ); assert.ok(values.isSuccess); const created = Asset.create( companyId, specification.data, values.data, actorId, "2026-10-15T12:00:00.000Z" ); assert.ok(created.isSuccess); expected.push(created.data); await writeInventory( database, mapper.toPersistence(created.data), new Set(), transaction ); } const inventory = await readInventory(database, companyId.toPrimitive(), transaction); assert.equal(inventory.rows.length, 2); assert.equal(inventory.revisions.length, 2); for (const asset of expected) { const row = inventory.rows.find((candidate) => candidate.id === asset.id.toPrimitive()); assert.ok(row); const restored = mapper.toDomain( row, inventory.revisions.filter((revision) => revision.assetId === row.id) ); assert.deepEqual(restored.values.toPrimitive(), asset.values.toPrimitive()); assert.deepEqual( restored.history[0]?.values.toPrimitive(), asset.history[0]?.values.toPrimitive() ); } assert.deepEqual( await readInventory(database, UniqueID.generateNewID().toPrimitive(), transaction), { rows: [], revisions: [] } ); } finally { for (const table of Object.keys(TABLES).reverse()) { await database.query(`DROP TEMPORARY TABLE IF EXISTS ${table}`, { transaction }); } } }); } finally { await database.close(); } });