제어관리 회사코드 저장 안되는 문제 수정
This commit is contained in:
@@ -218,46 +218,62 @@ router.delete("/:flowId", async (req: Request, res: Response) => {
|
|||||||
* 플로우 실행
|
* 플로우 실행
|
||||||
* POST /api/dataflow/node-flows/:flowId/execute
|
* POST /api/dataflow/node-flows/:flowId/execute
|
||||||
*/
|
*/
|
||||||
router.post("/:flowId/execute", authenticateToken, async (req: AuthenticatedRequest, res: Response) => {
|
router.post(
|
||||||
try {
|
"/:flowId/execute",
|
||||||
const { flowId } = req.params;
|
authenticateToken,
|
||||||
const contextData = req.body;
|
async (req: AuthenticatedRequest, res: Response) => {
|
||||||
|
try {
|
||||||
|
const { flowId } = req.params;
|
||||||
|
const contextData = req.body;
|
||||||
|
|
||||||
logger.info(`🚀 플로우 실행 요청: flowId=${flowId}`, {
|
logger.info(`🚀 플로우 실행 요청: flowId=${flowId}`, {
|
||||||
contextDataKeys: Object.keys(contextData),
|
contextDataKeys: Object.keys(contextData),
|
||||||
userId: req.user?.userId,
|
userId: req.user?.userId,
|
||||||
companyCode: req.user?.companyCode,
|
companyCode: req.user?.companyCode,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 사용자 정보를 contextData에 추가
|
// 🔍 디버깅: req.user 전체 확인
|
||||||
const enrichedContextData = {
|
logger.info(`🔍 req.user 전체 정보:`, {
|
||||||
...contextData,
|
user: req.user,
|
||||||
userId: req.user?.userId,
|
hasUser: !!req.user,
|
||||||
userName: req.user?.userName,
|
});
|
||||||
companyCode: req.user?.companyCode,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 플로우 실행
|
// 사용자 정보를 contextData에 추가
|
||||||
const result = await NodeFlowExecutionService.executeFlow(
|
const enrichedContextData = {
|
||||||
parseInt(flowId, 10),
|
...contextData,
|
||||||
enrichedContextData
|
userId: req.user?.userId,
|
||||||
);
|
userName: req.user?.userName,
|
||||||
|
companyCode: req.user?.companyCode,
|
||||||
|
};
|
||||||
|
|
||||||
return res.json({
|
// 🔍 디버깅: enrichedContextData 확인
|
||||||
success: result.success,
|
logger.info(`🔍 enrichedContextData:`, {
|
||||||
message: result.message,
|
userId: enrichedContextData.userId,
|
||||||
data: result,
|
companyCode: enrichedContextData.companyCode,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
logger.error("플로우 실행 실패:", error);
|
// 플로우 실행
|
||||||
return res.status(500).json({
|
const result = await NodeFlowExecutionService.executeFlow(
|
||||||
success: false,
|
parseInt(flowId, 10),
|
||||||
message:
|
enrichedContextData
|
||||||
error instanceof Error
|
);
|
||||||
? error.message
|
|
||||||
: "플로우 실행 중 오류가 발생했습니다.",
|
return res.json({
|
||||||
});
|
success: result.success,
|
||||||
|
message: result.message,
|
||||||
|
data: result,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("플로우 실행 실패:", error);
|
||||||
|
return res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
message:
|
||||||
|
error instanceof Error
|
||||||
|
? error.message
|
||||||
|
: "플로우 실행 중 오류가 발생했습니다.",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -754,12 +754,19 @@ export class DynamicFormService {
|
|||||||
|
|
||||||
// 🎯 제어관리 실행 (새로 추가)
|
// 🎯 제어관리 실행 (새로 추가)
|
||||||
try {
|
try {
|
||||||
|
// savedData 또는 insertedRecord에서 company_code 추출
|
||||||
|
const recordCompanyCode =
|
||||||
|
(insertedRecord as Record<string, any>)?.company_code ||
|
||||||
|
dataToInsert.company_code ||
|
||||||
|
"*";
|
||||||
|
|
||||||
await this.executeDataflowControlIfConfigured(
|
await this.executeDataflowControlIfConfigured(
|
||||||
screenId,
|
screenId,
|
||||||
tableName,
|
tableName,
|
||||||
insertedRecord as Record<string, any>,
|
insertedRecord as Record<string, any>,
|
||||||
"insert",
|
"insert",
|
||||||
created_by || "system"
|
created_by || "system",
|
||||||
|
recordCompanyCode
|
||||||
);
|
);
|
||||||
} catch (controlError) {
|
} catch (controlError) {
|
||||||
console.error("⚠️ 제어관리 실행 오류:", controlError);
|
console.error("⚠️ 제어관리 실행 오류:", controlError);
|
||||||
@@ -1107,12 +1114,19 @@ export class DynamicFormService {
|
|||||||
|
|
||||||
// 🎯 제어관리 실행 (UPDATE 트리거)
|
// 🎯 제어관리 실행 (UPDATE 트리거)
|
||||||
try {
|
try {
|
||||||
|
// updatedRecord에서 company_code 추출
|
||||||
|
const recordCompanyCode =
|
||||||
|
(updatedRecord as Record<string, any>)?.company_code ||
|
||||||
|
company_code ||
|
||||||
|
"*";
|
||||||
|
|
||||||
await this.executeDataflowControlIfConfigured(
|
await this.executeDataflowControlIfConfigured(
|
||||||
0, // UPDATE는 screenId를 알 수 없으므로 0으로 설정 (추후 개선 필요)
|
0, // UPDATE는 screenId를 알 수 없으므로 0으로 설정 (추후 개선 필요)
|
||||||
tableName,
|
tableName,
|
||||||
updatedRecord as Record<string, any>,
|
updatedRecord as Record<string, any>,
|
||||||
"update",
|
"update",
|
||||||
updated_by || "system"
|
updated_by || "system",
|
||||||
|
recordCompanyCode
|
||||||
);
|
);
|
||||||
} catch (controlError) {
|
} catch (controlError) {
|
||||||
console.error("⚠️ 제어관리 실행 오류:", controlError);
|
console.error("⚠️ 제어관리 실행 오류:", controlError);
|
||||||
@@ -1251,12 +1265,17 @@ export class DynamicFormService {
|
|||||||
try {
|
try {
|
||||||
if (result && Array.isArray(result) && result.length > 0) {
|
if (result && Array.isArray(result) && result.length > 0) {
|
||||||
const deletedRecord = result[0] as Record<string, any>;
|
const deletedRecord = result[0] as Record<string, any>;
|
||||||
|
// deletedRecord에서 company_code 추출
|
||||||
|
const recordCompanyCode =
|
||||||
|
deletedRecord?.company_code || companyCode || "*";
|
||||||
|
|
||||||
await this.executeDataflowControlIfConfigured(
|
await this.executeDataflowControlIfConfigured(
|
||||||
0, // DELETE는 screenId를 알 수 없으므로 0으로 설정 (추후 개선 필요)
|
0, // DELETE는 screenId를 알 수 없으므로 0으로 설정 (추후 개선 필요)
|
||||||
tableName,
|
tableName,
|
||||||
deletedRecord,
|
deletedRecord,
|
||||||
"delete",
|
"delete",
|
||||||
userId || "system"
|
userId || "system",
|
||||||
|
recordCompanyCode
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (controlError) {
|
} catch (controlError) {
|
||||||
@@ -1562,7 +1581,8 @@ export class DynamicFormService {
|
|||||||
tableName: string,
|
tableName: string,
|
||||||
savedData: Record<string, any>,
|
savedData: Record<string, any>,
|
||||||
triggerType: "insert" | "update" | "delete",
|
triggerType: "insert" | "update" | "delete",
|
||||||
userId: string = "system"
|
userId: string = "system",
|
||||||
|
companyCode: string = "*"
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
try {
|
try {
|
||||||
console.log(`🎯 제어관리 설정 확인 중... (screenId: ${screenId})`);
|
console.log(`🎯 제어관리 설정 확인 중... (screenId: ${screenId})`);
|
||||||
@@ -1636,6 +1656,7 @@ export class DynamicFormService {
|
|||||||
buttonId: "save-button",
|
buttonId: "save-button",
|
||||||
screenId: screenId,
|
screenId: screenId,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
|
companyCode: companyCode,
|
||||||
formData: savedData,
|
formData: savedData,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -117,6 +117,18 @@ export class NodeFlowExecutionService {
|
|||||||
try {
|
try {
|
||||||
logger.info(`🚀 플로우 실행 시작: flowId=${flowId}`);
|
logger.info(`🚀 플로우 실행 시작: flowId=${flowId}`);
|
||||||
|
|
||||||
|
// 🔍 디버깅: contextData 상세 로그
|
||||||
|
logger.info(`🔍 contextData 상세:`, {
|
||||||
|
directCompanyCode: contextData.companyCode,
|
||||||
|
nestedCompanyCode: contextData.context?.companyCode,
|
||||||
|
directUserId: contextData.userId,
|
||||||
|
nestedUserId: contextData.context?.userId,
|
||||||
|
contextKeys: Object.keys(contextData),
|
||||||
|
nestedContextKeys: contextData.context
|
||||||
|
? Object.keys(contextData.context)
|
||||||
|
: "no nested context",
|
||||||
|
});
|
||||||
|
|
||||||
// 1. 플로우 데이터 조회
|
// 1. 플로우 데이터 조회
|
||||||
const flow = await queryOne<{
|
const flow = await queryOne<{
|
||||||
flow_id: number;
|
flow_id: number;
|
||||||
@@ -979,12 +991,25 @@ export class NodeFlowExecutionService {
|
|||||||
const userId = context.buttonContext?.userId;
|
const userId = context.buttonContext?.userId;
|
||||||
const companyCode = context.buttonContext?.companyCode;
|
const companyCode = context.buttonContext?.companyCode;
|
||||||
|
|
||||||
|
// 🔍 디버깅: 자동 추가 조건 확인
|
||||||
|
console.log(` 🔍 INSERT 자동 추가 조건 확인:`, {
|
||||||
|
hasWriterMapping,
|
||||||
|
hasCompanyCodeMapping,
|
||||||
|
userId,
|
||||||
|
companyCode,
|
||||||
|
buttonContext: context.buttonContext,
|
||||||
|
});
|
||||||
|
|
||||||
// writer 자동 추가 (매핑에 없고, 컨텍스트에 userId가 있는 경우)
|
// writer 자동 추가 (매핑에 없고, 컨텍스트에 userId가 있는 경우)
|
||||||
if (!hasWriterMapping && userId) {
|
if (!hasWriterMapping && userId) {
|
||||||
fields.push("writer");
|
fields.push("writer");
|
||||||
values.push(userId);
|
values.push(userId);
|
||||||
insertedData.writer = userId;
|
insertedData.writer = userId;
|
||||||
console.log(` 🔧 자동 추가: writer = ${userId}`);
|
console.log(` 🔧 자동 추가: writer = ${userId}`);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
` ⚠️ writer 자동 추가 스킵: hasWriterMapping=${hasWriterMapping}, userId=${userId}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// company_code 자동 추가 (매핑에 없고, 컨텍스트에 companyCode가 있는 경우)
|
// company_code 자동 추가 (매핑에 없고, 컨텍스트에 companyCode가 있는 경우)
|
||||||
@@ -993,6 +1018,10 @@ export class NodeFlowExecutionService {
|
|||||||
values.push(companyCode);
|
values.push(companyCode);
|
||||||
insertedData.company_code = companyCode;
|
insertedData.company_code = companyCode;
|
||||||
console.log(` 🔧 자동 추가: company_code = ${companyCode}`);
|
console.log(` 🔧 자동 추가: company_code = ${companyCode}`);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
` ⚠️ company_code 자동 추가 스킵: hasCompanyCodeMapping=${hasCompanyCodeMapping}, companyCode=${companyCode}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sql = `
|
const sql = `
|
||||||
@@ -2251,6 +2280,34 @@ export class NodeFlowExecutionService {
|
|||||||
values.push(value);
|
values.push(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 🆕 writer와 company_code 자동 추가 (필드 매핑에 없는 경우)
|
||||||
|
const hasWriterMapping = fieldMappings.some(
|
||||||
|
(m: any) => m.targetField === "writer"
|
||||||
|
);
|
||||||
|
const hasCompanyCodeMapping = fieldMappings.some(
|
||||||
|
(m: any) => m.targetField === "company_code"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 컨텍스트에서 사용자 정보 추출
|
||||||
|
const userId = context.buttonContext?.userId;
|
||||||
|
const companyCode = context.buttonContext?.companyCode;
|
||||||
|
|
||||||
|
// writer 자동 추가 (매핑에 없고, 컨텍스트에 userId가 있는 경우)
|
||||||
|
if (!hasWriterMapping && userId) {
|
||||||
|
columns.push("writer");
|
||||||
|
values.push(userId);
|
||||||
|
logger.info(` 🔧 UPSERT INSERT - 자동 추가: writer = ${userId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// company_code 자동 추가 (매핑에 없고, 컨텍스트에 companyCode가 있는 경우)
|
||||||
|
if (!hasCompanyCodeMapping && companyCode && companyCode !== "*") {
|
||||||
|
columns.push("company_code");
|
||||||
|
values.push(companyCode);
|
||||||
|
logger.info(
|
||||||
|
` 🔧 UPSERT INSERT - 자동 추가: company_code = ${companyCode}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
||||||
const insertSql = `
|
const insertSql = `
|
||||||
INSERT INTO ${targetTable} (${columns.join(", ")})
|
INSERT INTO ${targetTable} (${columns.join(", ")})
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -95,11 +95,11 @@ export interface RightPanelConfig {
|
|||||||
actionButtons?: ActionButtonConfig[]; // 복수 액션 버튼 배열
|
actionButtons?: ActionButtonConfig[]; // 복수 액션 버튼 배열
|
||||||
primaryKeyColumn?: string; // 기본키 컬럼명 (수정/삭제용, 기본: id)
|
primaryKeyColumn?: string; // 기본키 컬럼명 (수정/삭제용, 기본: id)
|
||||||
emptyMessage?: string; // 데이터 없을 때 메시지
|
emptyMessage?: string; // 데이터 없을 때 메시지
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 추가 조인 테이블 설정
|
* 추가 조인 테이블 설정
|
||||||
* 메인 테이블에 다른 테이블을 JOIN하여 추가 정보를 함께 표시합니다.
|
* 메인 테이블에 다른 테이블을 JOIN하여 추가 정보를 함께 표시합니다.
|
||||||
*
|
*
|
||||||
* 사용 예시:
|
* 사용 예시:
|
||||||
* - 메인 테이블: user_dept (부서-사용자 관계)
|
* - 메인 테이블: user_dept (부서-사용자 관계)
|
||||||
* - 조인 테이블: user_info (사용자 개인정보)
|
* - 조인 테이블: user_info (사용자 개인정보)
|
||||||
@@ -109,19 +109,28 @@ export interface RightPanelConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 조인 설정
|
* 조인 키 설정 (복합키 지원)
|
||||||
*/
|
*/
|
||||||
export interface JoinConfig {
|
export interface JoinKey {
|
||||||
leftColumn: string; // 좌측 테이블의 조인 컬럼
|
leftColumn: string; // 좌측 테이블의 조인 컬럼
|
||||||
rightColumn: string; // 우측 테이블의 조인 컬럼
|
rightColumn: string; // 우측 테이블의 조인 컬럼
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 조인 설정
|
||||||
|
*/
|
||||||
|
export interface JoinConfig {
|
||||||
|
leftColumn?: string; // 좌측 테이블의 조인 컬럼 (단일키 - 하위 호환성)
|
||||||
|
rightColumn?: string; // 우측 테이블의 조인 컬럼 (단일키 - 하위 호환성)
|
||||||
|
keys?: JoinKey[]; // 복합키 지원 (여러 컬럼으로 조인)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 추가 조인 테이블 설정
|
* 추가 조인 테이블 설정
|
||||||
* 우측 패널의 메인 테이블에 다른 테이블을 JOIN하여 추가 컬럼을 가져옵니다.
|
* 우측 패널의 메인 테이블에 다른 테이블을 JOIN하여 추가 컬럼을 가져옵니다.
|
||||||
*
|
*
|
||||||
* 예시: user_dept (메인) + user_info (조인) → 부서관계 + 개인정보 함께 표시
|
* 예시: user_dept (메인) + user_info (조인) → 부서관계 + 개인정보 함께 표시
|
||||||
*
|
*
|
||||||
* - joinTable: 조인할 테이블명 (예: user_info)
|
* - joinTable: 조인할 테이블명 (예: user_info)
|
||||||
* - joinType: 조인 방식 (LEFT JOIN 권장)
|
* - joinType: 조인 방식 (LEFT JOIN 권장)
|
||||||
* - mainColumn: 메인 테이블의 조인 컬럼 (예: user_id)
|
* - mainColumn: 메인 테이블의 조인 컬럼 (예: user_id)
|
||||||
|
|||||||
Reference in New Issue
Block a user