# 채번규칙 (Numbering Rules) > **작성일**: 2026-02-27 > **상태**: 운영 중 > **최종 갱신**: 2026-03-17 --- ## 1. 개요 ### 1.1 목적 문서 번호(견적번호, 수주번호, 원자재 로트번호 등)를 규칙 기반으로 자동 생성하는 내부 서비스. 테넌트별로 채번 규칙을 설정하면, 해당 규칙에 따라 일련번호가 자동 생성된다. 규칙이 없는 경우 레거시 포맷으로 폴백. ### 1.2 핵심 원칙 - 유연한 패턴 기반 번호 생성 (6가지 세그먼트 유형) - Atomic UPSERT로 동시성 안전 시퀀스 관리 - 기간별 자동 리셋 (일/월/년/무제한) - 미리보기 기능 (DB 업데이트 없음) - 규칙 미설정 시 레거시 로직 자동 폴백 --- ## 2. 모델 | 모델 | 테이블 | 설명 | |------|--------|------| | `NumberingRule` | `numbering_rules` | 채번 규칙 정의 (document_type, pattern, reset_period) | | — | `numbering_sequences` | 일련번호 카운터 (tenant + type + scope + period) | **지원 문서 유형:** | 코드 | 한글 | 사용처 | |------|------|--------| | `quote` | 견적 | `QuoteNumberService` | | `order` | 수주 | `OrderService` | | `sale` | 매출 | (예정) | | `work_order` | 작업지시 | (예정) | | `material_receipt` | 원자재수입검사 | `ReceivingService` | **리셋 주기:** | 코드 | 설명 | period_key 예시 | |------|------|----------------| | `daily` | 매일 01부터 리셋 | `260317` | | `monthly` | 매월 01부터 리셋 | `202603` | | `yearly` | 매년 01부터 리셋 | `2026` | | `never` | 리셋 없이 계속 증가 | `all` | --- ## 3. 패턴 구조 패턴은 JSON 배열로 세그먼트를 정의한다. ### 3.1 세그먼트 유형 | 세그먼트 | 설명 | 예시 | |---------|------|------| | `static` | 고정 문자열 | `{ "type": "static", "value": "KD" }` | | `separator` | 구분자 | `{ "type": "separator", "value": "-" }` | | `date` | 날짜 포맷 (PHP date) | `{ "type": "date", "format": "ymd" }` → `260317` | | `sequence` | 일련번호 (자릿수는 rule 레벨) | `{ "type": "sequence" }` | | `param` | 외부 파라미터 | `{ "type": "param", "key": "pair_code", "default": "SS" }` | | `mapping` | 값 → 코드 매핑 | `{ "type": "mapping", "key": "category", "map": {"SCREEN": "SC"}, "default": "XX" }` | ### 3.2 date 포맷 예시 | format | 결과 | 설명 | |--------|------|------| | `ymd` | `260317` | 2자리 연+월+일 | | `Ymd` | `20260317` | 4자리 연+월+일 | | `ym` | `2603` | 2자리 연+월 | | `Y` | `2026` | 4자리 연도 | --- ## 4. MNG 채번규칙 관리 ### 4.1 접근 경로 ``` MNG > 권한 관리 > 채번 규칙 관리 URL: admin.codebridge-x.com/numbering-rules ``` ### 4.2 관리 화면 기능 | 기능 | 설명 | |------|------| | 목록 조회 | 문서유형, 상태 필터 + 규칙명 검색 | | 새 규칙 | 패턴 세그먼트 편집기 + 실시간 미리보기 | | 수정 | 기존 규칙의 패턴, 리셋주기, 자릿수 변경 | | 삭제 | 규칙 삭제 (Hard Delete) | ### 4.3 신규 규칙 생성 절차 1. **+ 새 규칙** 버튼 클릭 2. **기본 정보** 입력: - 규칙명: 관리용 이름 (예: `원자재 로트번호`) - 문서유형: 드롭다운 선택 (테넌트당 유형별 1개만 가능) - 리셋 주기: 일별 / 월별 / 연별 / 무제한 - 시퀀스 자릿수: 2 → `01,02` / 3 → `001,002` / 4 → `0001,0002` 3. **패턴 세그먼트** 구성: - `+ 세그먼트 추가` 버튼으로 세그먼트를 순서대로 추가 - 각 세그먼트의 타입과 값 설정 4. **미리보기** 확인: 세그먼트 변경 시 실시간 미리보기 표시 5. **생성** 버튼으로 저장 > **주의**: 테넌트당 문서유형별 1개 규칙만 가능하다. 이미 등록된 유형은 선택 불가. --- ## 5. 신규 규칙 생성 템플릿 아래는 자주 사용하는 채번 패턴 템플릿이다. MNG에서 새 규칙 생성 시 참고한다. ### 5.1 원자재 로트번호 (YYMMDD-NN) > 5130 레거시 방식 차용. 일별 시퀀스 리셋. | 항목 | 값 | |------|------| | 규칙명 | `원자재 로트번호` | | 문서유형 | `material_receipt` (원자재수입검사) | | 리셋 주기 | `daily` (일별) | | 시퀀스 자릿수 | `2` | **패턴:** ```json [ { "type": "date", "format": "ymd" }, { "type": "separator", "value": "-" }, { "type": "sequence" } ] ``` **결과:** `260317-01`, `260317-02`, ... → 다음날 `260318-01` ### 5.2 견적번호 (KD-PR-YYMMDD-NN) | 항목 | 값 | |------|------| | 규칙명 | `5130 견적번호` | | 문서유형 | `quote` (견적) | | 리셋 주기 | `daily` | | 시퀀스 자릿수 | `2` | **패턴:** ```json [ { "type": "static", "value": "KD" }, { "type": "separator", "value": "-" }, { "type": "static", "value": "PR" }, { "type": "separator", "value": "-" }, { "type": "date", "format": "ymd" }, { "type": "separator", "value": "-" }, { "type": "sequence" } ] ``` **결과:** `KD-PR-260317-01` ### 5.3 수주 로트번호 (KD-{pairCode}-YYMMDD-NN) | 항목 | 값 | |------|------| | 규칙명 | `5130 수주 로트번호` | | 문서유형 | `order` (수주) | | 리셋 주기 | `daily` | | 시퀀스 자릿수 | `2` | **패턴:** ```json [ { "type": "static", "value": "KD" }, { "type": "separator", "value": "-" }, { "type": "param", "key": "pair_code", "default": "SS" }, { "type": "separator", "value": "-" }, { "type": "date", "format": "ymd" }, { "type": "separator", "value": "-" }, { "type": "sequence" } ] ``` **결과:** `KD-SS-260317-01`, `KD-TE-260317-01` (pairCode별 독립 시퀀스) ### 5.4 작업지시번호 (WO-YYYYMMDD-NNNN) | 항목 | 값 | |------|------| | 규칙명 | `작업지시번호` | | 문서유형 | `work_order` (작업지시) | | 리셋 주기 | `daily` | | 시퀀스 자릿수 | `4` | **패턴:** ```json [ { "type": "static", "value": "WO" }, { "type": "separator", "value": "-" }, { "type": "date", "format": "Ymd" }, { "type": "separator", "value": "-" }, { "type": "sequence" } ] ``` **결과:** `WO-20260317-0001` ### 5.5 월별 리셋 예시 (INV-YYYYMM-NNN) | 항목 | 값 | |------|------| | 규칙명 | `매출번호` | | 문서유형 | `sale` (매출) | | 리셋 주기 | `monthly` | | 시퀀스 자릿수 | `3` | **패턴:** ```json [ { "type": "static", "value": "INV" }, { "type": "separator", "value": "-" }, { "type": "date", "format": "Ym" }, { "type": "separator", "value": "-" }, { "type": "sequence" } ] ``` **결과:** `INV-202603-001` → 4월 리셋 → `INV-202604-001` --- ## 6. 서비스 연동 ### 6.1 호출 구조 ``` 호출 서비스 → NumberingService.generate(documentType, params) ├─ 규칙 있음 → 패턴 기반 생성 (Atomic UPSERT) └─ 규칙 없음 → null 반환 → 호출 서비스가 레거시 로직 사용 ``` ### 6.2 현재 연동 서비스 | 서비스 | 문서유형 | 레거시 폴백 | |--------|---------|------------| | `QuoteNumberService` | `quote` | `QT{YYYYMMDD}{NNNN}` | | `OrderService` | `order` | `ORD{YYYYMMDD}{NNNN}` | | `ReceivingService` | `material_receipt` | `YYMMDD-NN` (DB 시퀀스) | ### 6.3 연동 코드 패턴 새로운 서비스에서 채번규칙을 사용하려면 아래 패턴을 따른다: ```php // 1. NumberingService 호출 $numberingService = app(NumberingService::class); $numberingService->setContext($this->tenantId(), $this->apiUserId()); // 2. 규칙 기반 생성 시도 $number = $numberingService->generate('document_type', [ 'param_key' => 'value', // param/mapping 세그먼트용 ]); // 3. 규칙 없으면 레거시 폴백 if ($number !== null) { return $number; } return $this->generateLegacy(); ``` --- ## 7. 동시성 처리 ```sql INSERT INTO numbering_sequences (tenant_id, document_type, scope_key, period_key, last_sequence, created_at, updated_at) VALUES (?, ?, ?, ?, 1, NOW(), NOW()) ON DUPLICATE KEY UPDATE last_sequence = last_sequence + 1, updated_at = NOW() ``` MySQL의 `ON DUPLICATE KEY UPDATE`로 Atomic 연산을 보장한다. 동시 요청에서도 시퀀스 충돌 없이 안전하게 번호를 생성한다. **scope_key 분리**: `param`, `mapping` 세그먼트 값이 scope_key로 저장되어, 파라미터별 독립 시퀀스를 유지한다. 예: 수주 `KD-SS-260317-01`과 `KD-TE-260317-01`은 각각 독립 시퀀스. --- ## 8. 현재 등록 현황 ### 프론트_테스트회사 (tenant_id: 287) | # | 규칙명 | 문서유형 | 패턴 미리보기 | 리셋 | 자릿수 | |---|--------|---------|-------------|------|:------:| | 1 | 5130 견적번호 | quote | `KD-PR-260317-01` | 일별 | 2 | | 2 | 5130 수주 로트번호 | order | `KD-SS-260317-01` | 일별 | 2 | | 3 | 원자재 로트번호 | material_receipt | `260317-01` | 일별 | 2 | > 신규 테넌트에 규칙이 없으면 각 서비스의 레거시 로직이 자동 적용된다. --- ## 관련 문서 - [DB 스키마 — 공통](../system/database/commons.md) - [품목 정책](item-policy.md) — 품목 코드 체계 --- **최종 업데이트**: 2026-03-17