Files
vexplor/채번규칙_테이블기반_자동감지_구현_완료.md
kjs 4294fbf608 feat: 채번 규칙 테이블 기반 자동 필터링 구현
- 채번 규칙 scope_type을 table로 단순화
- 화면의 테이블명을 자동으로 감지하여 채번 규칙 필터링
- TextInputConfigPanel에 screenTableName prop 추가
- getAvailableNumberingRulesForScreen API로 테이블 기반 조회
- NumberingRuleDesigner에서 자동으로 테이블명 설정
- webTypeConfigConverter 유틸리티 추가 (기존 화면 호환성)
- AutoGenerationConfig 타입 개선 (enabled, options.numberingRuleId)
- 채번 규칙 선택 UI에서 ID 제거, 설명 추가
- 불필요한 console.log 제거

Backend:
- numberingRuleService: 테이블 기반 필터링 로직 구현
- numberingRuleController: available-for-screen 엔드포인트 수정

Frontend:
- TextInputConfigPanel: 테이블명 기반 채번 규칙 로드
- NumberingRuleDesigner: 적용 범위 UI 제거, 테이블명 자동 설정
- ScreenDesigner: webTypeConfig → autoGeneration 변환 로직 통합
- DetailSettingsPanel: autoGeneration 속성 매핑 개선
2025-11-07 14:27:07 +09:00

9.7 KiB

채번규칙 테이블 기반 자동 감지 구현 완료

📋 변경 요청사항

요구사항: 채번 규칙을 더 간단하게 만들기

  1. 기본값을 table로 설정
  2. 적용 범위 선택 UI 제거
  3. 현재 화면의 테이블을 자동으로 감지하여 저장

구현 완료 내역

1. 데이터베이스 마이그레이션

파일: db/migrations/046_update_numbering_rules_scope_type.sql

주요 변경사항:

  • 기존 모든 규칙을 table 타입으로 변경
  • scope_type 제약조건 단순화 (table만 지원)
  • 불필요한 제약조건 제거 (global, menu 관련)
  • 인덱스 최적화 (table_name + company_code)
-- 모든 기존 규칙을 table 타입으로 변경
UPDATE numbering_rules
SET scope_type = 'table'
WHERE scope_type IN ('global', 'menu');

-- table_name이 없는 규칙은 빈 문자열로 설정
UPDATE numbering_rules
SET table_name = ''
WHERE table_name IS NULL;

-- 제약조건: table 타입이면 table_name 필수
ALTER TABLE numbering_rules
ADD CONSTRAINT check_table_scope_requires_table_name
CHECK (
  (scope_type = 'table' AND table_name IS NOT NULL)
  OR scope_type != 'table'
);

-- 인덱스 최적화
CREATE INDEX IF NOT EXISTS idx_numbering_rules_table_company 
ON numbering_rules(table_name, company_code);

2. 백엔드 API 간소화

파일:

  • backend-node/src/services/numberingRuleService.ts
  • backend-node/src/controllers/numberingRuleController.ts

주요 변경사항:

  • menuObjid 파라미터 제거
  • 테이블명만으로 필터링 (tableName 필수)
  • SQL 쿼리 단순화

수정된 서비스 메서드:

async getAvailableRulesForScreen(
  companyCode: string,
  tableName: string
): Promise<NumberingRuleConfig[]> {
  // menuObjid 제거, tableName만 사용
  // WHERE table_name = $1 AND company_code = $2
}

수정된 API 엔드포인트:

GET /api/numbering-rules/available-for-screen?tableName=item_info
// menuObjid 파라미터 제거

3. 프론트엔드 API 클라이언트 수정

파일: frontend/lib/api/numberingRule.ts

주요 변경사항:

  • menuObjid 파라미터 제거
  • 테이블명만 전달
export async function getAvailableNumberingRulesForScreen(
  tableName: string // menuObjid 제거
): Promise<ApiResponse<NumberingRuleConfig[]>> {
  const response = await apiClient.get("/numbering-rules/available-for-screen", {
    params: { tableName },
  });
  return response.data;
}

4. 채번 규칙 디자이너 UI 대폭 간소화

파일: frontend/components/numbering-rule/NumberingRuleDesigner.tsx

주요 변경사항:

Props 추가
interface NumberingRuleDesignerProps {
  // ... 기존 props
  currentTableName?: string; // 현재 화면의 테이블명 자동 전달
}
새 규칙 생성 시 자동 설정
const handleNewRule = useCallback(() => {
  const newRule: NumberingRuleConfig = {
    // ...
    scopeType: "table", // 기본값 table로 고정
    tableName: currentTableName || "", // 현재 테이블명 자동 설정
  };
}, [currentTableName]);
저장 시 자동 설정
const handleSaveRule = useCallback(async () => {
  const ruleToSave = {
    ...currentRule,
    scopeType: "table" as const, // 항상 table로 고정
    tableName: currentTableName || currentRule.tableName || "", // 자동 감지
  };
  
  // 백엔드에 저장
}, [currentRule, currentTableName]);
UI 변경: 적용 범위 선택 제거

이전:

{/* 적용 범위 선택 Select */}
<Select value={scopeType}>
  <SelectItem value="global">전역</SelectItem>
  <SelectItem value="table">테이블별</SelectItem>
  <SelectItem value="menu">메뉴별</SelectItem>
</Select>

{/* 조건부: 테이블명 입력 */}
{scopeType === "table" && (
  <Input value={tableName} onChange={...} />
)}

{/* 조건부: 메뉴 선택 */}
{scopeType === "menu" && (
  <Select value={menuObjid}>...</Select>
)}

현재 (간소화):

{/* 자동 감지된 테이블 정보 표시 (읽기 전용) */}
{currentTableName && (
  <div className="space-y-2">
    <Label className="text-sm font-medium">적용 테이블</Label>
    <div className="flex h-9 items-center rounded-md border border-input bg-muted px-3 text-sm text-muted-foreground">
      {currentTableName}
    </div>
    <p className="text-muted-foreground text-xs">
       규칙은 현재 화면의 테이블({currentTableName}) 자동으로 적용됩니다
    </p>
  </div>
)}

5. 화면관리에서 테이블명 전달

파일: frontend/components/screen/panels/webtype-configs/TextTypeConfigPanel.tsx

주요 변경사항:

  • menuObjid 제거, tableName만 사용
  • 테이블명이 없으면 빈 배열 반환
useEffect(() => {
  const loadRules = async () => {
    if (tableName) {
      console.log("📋 테이블 기반 채번 규칙 조회:", { tableName });
      response = await getAvailableNumberingRulesForScreen(tableName);
    } else {
      console.warn("⚠️ 테이블명이 없어 채번 규칙을 조회할 수 없습니다");
      setNumberingRules([]);
      return;
    }
  };
}, [localValues.autoValueType, tableName]); // menuObjid 제거

📊 변경 전후 비교

이전 방식 (복잡)

  1. 사용자가 적용 범위 선택 (전역/테이블별/메뉴별)
  2. 테이블별 선택 시 → 테이블명 직접 입력
  3. 메뉴별 선택 시 → 메뉴 수동 선택
  4. 저장 시 입력한 정보로 저장

문제점:

  • UI가 복잡 (3단계 선택)
  • 사용자가 테이블명을 수동 입력해야 함
  • 오타 가능성
  • 메뉴 기반 필터링은 복잡하고 직관적이지 않음

현재 방식 (간단)

  1. 채번 규칙 디자이너 열기
  2. 규칙 이름과 파트 설정
  3. 저장 → 자동으로 현재 화면의 테이블명 저장됨

장점:

  • UI 단순 (적용 범위 선택 UI 제거)
  • 테이블명 자동 감지 (오타 없음)
  • 사용자는 규칙만 설계하면 됨
  • 같은 테이블을 사용하는 화면에서 자동으로 규칙 공유

🔍 작동 흐름

1. 채번 규칙 생성

사용자: "새 규칙" 버튼 클릭
  ↓
시스템: currentTableName (예: "item_info") 자동 감지
  ↓
규칙 생성: scopeType = "table", tableName = "item_info"
  ↓
저장 시: DB에 table_name = "item_info"로 저장됨

2. 화면관리에서 규칙 사용

사용자: 텍스트 필드 설정 → "자동값 유형" = "채번 규칙"
  ↓
시스템: 현재 화면의 테이블명 (예: "item_info") 가져옴
  ↓
API 호출: GET /api/numbering-rules/available-for-screen?tableName=item_info
  ↓
백엔드: WHERE table_name = 'item_info' AND company_code = 'COMPANY_A'
  ↓
응답: item_info 테이블에 대한 규칙 목록 반환
  ↓
UI: 드롭다운에 해당 규칙들만 표시

🎯 핵심 개선 포인트

사용자 경험 (UX)

  • 이전: 3단계 선택 (범위 → 테이블/메뉴 → 입력/선택)
  • 현재: 규칙만 설계 (테이블은 자동 감지)

오류 가능성

  • 이전: 테이블명 직접 입력 → 오타 발생 가능
  • 현재: 자동 감지 → 오타 불가능

직관성

  • 이전: "이 규칙은 어디에 적용되나요?" → 사용자가 이해해야 함
  • 현재: "현재 화면의 테이블에 자동 적용" → 자동으로 알맞게 적용

코드 복잡도

  • 이전: 3가지 scopeType 처리 (global, table, menu)
  • 현재: 1가지 scopeType만 처리 (table)

🚀 다음 단계

1. 데이터베이스 마이그레이션 실행 (필수)

# PostgreSQL 비밀번호 확인 후 실행
PGPASSWORD=<실제_비밀번호> psql -h localhost -U postgres -d ilshin \
  -f /Users/kimjuseok/ERP-node/db/migrations/046_update_numbering_rules_scope_type.sql

2. 통합 테스트

테스트 시나리오:

  1. 화면관리에서 item_info 테이블 선택
  2. 채번 규칙 컴포넌트 열기
  3. "새 규칙" 생성 → 자동으로 tableName = "item_info" 설정되는지 확인
  4. 규칙 저장 → DB에 scope_type = 'table', table_name = 'item_info'로 저장되는지 확인
  5. 텍스트 필드 설정 → "자동값 유형" = "채번 규칙" 선택
  6. 드롭다운에서 해당 규칙이 표시되는지 확인
  7. 다른 테이블 화면에서는 해당 규칙이 안 보이는지 확인

3. 기존 데이터 마이그레이션 확인

마이그레이션 실행 후:

-- 모든 규칙이 table 타입인지 확인
SELECT scope_type, COUNT(*) 
FROM numbering_rules 
GROUP BY scope_type;

-- 결과: scope_type='table'만 나와야 함

-- table_name이 비어있는 규칙 확인
SELECT rule_id, rule_name, table_name 
FROM numbering_rules 
WHERE table_name = '' OR table_name IS NULL;

-- 결과: 비어있는 규칙이 있다면 수동 업데이트 필요

📝 변경된 파일 목록

데이터베이스

  • db/migrations/046_update_numbering_rules_scope_type.sql (수정)

백엔드

  • backend-node/src/services/numberingRuleService.ts (간소화)
  • backend-node/src/controllers/numberingRuleController.ts (간소화)

프론트엔드

  • frontend/lib/api/numberingRule.ts (간소화)
  • frontend/components/numbering-rule/NumberingRuleDesigner.tsx (대폭 간소화)
  • frontend/components/screen/panels/webtype-configs/TextTypeConfigPanel.tsx (간소화)

🎉 결론

채번 규칙 시스템이 대폭 간소화되었습니다!

이제 사용자는:

  1. 화면관리에서 테이블 선택
  2. 채번 규칙 디자이너에서 규칙 설계
  3. 저장 → 자동으로 현재 테이블에 적용됨

시스템은:

  • 자동으로 현재 화면의 테이블명 감지
  • 같은 테이블의 화면에서 규칙 자동 공유
  • 오타 없는 정확한 매핑

완료! 🚀