- Introduced a new optional field `registeredOn` to the asset input schema. - Updated asset values and persistence layers to handle the new field. - Enhanced tests to validate the behavior of the `registeredOn` field, including various date formats and null values. - Modified UI components to display the registration date in asset details and forms. - Added localization support for the new field in English and Spanish. - Implemented helper functions for formatting the registration date. - Created integration tests for reading and writing assets with the new field in the database.
130 lines
5.5 KiB
TypeScript
130 lines
5.5 KiB
TypeScript
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();
|
|
}
|
|
});
|