# KBX Excel Import v1 — Foundation v5

## 목적

모든 입력형 업무 화면에서 별도의 Excel 업로드 기능을 다시 만들지 않고 다음 공통 파이프라인을 사용한다.

`Template → Upload → Mapping → Staging → Validation → Preview → Commit → Audit`

## 핵심 원칙

1. Excel은 DB에 직접 반영하지 않는다.
2. 원본 행 번호를 유지한다.
3. Exact → Alias → Saved Mapping → AI Suggestion의 순서로 매핑하되, 저장 매핑은 동일 source signature에 대해서만 우선 적용한다.
4. AI 추천은 미매핑 컬럼만 제안하며 ImportDefinition에 없는 필드를 만들 수 없다.
5. 참조 마스터는 행마다 조회하지 않고 batch resolve한다.
6. 정상 데이터만 Commit 대상으로 사용한다.
7. Commit Job은 Import Session 상태 전이와 Row status로 중복 실행에 안전해야 한다.
8. 원본 XLSX와 staging은 14일 기본 보관 후 제거한다. Domain/Audit 데이터는 보존한다.
9. SignalR 진행률은 편의 채널이고 Source of Truth는 PostgreSQL Import Session이다.
10. 브라우저 종료 후에도 세션 ID로 진행상태를 복구할 수 있다.

## 사용자 흐름

- `엑셀 > 업로드 양식 다운로드`
- 또는 기존 Excel 선택
- 자동매핑 확인
- 필요 시 `쿠팡 주문양식` 같은 이름으로 매핑 저장
- 검증 실행
- 오류 행은 화면 100건 미리보기 또는 오류 XLSX 다운로드
- 정상 건 반영
- 대량 작업은 Hangfire + SignalR로 진행상태 표시

## 저장 구조

- `kbx.import_sessions`: 수명주기, 매핑, 건수, 진행률
- `kbx.import_files`: 원본 XLSX bytea. 초기 Modular Monolith용 교체 가능 Adapter 경계
- `kbx.import_rows`: raw/normalized/error/warning/domain key staging
- `kbx.saved_import_mappings`: 사용자별 재사용 매핑
- `kbx.import_job_receipts`: 향후 job observability 확장 지점

원본 파일을 session metadata와 별도 table에 둬 일반 조회에서 대용량 bytea가 함께 읽히지 않게 한다.

## 주문 Import 예제

`oms.orders.v1`은 주문번호별 여러 Excel 행을 하나의 Header/Detail Transaction으로 그룹화한다.

검증 시 거래처/창고/품목 코드는 distinct 목록을 한 번에 조회하고 실제 Domain ID로 resolve한다. 같은 주문번호의 Header 값이 행마다 다르면 `ORDER_HEADER_CONFLICT`로 차단한다.

기존 주문은 `NEW/DRAFT` 상태만 Excel update를 허용한다. Commit에서는 주문별 transaction 안에서 Header, Lines, Audit, Outbox, staging status를 같이 변경한다.

## AI Mapping

`IImportMappingSuggester`가 확장 지점이다. 기본 구현은 No-op이다. 실제 AI Adapter는 다음 계약을 지켜야 한다.

- 미매핑 컬럼만 입력
- ImportDefinition 내 target field만 반환
- confidence/reason 반환
- 자동 저장 금지
- 데이터 Commit 금지
- 사용자 확정 또는 검증 이후만 사용

이 경계로 LLM hallucination이 DB field나 Domain Entity 생성으로 연결되지 않게 한다.

## Host wiring

필요 NuGet/Frontend package 예:

- ClosedXML
- Hangfire.AspNetCore 및 현재 프로젝트가 사용하는 PostgreSQL Hangfire storage
- Microsoft.AspNetCore.SignalR은 ASP.NET Core shared framework 사용
- `@microsoft/signalr` client

등록 예:

```csharp
builder.Services.AddKbxExcelImport();
// 기존 Hangfire/Npgsql/FastEndpoints 등록

app.MapKbxExcelImport();
```

Hangfire recurring job에서 `PurgeExpiredImportsJob`을 하루 한 번 실행한다.

## 향후 교체 지점

트래픽 증가 시 다음은 인터페이스를 유지하며 교체한다.

- PostgreSQL bytea → object storage
- 전체 Workbook parsing → streaming OpenXML reader
- 100k 행 memory grouping → keyset/chunk pipeline
- Noop AI Mapping → 승인된 내부 AI tool adapter

처음부터 분산 스토리지·자체 Excel engine을 만들지는 않는다. 측정된 병목이 생긴 뒤 교체한다.
