metis-desk/modules/assets/src/api/domain/asset-catalog-seed.ts

229 lines
8.9 KiB
TypeScript
Raw Normal View History

import { UniqueID } from "@repo/rdx-ddd";
import type { AssetTemplateIconKey } from "../../common/asset-template-icons";
import type { AssetCatalog } from "./asset-catalog.aggregate";
import type { AssetDefinitionSpec, AssetFieldType } from "./asset-definition";
2026-10-09 08:38:19 +00:00
import { AssetDefinitionValues } from "./value-objects/asset-definition-values.vo";
const FIELDS: readonly [string, string, AssetFieldType, string, (readonly string[])?][] = [
["product_code", "Código de producto / Service Tag", "text", ""],
["memory_type", "Tipo de RAM", "text", ""],
["memory_layout", "Distribución de RAM", "text", ""],
["memory_free_slots", "Ranuras libres de RAM", "number", ""],
["memory_soldered", "Memoria soldada", "boolean", ""],
["disk_model", "Modelo del disco", "text", ""],
["disk_interface", "Interfaz del disco", "text", ""],
["disk_format", "Formato del disco", "text", ""],
["disk_free_slots", "Ranuras libres de almacenamiento", "number", ""],
["touchscreen", "Pantalla táctil", "boolean", ""],
["panel_reference", "Referencia del panel", "text", ""],
["keyboard_layout", "Distribución / idioma del teclado", "text", ""],
["keyboard_backlight", "Teclado retroiluminado", "boolean", ""],
["battery_reference", "Referencia / modelo de batería", "text", ""],
["battery_design_capacity", "Capacidad de diseño de batería", "number", "Wh"],
["battery_full_capacity", "Capacidad máxima actual de batería", "number", "Wh"],
["battery_cycles", "Número de ciclos de batería", "number", ""],
[
"battery_status",
"Estado de batería",
"choice",
"",
["Normal", "Desgastada", "Averiada", "Hinchada"],
],
["battery_checked_on", "Fecha de comprobación de batería", "date", ""],
["charger_power", "Potencia del cargador", "number", "W"],
["charger_connector", "Tipo de conector del cargador", "text", ""],
["charger_reference", "Referencia / modelo del cargador", "text", ""],
["service_manual", "Enlace al manual de servicio", "text", ""],
["technical_notes", "Observaciones técnicas", "text", ""],
["brand", "Marca", "text", ""],
["model", "Modelo", "text", ""],
["serial", "Número de serie", "text", ""],
["processor", "Procesador", "text", ""],
["memory", "Memoria RAM", "number", "GB"],
["storage", "Almacenamiento", "text", ""],
["graphics", "Tarjeta gráfica", "text", ""],
["webcam", "Webcam", "text", ""],
["bluetooth", "Versión de Bluetooth", "text", ""],
["numeric_keypad", "Teclado numérico", "boolean", ""],
["os", "Sistema operativo", "text", ""],
["hostname", "Nombre de equipo", "text", ""],
["screen_size", "Pulgadas", "number", "pulgadas"],
["resolution", "Resolución", "text", ""],
["connections", "Conexiones", "text", ""],
["ip", "Dirección IP", "text", ""],
["mac", "Dirección MAC", "text", ""],
["ports", "Número de puertos", "number", ""],
["speed", "Velocidad de red", "text", ""],
["poe", "PoE", "boolean", ""],
["wifi", "Estándar Wi-Fi", "text", ""],
["capacity", "Capacidad útil", "text", ""],
["disks", "Discos", "text", ""],
["raid", "RAID", "text", ""],
["printing", "Tecnología de impresión", "text", ""],
["color", "Impresión en color", "boolean", ""],
["duplex", "Doble cara", "boolean", ""],
["imei", "IMEI", "text", ""],
["phone", "Número de teléfono", "text", ""],
["carrier", "Operador móvil", "text", ""],
["power", "Potencia", "number", "VA"],
["battery", "Autonomía", "number", "minutos"],
["purchased_on", "Fecha de compra", "date", ""],
["warranty_until", "Fin de garantía", "date", ""],
];
const COMMON = ["brand", "model", "serial", "purchased_on", "warranty_until"];
const LAPTOP_SECTION_FIELDS: readonly [string, readonly string[]][] = [
["Identificación", ["brand", "model", "serial", "product_code"]],
["Hardware", ["processor", "graphics", "webcam", "wifi", "bluetooth"]],
[
"Memoria RAM",
["memory", "memory_type", "memory_layout", "memory_free_slots", "memory_soldered"],
],
["Almacenamiento", ["storage", "disk_model", "disk_interface", "disk_format", "disk_free_slots"]],
["Pantalla", ["screen_size", "resolution", "touchscreen", "panel_reference"]],
["Teclado", ["keyboard_layout", "numeric_keypad", "keyboard_backlight"]],
[
"Batería",
[
"battery_reference",
"battery_design_capacity",
"battery_full_capacity",
"battery_cycles",
"battery_status",
"battery_checked_on",
],
],
["Alimentación", ["charger_power", "charger_connector", "charger_reference"]],
["Compra y garantía", ["purchased_on", "warranty_until"]],
["Soporte y reparación", ["service_manual", "technical_notes"]],
];
const TEMPLATES: readonly [string, string, readonly string[]][] = [
[
"laptop",
"Portátil",
LAPTOP_SECTION_FIELDS.flatMap(([, keys]) => keys).filter((key) => !COMMON.includes(key)),
],
[
"desktop",
"PC de sobremesa",
["processor", "memory", "storage", "os", "hostname", "connections", "ip", "mac"],
],
["monitor", "Monitor", ["screen_size", "resolution", "connections"]],
["printer", "Impresora", ["printing", "color", "duplex", "connections", "ip", "mac"]],
["router", "Router", ["ports", "speed", "wifi", "ip", "mac"]],
["firewall", "Firewall", ["ports", "speed", "ip", "mac"]],
["switch", "Switch", ["ports", "speed", "poe", "ip", "mac"]],
["access_point", "Punto de acceso Wi-Fi", ["wifi", "poe", "ip", "mac"]],
["nas", "NAS", ["processor", "memory", "disks", "capacity", "raid", "os", "ip", "mac"]],
[
"server",
"Servidor",
["processor", "memory", "storage", "disks", "raid", "os", "hostname", "ip", "mac"],
],
["smartphone", "Smartphone", ["os", "storage", "screen_size", "imei", "phone", "carrier"]],
["ups", "SAI", ["power", "battery", "connections"]],
];
const TEMPLATE_ICONS: Readonly<Record<string, AssetTemplateIconKey>> = {
laptop: "laptop",
desktop: "desktop",
monitor: "monitor",
printer: "printer",
router: "router",
firewall: "shield",
switch: "network",
access_point: "wifi",
nas: "hard-drive",
server: "server",
smartphone: "smartphone",
ups: "battery",
};
const SECTION_FIELDS: readonly [string, readonly string[]][] = [
["Identificación", ["brand", "model", "serial"]],
["Hardware", ["processor", "memory", "storage", "capacity", "disks", "raid"]],
["Sistema", ["os", "hostname"]],
["Pantalla y conexiones", ["screen_size", "resolution", "connections"]],
["Red", ["ip", "mac", "ports", "speed", "poe", "wifi"]],
["Impresión", ["printing", "color", "duplex"]],
["Telefonía", ["imei", "phone", "carrier"]],
["Alimentación", ["power", "battery"]],
["Compra y garantía", ["purchased_on", "warranty_until"]],
];
export function seedAssetCatalog(catalog: AssetCatalog) {
let current = catalog;
2026-10-10 10:01:58 +00:00
const add = (key: string, input: AssetDefinitionSpec) => {
const values = AssetDefinitionValues.create(input);
2026-10-10 10:01:58 +00:00
if (!values.isSuccess) {
throw new Error("Definición inicial de activos inválida.");
}
const result = current.seed(key, values.data);
2026-10-10 10:01:58 +00:00
if (!result.isSuccess) {
throw new Error("Catálogo inicial de activos inconsistente.");
}
current = result.data;
};
2026-10-10 10:01:58 +00:00
for (const [key, name, type, unit, choices = []] of FIELDS) {
add(`field:${key}`, {
kind: "field",
name,
description: "",
type,
unit,
choices: [...choices],
});
}
for (const [key, name, fields] of TEMPLATES) {
const sectionFields = [...COMMON, ...fields];
const sectionLayout = key === "laptop" ? LAPTOP_SECTION_FIELDS : SECTION_FIELDS;
const sections = sectionLayout
.filter(([, keys]) => keys.some((field) => sectionFields.includes(field)))
.map(([name, keys]) => ({
id: UniqueID.generateNewID().toPrimitive(),
name,
description: "",
keys,
}));
const references = [...COMMON, ...fields].map((field) => {
const id = current.definitions
.find((item) => item.stockKey.getOrUndefined() === `field:${field}`)
?.id.toPrimitive();
2026-10-10 10:01:58 +00:00
if (!id) {
throw new Error("Campo inicial de activos ausente.");
}
const sectionId = sections.find((section) => section.keys.includes(field))?.id;
2026-10-10 10:01:58 +00:00
return { fieldId: id, required: false, ...(sectionId ? { sectionId } : {}) };
});
2026-10-10 10:01:58 +00:00
add(`template:${key}`, {
kind: "template",
icon: TEMPLATE_ICONS[key],
name,
description: "",
fields: references,
...(sections.length
? { sections: sections.map(({ id, name, description }) => ({ id, name, description })) }
: {}),
});
}
2026-10-04 19:04:14 +00:00
for (const [key, name, inverseName, symmetric] of [
["connected", "Conectado a", "Conectado a", true],
["hosted", "Alojado en", "Aloja", false],
["depends", "Depende de", "Es necesario para", false],
["powered", "Alimentado por", "Alimenta", false],
["installed", "Instalado en", "Tiene instalado", false],
] as const) {
add(`relation:${key}`, { kind: "relation", name, inverseName, symmetric, description: "" });
}
2026-10-10 10:01:58 +00:00
return current;
}