336 lines
9.7 KiB
Markdown
336 lines
9.7 KiB
Markdown
# 채번규칙 테이블 기반 자동 감지 구현 완료
|
|
|
|
## 📋 변경 요청사항
|
|
|
|
**요구사항**: 채번 규칙을 더 간단하게 만들기
|
|
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)
|
|
|
|
```sql
|
|
-- 모든 기존 규칙을 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 쿼리 단순화
|
|
|
|
**수정된 서비스 메서드**:
|
|
```typescript
|
|
async getAvailableRulesForScreen(
|
|
companyCode: string,
|
|
tableName: string
|
|
): Promise<NumberingRuleConfig[]> {
|
|
// menuObjid 제거, tableName만 사용
|
|
// WHERE table_name = $1 AND company_code = $2
|
|
}
|
|
```
|
|
|
|
**수정된 API 엔드포인트**:
|
|
```typescript
|
|
GET /api/numbering-rules/available-for-screen?tableName=item_info
|
|
// menuObjid 파라미터 제거
|
|
```
|
|
|
|
### 3. 프론트엔드 API 클라이언트 수정
|
|
|
|
**파일**: `frontend/lib/api/numberingRule.ts`
|
|
|
|
#### 주요 변경사항:
|
|
- `menuObjid` 파라미터 제거
|
|
- 테이블명만 전달
|
|
|
|
```typescript
|
|
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 추가
|
|
```typescript
|
|
interface NumberingRuleDesignerProps {
|
|
// ... 기존 props
|
|
currentTableName?: string; // 현재 화면의 테이블명 자동 전달
|
|
}
|
|
```
|
|
|
|
##### ✅ 새 규칙 생성 시 자동 설정
|
|
```typescript
|
|
const handleNewRule = useCallback(() => {
|
|
const newRule: NumberingRuleConfig = {
|
|
// ...
|
|
scopeType: "table", // 기본값 table로 고정
|
|
tableName: currentTableName || "", // 현재 테이블명 자동 설정
|
|
};
|
|
}, [currentTableName]);
|
|
```
|
|
|
|
##### ✅ 저장 시 자동 설정
|
|
```typescript
|
|
const handleSaveRule = useCallback(async () => {
|
|
const ruleToSave = {
|
|
...currentRule,
|
|
scopeType: "table" as const, // 항상 table로 고정
|
|
tableName: currentTableName || currentRule.tableName || "", // 자동 감지
|
|
};
|
|
|
|
// 백엔드에 저장
|
|
}, [currentRule, currentTableName]);
|
|
```
|
|
|
|
##### ✅ UI 변경: 적용 범위 선택 제거
|
|
**이전**:
|
|
```tsx
|
|
{/* 적용 범위 선택 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>
|
|
)}
|
|
```
|
|
|
|
**현재 (간소화)**:
|
|
```tsx
|
|
{/* 자동 감지된 테이블 정보 표시 (읽기 전용) */}
|
|
{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`만 사용
|
|
- 테이블명이 없으면 빈 배열 반환
|
|
|
|
```typescript
|
|
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. 데이터베이스 마이그레이션 실행 (필수)
|
|
|
|
```bash
|
|
# 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. 기존 데이터 마이그레이션 확인
|
|
|
|
마이그레이션 실행 후:
|
|
```sql
|
|
-- 모든 규칙이 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. 저장 → **자동으로 현재 테이블에 적용됨**
|
|
|
|
**시스템은**:
|
|
- 자동으로 현재 화면의 테이블명 감지
|
|
- 같은 테이블의 화면에서 규칙 자동 공유
|
|
- 오타 없는 정확한 매핑
|
|
|
|
완료! 🚀
|
|
|