metis-desk/modules/assets/src/api/infrastructure/persistence/rename-workstations-from-primary-assets.ts
David 0e8e15c9c2 feat: Implement account deletion functionality with UI and API integration
- Added `removeAccessAccount` function to handle account deletion in the database, ensuring no external references exist.
- Created `deleteAccount` API function to facilitate account deletion requests from the client.
- Developed `AccountDeleteDialog` component for user confirmation before account deletion, integrating with the delete API.
- Introduced resource image handling with validation for PNG uploads, including UI components for image selection and preview.
- Implemented resource icon template evolution logic to maintain icon bindings without overwriting existing fields.
- Added scripts for auditing account deletion and usage checks, ensuring robust testing of the new features.
2026-10-27 11:39:53 +01:00

73 lines
2.8 KiB
TypeScript

import { UniqueID } from "@repo/rdx-ddd";
import type { Sequelize } from "sequelize";
import { QueryTypes } from "sequelize";
import { z } from "zod/v4";
import { WorkstationInputSchema } from "../../domain/workstation-values";
const CandidateSchema = z.object({
id: z.uuid(),
name: WorkstationInputSchema.shape.name,
});
/** Corrección explícita de nombres; conserva las revisiones anteriores y la composición. */
export async function renameWorkstationsFromPrimaryAssets(database: Sequelize, actorId: string) {
const actor = z.uuid().parse(actorId);
return database.transaction(async (transaction) => {
const users = await database.query<{ id: string }>(
"SELECT id FROM users WHERE id=:actor AND active=1",
{ replacements: { actor }, transaction, type: QueryTypes.SELECT }
);
if (users.length !== 1) {
throw new Error("La corrección requiere un usuario activo para registrar las revisiones.");
}
// Mismo bloqueo por compañía que las escrituras ordinarias del inventario.
await database.query("SELECT id FROM companies ORDER BY id FOR UPDATE", {
transaction,
type: QueryTypes.SELECT,
});
const candidates = z.array(CandidateSchema).parse(
await database.query(
`SELECT w.id,a.name FROM workstations w
INNER JOIN assets a ON a.id=w.computerAssetId AND a.companyId=w.companyId
INNER JOIN workstation_members m ON m.workstationId=w.id AND m.assetId=a.id AND m.kind='exclusive'
WHERE BINARY w.name<>BINARY a.name FOR UPDATE`,
{ transaction, type: QueryTypes.SELECT }
)
);
for (const candidate of candidates) {
const replacements = {
id: candidate.id,
name: candidate.name,
revisionId: UniqueID.generateNewID().toPrimitive(),
actor,
recordedAt: new Date().toISOString(),
};
await database.query(
`INSERT INTO workstation_revisions
(id,workstationId,actorId,siteId,personId,computerAssetId,name,active,recordedAt,position)
SELECT :revisionId,w.id,:actor,w.siteId,w.personId,w.computerAssetId,:name,w.active,
GREATEST(:recordedAt,COALESCE(MAX(r.recordedAt),:recordedAt)),COALESCE(MAX(r.position),-1)+1
FROM workstations w LEFT JOIN workstation_revisions r ON r.workstationId=w.id
WHERE w.id=:id GROUP BY w.id,w.siteId,w.personId,w.computerAssetId,w.active`,
{ replacements, transaction }
);
await database.query(
`INSERT INTO workstation_revision_members (revisionId,assetId,kind,position)
SELECT :revisionId,assetId,kind,position FROM workstation_members WHERE workstationId=:id`,
{ replacements, transaction }
);
await database.query("UPDATE workstations SET name=:name WHERE id=:id", {
replacements,
transaction,
});
}
return candidates.length;
});
}