임동욱 임동욱 09-17
feat: 가맹점 업종 이름을 FRCS_TPBIZ_CD에 없으면 FRCS_CD에서 찾는다
BizPlay 업종 값이 2자리(FRCS_TPBIZ_CD)와 4자리(FRCS_CD = 업종+업태)로 섞여 온다. 두 표를
차례로 이어 붙여 앞 표가 먼저 맞게 한다(사용자 확정). 목록·상세 모달·엑셀이 같은 표를 쓴다.

Co-Authored-By: Claude Opus 5 
@e0f887f3324fc47bfc36200b5665af6ddc262d81
app/(protected)/(basic)/system/merchants/_components/merchant-list.tsx
--- app/(protected)/(basic)/system/merchants/_components/merchant-list.tsx
+++ app/(protected)/(basic)/system/merchants/_components/merchant-list.tsx
@@ -33,7 +33,7 @@
 
 interface MerchantListProps {
   items: Merchant[];
-  /** 업종 코드표(`FRCS_TPBIZ_CD`) — 업종 열과 상세 모달이 이름을 찾는다. */
+  /** 업종 코드표(`FRCS_TPBIZ_CD` 다음 `FRCS_CD`) — 업종 열과 상세 모달이 이름을 찾는다. */
   businessCodes: CommonCode[];
   query: MerchantQuery;
   currentPage: number;
app/(protected)/(basic)/system/merchants/excel/route.ts
--- app/(protected)/(basic)/system/merchants/excel/route.ts
+++ app/(protected)/(basic)/system/merchants/excel/route.ts
@@ -36,10 +36,12 @@
 export async function GET() {
   await verifySession();
 
-  const [merchants, businessCodes] = await Promise.all([
+  const [merchants, business, businessDetail] = await Promise.all([
     fetchAllMerchants(),
     fetchCommonCodes(CODE_GROUP.merchantBusiness),
+    fetchCommonCodes(CODE_GROUP.merchantBusinessDetail),
   ]);
+  const businessCodes = [...business, ...businessDetail];
 
   const rows = merchants.map((merchant, index) =>
     [
app/(protected)/(basic)/system/merchants/page.tsx
--- app/(protected)/(basic)/system/merchants/page.tsx
+++ app/(protected)/(basic)/system/merchants/page.tsx
@@ -20,10 +20,13 @@
   await verifySession();
 
   const query = parseMerchantQuery(await searchParams);
-  const [{ items, totalCount }, businessCodes] = await Promise.all([
+  const [{ items, totalCount }, business, businessDetail] = await Promise.all([
     fetchMerchants(query),
     fetchCommonCodes(CODE_GROUP.merchantBusiness),
+    fetchCommonCodes(CODE_GROUP.merchantBusinessDetail),
   ]);
+  // 앞쪽 표가 먼저 맞는다 — 2자리 값은 FRCS_TPBIZ_CD에서, 4자리 값은 FRCS_CD에서 이름을 찾는다.
+  const businessCodes = [...business, ...businessDetail];
 
   const totalPages = Math.max(1, Math.ceil(totalCount / query.pageSize));
   const currentPage = Math.min(query.page, totalPages);
lib/domain/common-code.ts
--- lib/domain/common-code.ts
+++ lib/domain/common-code.ts
@@ -41,8 +41,10 @@
   },
   /** 가맹점 상세의 카테고리 — 백엔드 `MngrVocDetailMapper`가 이 그룹과 조인한다. */
   merchantType: 'COM_FRCS_TYPE_CD',
-  /** 가맹점 업종 — BizPlay `FRCS_TPBIZ_CD` 값의 이름은 이 그룹에서 찾는다(사용자 확정). */
+  /** 가맹점 업종 — BizPlay `FRCS_TPBIZ_CD` 값(2자리)의 이름은 먼저 이 그룹에서 찾는다(사용자 확정). */
   merchantBusiness: 'FRCS_TPBIZ_CD',
+  /** 업종 세분류(4자리 = 업종 2자리 + 업태 2자리). 값이 위 그룹에 없을 때 여기서 찾는다(사용자 확정). */
+  merchantBusinessDetail: 'FRCS_CD',
 } as const;
 
 /** 값이 없는 항목의 화면 표기. */
lib/domain/merchant.ts
--- lib/domain/merchant.ts
+++ lib/domain/merchant.ts
@@ -40,7 +40,7 @@
     : String(value);
 }
 
-/** 업종 이름 — 공통코드 `FRCS_TPBIZ_CD`에서 찾고, 없으면 코드를 그대로 보인다. */
+/** 업종 이름 — 공통코드 `FRCS_TPBIZ_CD`에서 먼저, 없으면 `FRCS_CD`(4자리)에서 찾고, 그래도 없으면 코드를 그대로 보인다. */
 export function formatCategoryLabel(codes: readonly CommonCode[], code: string): string {
   if (!code) {
     return EMPTY_FIELD_PLACEHOLDER;
Add a comment
List