- features/esign/README.md: 전자서명 (4모델, 16 API) - features/documents/README.md: 문서관리 (12모델, EAV 기반, 15 API) - features/ai/README.md: AI 리포트 (Gemini 2.0, 4 API) - features/equipment/README.md: 설비관리 (MNG 전용) - features/finance/ 9개 하위문서: 입출금, 급여, 가지급금, 세금계산서, 악성채권, 어음, 카드, 미지급비용, 채권현황, CEO 대시보드 - features/finance/README.md 재구조화 (14개 하위문서 목록) - features/barobill-kakaotalk/README.md 확장 (API 설정 + 세금계산서) - rules/numbering-rules.md: 채번규칙 (6세그먼트, 원자적 UPSERT) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
109 lines
3.4 KiB
Markdown
109 lines
3.4 KiB
Markdown
# 채번규칙 (Numbering Rules)
|
|
|
|
> **상태**: 내부 서비스 (직접 API 없음)
|
|
> **최종 갱신**: 2026-02-27
|
|
|
|
---
|
|
|
|
## 1. 개요
|
|
|
|
문서 번호(견적번호, 수주번호 등)를 규칙 기반으로 자동 생성하는 내부 서비스. 테넌트별로 채번 규칙을 설정하면, 해당 규칙에 따라 일련번호가 자동 생성된다. 규칙이 없는 경우 레거시 포맷으로 폴백.
|
|
|
|
**핵심 기능:**
|
|
- 유연한 패턴 기반 번호 생성 (6가지 세그먼트 유형)
|
|
- Atomic UPSERT로 동시성 안전 시퀀스 관리
|
|
- 기간별 자동 리셋 (일/월/년/무제한)
|
|
- 미리보기 기능 (DB 업데이트 없음)
|
|
|
|
---
|
|
|
|
## 2. 모델
|
|
|
|
| 모델 | 테이블 | 설명 |
|
|
|------|--------|------|
|
|
| `NumberingRule` | `numbering_rules` | 채번 규칙 정의 (document_type, pattern, reset_period) |
|
|
| `NumberingSequence` | `numbering_sequences` | 일련번호 카운터 (tenant + type + scope + period) |
|
|
|
|
**지원 문서 유형:** quote, order, sale, work_order, material_receipt
|
|
|
|
**리셋 주기:** daily, monthly, yearly, never
|
|
|
|
---
|
|
|
|
## 3. 패턴 구조
|
|
|
|
패턴은 JSON 배열로 세그먼트를 정의한다.
|
|
|
|
| 세그먼트 | 설명 | 예시 |
|
|
|---------|------|------|
|
|
| `static` | 고정 문자열 | `{ "type": "static", "value": "QT" }` |
|
|
| `date` | 날짜 포맷 | `{ "type": "date", "format": "ymd" }` → `260227` |
|
|
| `sequence` | 일련번호 | `{ "type": "sequence", "padding": 4 }` → `0001` |
|
|
| `separator` | 구분자 | `{ "type": "separator", "value": "-" }` |
|
|
| `param` | 외부 파라미터 | `{ "type": "param", "key": "product_category" }` |
|
|
| `mapping` | 값 매핑 | `{ "type": "mapping", "key": "category", "map": {"A": "PR"} }` |
|
|
|
|
**패턴 예시:**
|
|
```json
|
|
[
|
|
{ "type": "static", "value": "KD" },
|
|
{ "type": "separator", "value": "-" },
|
|
{ "type": "mapping", "key": "category", "map": { "A": "PR" }, "default": "XX" },
|
|
{ "type": "separator", "value": "-" },
|
|
{ "type": "date", "format": "ymd" },
|
|
{ "type": "separator", "value": "-" },
|
|
{ "type": "sequence", "padding": 2 }
|
|
]
|
|
```
|
|
→ `KD-PR-260227-01`
|
|
|
|
---
|
|
|
|
## 4. 서비스
|
|
|
|
| 서비스 | 메서드 | 설명 |
|
|
|--------|--------|------|
|
|
| `NumberingService` | `generate($documentType, $params)` | 번호 생성 (규칙 없으면 null → 레거시 폴백) |
|
|
| | `preview($documentType, $params)` | 미리보기 (시퀀스 증가 없음) |
|
|
| `QuoteNumberService` | `generate()` | 견적번호 생성 (NumberingService → 레거시 폴백) |
|
|
| | `validate()` | 형식 검증 |
|
|
| | `isUnique()` | 중복 체크 |
|
|
|
|
**레거시 포맷:** `QT{YYYYMMDD}{NNNN}` (예: `QT202602270001`)
|
|
|
|
---
|
|
|
|
## 5. 동시성 처리
|
|
|
|
```sql
|
|
INSERT INTO numbering_sequences (tenant_id, document_type, scope_key, period_key, last_sequence)
|
|
VALUES (?, ?, ?, ?, 1)
|
|
ON DUPLICATE KEY UPDATE last_sequence = last_sequence + 1
|
|
```
|
|
|
|
MySQL의 `UPSERT`를 사용하여 동시 요청에서도 시퀀스 충돌 없이 안전하게 번호 생성.
|
|
|
|
---
|
|
|
|
## 6. 호출 위치
|
|
|
|
직접 API 엔드포인트는 없으며, 아래 서비스에서 내부 호출된다:
|
|
|
|
| 서비스 | 용도 |
|
|
|--------|------|
|
|
| `QuoteNumberService` | 견적번호 생성 |
|
|
| `OrderService` | 수주번호 생성 |
|
|
| `WorkOrderService` | 작업지시번호 생성 |
|
|
| `MaterialReceiptService` | 입고번호 생성 |
|
|
|
|
---
|
|
|
|
## 관련 문서
|
|
|
|
- [DB 스키마 — 공통](../system/database/commons.md)
|
|
- [품목 정책](item-policy.md) — 품목 코드 체계
|
|
|
|
---
|
|
|
|
**최종 업데이트**: 2026-02-27
|