- 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.
73 lines
2.8 KiB
TypeScript
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;
|
|
});
|
|
}
|