flow-widgdt 인라인 편집 및 검색 하이라이트 기능 추가
This commit is contained in:
@@ -837,4 +837,53 @@ export class FlowController {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 스텝 데이터 업데이트 (인라인 편집)
|
||||
*/
|
||||
updateStepData = async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const { flowId, stepId, recordId } = req.params;
|
||||
const updateData = req.body;
|
||||
const userId = (req as any).user?.userId || "system";
|
||||
const userCompanyCode = (req as any).user?.companyCode;
|
||||
|
||||
if (!flowId || !stepId || !recordId) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "flowId, stepId, and recordId are required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!updateData || Object.keys(updateData).length === 0) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: "Update data is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await this.flowExecutionService.updateStepData(
|
||||
parseInt(flowId),
|
||||
parseInt(stepId),
|
||||
recordId,
|
||||
updateData,
|
||||
userId,
|
||||
userCompanyCode
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: "Data updated successfully",
|
||||
data: result,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error("Error updating step data:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message || "Failed to update step data",
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ router.get("/:flowId/steps/counts", flowController.getAllStepCounts);
|
||||
router.post("/move", flowController.moveData);
|
||||
router.post("/move-batch", flowController.moveBatchData);
|
||||
|
||||
// ==================== 스텝 데이터 수정 (인라인 편집) ====================
|
||||
router.put("/:flowId/step/:stepId/data/:recordId", flowController.updateStepData);
|
||||
|
||||
// ==================== 오딧 로그 ====================
|
||||
router.get("/audit/:flowId/:recordId", flowController.getAuditLogs);
|
||||
router.get("/audit/:flowId", flowController.getFlowAuditLogs);
|
||||
|
||||
@@ -263,4 +263,115 @@ export class FlowExecutionService {
|
||||
tableName: result[0].table_name,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 스텝 데이터 업데이트 (인라인 편집)
|
||||
* 원본 테이블의 데이터를 직접 업데이트합니다.
|
||||
*/
|
||||
async updateStepData(
|
||||
flowId: number,
|
||||
stepId: number,
|
||||
recordId: string,
|
||||
updateData: Record<string, any>,
|
||||
userId: string,
|
||||
companyCode?: string
|
||||
): Promise<{ success: boolean }> {
|
||||
try {
|
||||
// 1. 플로우 정의 조회
|
||||
const flowDef = await this.flowDefinitionService.findById(flowId);
|
||||
if (!flowDef) {
|
||||
throw new Error(`Flow definition not found: ${flowId}`);
|
||||
}
|
||||
|
||||
// 2. 스텝 조회
|
||||
const step = await this.flowStepService.findById(stepId);
|
||||
if (!step) {
|
||||
throw new Error(`Flow step not found: ${stepId}`);
|
||||
}
|
||||
|
||||
// 3. 테이블명 결정
|
||||
const tableName = step.tableName || flowDef.tableName;
|
||||
if (!tableName) {
|
||||
throw new Error("Table name not found");
|
||||
}
|
||||
|
||||
// 4. Primary Key 컬럼 결정 (기본값: id)
|
||||
const primaryKeyColumn = flowDef.primaryKey || "id";
|
||||
|
||||
console.log(`🔍 [updateStepData] Updating table: ${tableName}, PK: ${primaryKeyColumn}=${recordId}`);
|
||||
|
||||
// 5. SET 절 생성
|
||||
const updateColumns = Object.keys(updateData);
|
||||
if (updateColumns.length === 0) {
|
||||
throw new Error("No columns to update");
|
||||
}
|
||||
|
||||
// 6. 외부 DB vs 내부 DB 구분
|
||||
if (flowDef.dbSourceType === "external" && flowDef.dbConnectionId) {
|
||||
// 외부 DB 업데이트
|
||||
console.log("✅ [updateStepData] Using EXTERNAL DB:", flowDef.dbConnectionId);
|
||||
|
||||
// 외부 DB 연결 정보 조회
|
||||
const connectionResult = await db.query(
|
||||
"SELECT * FROM external_db_connection WHERE id = $1",
|
||||
[flowDef.dbConnectionId]
|
||||
);
|
||||
|
||||
if (connectionResult.length === 0) {
|
||||
throw new Error(`External DB connection not found: ${flowDef.dbConnectionId}`);
|
||||
}
|
||||
|
||||
const connection = connectionResult[0];
|
||||
const dbType = connection.db_type?.toLowerCase();
|
||||
|
||||
// DB 타입에 따른 placeholder 및 쿼리 생성
|
||||
let setClause: string;
|
||||
let params: any[];
|
||||
|
||||
if (dbType === "mysql" || dbType === "mariadb") {
|
||||
// MySQL/MariaDB: ? placeholder
|
||||
setClause = updateColumns.map((col) => `\`${col}\` = ?`).join(", ");
|
||||
params = [...Object.values(updateData), recordId];
|
||||
} else if (dbType === "mssql") {
|
||||
// MSSQL: @p1, @p2 placeholder
|
||||
setClause = updateColumns.map((col, idx) => `[${col}] = @p${idx + 1}`).join(", ");
|
||||
params = [...Object.values(updateData), recordId];
|
||||
} else {
|
||||
// PostgreSQL: $1, $2 placeholder
|
||||
setClause = updateColumns.map((col, idx) => `"${col}" = $${idx + 1}`).join(", ");
|
||||
params = [...Object.values(updateData), recordId];
|
||||
}
|
||||
|
||||
const updateQuery = `UPDATE ${tableName} SET ${setClause} WHERE ${primaryKeyColumn} = ${dbType === "mysql" || dbType === "mariadb" ? "?" : dbType === "mssql" ? `@p${params.length}` : `$${params.length}`}`;
|
||||
|
||||
console.log(`📝 [updateStepData] Query: ${updateQuery}`);
|
||||
console.log(`📝 [updateStepData] Params:`, params);
|
||||
|
||||
await executeExternalQuery(flowDef.dbConnectionId, updateQuery, params);
|
||||
} else {
|
||||
// 내부 DB 업데이트
|
||||
console.log("✅ [updateStepData] Using INTERNAL DB");
|
||||
|
||||
const setClause = updateColumns.map((col, idx) => `"${col}" = $${idx + 1}`).join(", ");
|
||||
const params = [...Object.values(updateData), recordId];
|
||||
|
||||
const updateQuery = `UPDATE "${tableName}" SET ${setClause} WHERE "${primaryKeyColumn}" = $${params.length}`;
|
||||
|
||||
console.log(`📝 [updateStepData] Query: ${updateQuery}`);
|
||||
console.log(`📝 [updateStepData] Params:`, params);
|
||||
|
||||
await db.query(updateQuery, params);
|
||||
}
|
||||
|
||||
console.log(`✅ [updateStepData] Data updated successfully: ${tableName}.${primaryKeyColumn}=${recordId}`, {
|
||||
updatedFields: updateColumns,
|
||||
userId,
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
} catch (error: any) {
|
||||
console.error("❌ [updateStepData] Error:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user