diff --git a/backend-node/src/controllers/approvalController.ts b/backend-node/src/controllers/approvalController.ts index b96d1dc2..a63c8196 100644 --- a/backend-node/src/controllers/approvalController.ts +++ b/backend-node/src/controllers/approvalController.ts @@ -166,11 +166,15 @@ export class ApprovalDefinitionController { fields.push(`updated_by = $${idx++}`, `updated_at = NOW()`); params.push(req.user?.userId || "system"); + + // WHERE 절 파라미터 인덱스를 미리 계산 (쿼리 문자열 내 idx++ 호출 순서 보장) + const idIdx = idx++; + const ccIdx = idx++; params.push(id, companyCode); const [row] = await query( `UPDATE approval_definitions SET ${fields.join(", ")} - WHERE definition_id = $${idx++} AND company_code = $${idx++} RETURNING *`, + WHERE definition_id = $${idIdx} AND company_code = $${ccIdx} RETURNING *`, params ); @@ -395,11 +399,16 @@ export class ApprovalTemplateController { if (definition_id !== undefined) { fields.push(`definition_id = $${idx++}`); params.push(definition_id); } if (is_active !== undefined) { fields.push(`is_active = $${idx++}`); params.push(is_active); } fields.push(`updated_by = $${idx++}`, `updated_at = NOW()`); - params.push(userId, id, companyCode); + params.push(userId); + + // WHERE 절 파라미터 인덱스를 미리 계산 + const tmplIdx = idx++; + const ccIdx = idx++; + params.push(id, companyCode); const { rows } = await client.query( `UPDATE approval_line_templates SET ${fields.join(", ")} - WHERE template_id = $${idx++} AND company_code = $${idx++} RETURNING *`, + WHERE template_id = $${tmplIdx} AND company_code = $${ccIdx} RETURNING *`, params ); result = rows[0]; @@ -597,6 +606,18 @@ export class ApprovalRequestController { } const offset = (parseInt(page as string) - 1) * parseInt(limit as string); + + // 카운트 쿼리는 LIMIT/OFFSET 파라미터 없이 실행 + const countParams = [...params]; + const [countRow] = await query( + `SELECT COUNT(*) as total FROM approval_requests r + WHERE ${conditions.join(" AND ")}`, + countParams + ); + + // LIMIT/OFFSET 파라미터 인덱스를 미리 계산 + const limitIdx = idx++; + const offsetIdx = idx++; params.push(parseInt(limit as string), offset); const rows = await query( @@ -605,18 +626,10 @@ export class ApprovalRequestController { LEFT JOIN approval_definitions d ON r.definition_id = d.definition_id AND r.company_code = d.company_code WHERE ${conditions.join(" AND ")} ORDER BY r.created_at DESC - LIMIT $${idx++} OFFSET $${idx++}`, + LIMIT $${limitIdx} OFFSET $${offsetIdx}`, params ); - // 전체 건수 조회 - const countParams = params.slice(0, params.length - 2); - const [countRow] = await query( - `SELECT COUNT(*) as total FROM approval_requests r - WHERE ${conditions.join(" AND ")}`, - countParams - ); - return res.json({ success: true, data: rows, @@ -691,6 +704,9 @@ export class ApprovalRequestController { return res.status(400).json({ success: false, message: "제목과 대상 테이블은 필수입니다." }); } + // target_record_id는 NOT NULL 컬럼이므로 빈 값은 기본값으로 대체 + const safeTargetRecordId = target_record_id || "0"; + const userId = req.user?.userId || "system"; const userName = req.user?.userName || ""; const deptName = req.user?.deptName || ""; @@ -727,7 +743,7 @@ export class ApprovalRequestController { $7, $8, $9, $10, $11, $12, $7, NOW()) RETURNING *`, [ - title, description, definition_id, target_table, target_record_id || null, + title, description, definition_id, target_table, safeTargetRecordId, JSON.stringify(mergedRecordData), userId, userName, deptName, screen_id, button_component_id, companyCode, @@ -841,7 +857,7 @@ export class ApprovalRequestController { ) VALUES ($1, $2, $3, $4, $5, $6, $7, 1, $8, $9, $10, $11, $12, $13, $14, $15) RETURNING *`, [ - title, description, definition_id, target_table, target_record_id || null, + title, description, definition_id, target_table, safeTargetRecordId, JSON.stringify(mergedRecordData), initialStatus, totalSteps, storedApprovalType, userId, userName, deptName, screen_id, button_component_id, companyCode, diff --git a/run-playwright-test.sh b/run-playwright-test.sh new file mode 100644 index 00000000..c998006e --- /dev/null +++ b/run-playwright-test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +cd /Users/gbpark/ERP-node +./node_modules/.bin/playwright test ".agent-pipeline/browser-tests/e2e-test.spec.ts" --config=".agent-pipeline/browser-tests/playwright.config.ts" --reporter=line 2>&1 | tee /tmp/playwright-result.txt +echo "EXIT_CODE: $?" >> /tmp/playwright-result.txt