corrad-bp/server/api/process/[id]/duplicate.post.js
Afiq 44baddb6e3 Enhance Process Builder with Critical Fixes and Database Integration
- Implemented complete API system with REST endpoints for all process operations, including CRUD functionality.
- Added support for direct process linking via URL parameters, improving navigation and usability.
- Enhanced save functionality with success/error notifications and improved state management.
- Fixed navigation issues, including unsaved changes detection and automatic URL synchronization.
- Resolved Vue Flow interference, allowing for seamless connector dragging between nodes.
- Ensured backward compatibility for legacy process definitions, automatically upgrading them.
- Introduced comprehensive toast notifications for user feedback on all operations.
- Optimized performance by reducing re-renders and improving memory management.
- Enhanced error handling with robust validation and graceful recovery throughout the system.
- Updated UI consistency across form builder and process builder management interfaces.
2025-05-30 16:36:32 +08:00

114 lines
3.3 KiB
JavaScript

import { PrismaClient } from '@prisma/client';
import { v4 as uuidv4 } from 'uuid';
// Initialize Prisma client
const prisma = new PrismaClient();
export default defineEventHandler(async (event) => {
try {
// Get the process ID from the route parameter
const processId = getRouterParam(event, 'id');
if (!processId) {
return {
success: false,
error: 'Process ID is required'
};
}
// Parse the request body for optional parameters
const body = await readBody(event);
const { newName, asTemplate = false } = body;
// Check if the ID is a UUID or numeric ID
const isUUID = processId.length === 36 && processId.includes('-');
// Find the source process
const sourceProcess = await prisma.process.findFirst({
where: isUUID
? { processUUID: processId }
: { processID: parseInt(processId) }
});
if (!sourceProcess) {
return {
success: false,
error: 'Source process not found'
};
}
// Generate new IDs for all nodes and edges in the definition
const newDefinition = JSON.parse(JSON.stringify(sourceProcess.processDefinition));
const nodeIdMap = new Map();
// Update node IDs
if (newDefinition.nodes) {
newDefinition.nodes.forEach(node => {
const oldId = node.id;
const newId = uuidv4();
nodeIdMap.set(oldId, newId);
node.id = newId;
});
}
// Update edge IDs and references
if (newDefinition.edges) {
newDefinition.edges.forEach(edge => {
edge.id = uuidv4();
edge.source = nodeIdMap.get(edge.source) || edge.source;
edge.target = nodeIdMap.get(edge.target) || edge.target;
});
}
// Create the duplicate process
const duplicatedProcess = await prisma.process.create({
data: {
processUUID: uuidv4(),
processName: newName || `${sourceProcess.processName} (Copy)`,
processDescription: sourceProcess.processDescription,
processCategory: sourceProcess.processCategory,
processPriority: sourceProcess.processPriority,
processOwner: sourceProcess.processOwner,
processDefinition: newDefinition,
processVariables: sourceProcess.processVariables,
processSettings: sourceProcess.processSettings,
processPermissions: sourceProcess.processPermissions,
processStatus: 'draft', // Always start as draft
isTemplate: asTemplate,
templateCategory: asTemplate ? sourceProcess.templateCategory : null,
processCreatedBy: body.createdBy || sourceProcess.processCreatedBy
},
include: {
creator: {
select: {
userID: true,
userFullName: true,
userUsername: true
}
}
}
});
return {
success: true,
message: 'Process duplicated successfully',
process: duplicatedProcess
};
} catch (error) {
console.error('Error duplicating process:', error);
// Handle specific Prisma errors
if (error.code === 'P2025') {
return {
success: false,
error: 'Source process not found'
};
}
return {
success: false,
error: 'Failed to duplicate process',
details: process.env.NODE_ENV === 'development' ? error.message : undefined
};
}
});