feat(pop): 입고 확정 시 자동 채번 실행 + 결과 모달 UX + 셀렉트 높이 통일
입고 확정(inbound-confirm) 실행 시 채번 규칙이 설정되어 있어도 inbound_number가 null로 저장되던 문제를 해결한다. [채번 실행 (FIX-1)] - types.ts: SaveMapping에 autoGenMappings 필드 추가 (numberingRuleId, targetColumn, showResultModal) - PopFieldComponent: collect_data 응답에 autoGenMappings 포함하여 백엔드에 채번 규칙 정보 전달 - popActionRoutes: INSERT 전 numberingRuleService.allocateCode() 호출, 생성된 코드를 generatedCodes 배열로 응답에 포함 [결과 모달 UX] - pop-button: showResultModal 토글에 따라 채번 결과 모달 표시 분기 - 모달이 열려 있는 동안 followUpActions(refresh/navigate) 지연하여 사용자가 확인 버튼을 눌러야 후속 액션 실행 [셀렉트 높이 일관성] - SelectTrigger hasCustomHeight에 /\bh-\d/ 패턴 추가하여 className의 h-9 등이 기본 data-size="xs"(h-6)와 충돌하지 않도록 수정 [기타 수정] - SelectFieldInput: Set 기반 dedup으로 React key 중복 방지 - PopFieldConfig: AutoNumberEditor 제거, 채번 규칙을 저장 탭에서 관리 - PopFieldConfig: 전체 채번 규칙 보기 토글 추가 - PopCardListComponent: 장바구니 목록 모드에서 수량 자동 초기화 방지 - PopCardListConfig: 수식 필드 매핑 노출 + 누락 필드 자동 추가
This commit is contained in:
@@ -2,6 +2,7 @@ import { Router, Request, Response } from "express";
|
||||
import { getPool } from "../database/db";
|
||||
import logger from "../utils/logger";
|
||||
import { authenticateToken } from "../middleware/authMiddleware";
|
||||
import { numberingRuleService } from "../services/numberingRuleService";
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -12,9 +13,16 @@ function isSafeIdentifier(name: string): boolean {
|
||||
return SAFE_IDENTIFIER.test(name);
|
||||
}
|
||||
|
||||
interface AutoGenMappingInfo {
|
||||
numberingRuleId: string;
|
||||
targetColumn: string;
|
||||
showResultModal?: boolean;
|
||||
}
|
||||
|
||||
interface MappingInfo {
|
||||
targetTable: string;
|
||||
columnMapping: Record<string, string>;
|
||||
autoGenMappings?: AutoGenMappingInfo[];
|
||||
}
|
||||
|
||||
interface StatusConditionRule {
|
||||
@@ -114,6 +122,7 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
|
||||
let processedCount = 0;
|
||||
let insertedCount = 0;
|
||||
const generatedCodes: Array<{ targetColumn: string; code: string }> = [];
|
||||
|
||||
if (action === "inbound-confirm") {
|
||||
// 1. 매핑 기반 INSERT (장바구니 데이터 -> 대상 테이블)
|
||||
@@ -144,6 +153,37 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
}
|
||||
}
|
||||
|
||||
// 채번 규칙 실행: field + cardList의 autoGenMappings에서 코드 발급
|
||||
const allAutoGen = [
|
||||
...(fieldMapping?.autoGenMappings ?? []),
|
||||
...(cardMapping?.autoGenMappings ?? []),
|
||||
];
|
||||
for (const ag of allAutoGen) {
|
||||
if (!ag.numberingRuleId || !ag.targetColumn) continue;
|
||||
if (!isSafeIdentifier(ag.targetColumn)) continue;
|
||||
if (columns.includes(`"${ag.targetColumn}"`)) continue;
|
||||
try {
|
||||
const generatedCode = await numberingRuleService.allocateCode(
|
||||
ag.numberingRuleId,
|
||||
companyCode,
|
||||
{ ...fieldValues, ...item },
|
||||
);
|
||||
columns.push(`"${ag.targetColumn}"`);
|
||||
values.push(generatedCode);
|
||||
generatedCodes.push({ targetColumn: ag.targetColumn, code: generatedCode, showResultModal: ag.showResultModal ?? false });
|
||||
logger.info("[pop/execute-action] 채번 완료", {
|
||||
ruleId: ag.numberingRuleId,
|
||||
targetColumn: ag.targetColumn,
|
||||
generatedCode,
|
||||
});
|
||||
} catch (err: any) {
|
||||
logger.error("[pop/execute-action] 채번 실패", {
|
||||
ruleId: ag.numberingRuleId,
|
||||
error: err.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (columns.length > 1) {
|
||||
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
||||
const sql = `INSERT INTO "${cardMapping.targetTable}" (${columns.join(", ")}) VALUES (${placeholders})`;
|
||||
@@ -263,7 +303,7 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
return res.json({
|
||||
success: true,
|
||||
message: `${processedCount}건 처리 완료${insertedCount > 0 ? `, ${insertedCount}건 생성` : ""}`,
|
||||
data: { processedCount, insertedCount },
|
||||
data: { processedCount, insertedCount, generatedCodes },
|
||||
});
|
||||
} catch (error: any) {
|
||||
await client.query("ROLLBACK");
|
||||
|
||||
Reference in New Issue
Block a user