summaryrefslogtreecommitdiff
path: root/components/common/selectors/material/material-service.ts
blob: 1f238ed7d42ef322c2b9773d4767475092bd6165 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"use server";

import { sql, SQL } from "drizzle-orm";
import db from "@/db/db";
import { MATERIAL_MASTER_PART_MATL } from "@/db/schema/MDG/mdg";

export interface MaterialSearchItem {
  materialCode: string;        // 자재코드 (MATNR)
  materialName: string;        // 자재명 (ZZNAME)
  displayText: string;         // 애플리케이션 레벨에서 계산된 필드
}

export interface MaterialSearchResult {
  success: boolean;
  data: MaterialSearchItem[];
  pagination: {
    page: number;
    perPage: number;
    total: number;
    pageCount: number;
    hasNextPage: boolean;
    hasPrevPage: boolean;
  };
}

/**
 * 자재 검색 함수 - MATERIAL_MASTER_PART_MATL 테이블에서 검색 (페이지네이션)
 * 사용자는 자재코드를 직접 입력하여 검색함 (자재명이 아닌 자재코드만 검색 대상)
 * 자재 레코드가 수억개 수준이므로 항상 페이지네이션 사용
 */
export async function searchMaterialsForSelector(
  query: string,
  page: number = 1,
  perPage: number = 10
): Promise<MaterialSearchResult> {
  try {
    const offset = (page - 1) * perPage;

    // 검색 조건 - 자재코드(MATNR)로만 검색
    let searchWhere: SQL<unknown> | undefined;
    if (query.trim()) {
      const searchPattern = `%${query.trim()}%`;
      searchWhere = sql`${MATERIAL_MASTER_PART_MATL.MATNR} ILIKE ${searchPattern}`;
    }

    const { data, total } = await db.transaction(async (tx) => {
      // 데이터 조회 - MATNR과 ZZNAME만 선택
      const data = await tx
        .select({
          materialCode: MATERIAL_MASTER_PART_MATL.MATNR,
          materialName: MATERIAL_MASTER_PART_MATL.ZZNAME,
        })
        .from(MATERIAL_MASTER_PART_MATL)
        .where(searchWhere)
        .orderBy(MATERIAL_MASTER_PART_MATL.MATNR)
        .limit(perPage)
        .offset(offset);

      // 총 개수 조회
      const countResult = await tx
        .select({ count: sql<number>`count(*)` })
        .from(MATERIAL_MASTER_PART_MATL)
        .where(searchWhere);

      const total = countResult[0]?.count || 0;

      return {
        data: data.map((row) => ({
          materialCode: row.materialCode || '',
          materialName: row.materialName || '',
          displayText: `${row.materialCode || ''} - ${row.materialName || ''}`, // 애플리케이션 레벨에서 생성
        })),
        total,
      };
    });

    const pageCount = Math.ceil(total / perPage);

    return {
      success: true,
      data,
      pagination: {
        page,
        perPage,
        total,
        pageCount,
        hasNextPage: page < pageCount,
        hasPrevPage: page > 1,
      },
    };
  } catch (error) {
    console.error("자재 검색 오류:", error);
    return {
      success: false,
      data: [],
      pagination: {
        page: 1,
        perPage: 10,
        total: 0,
        pageCount: 0,
        hasNextPage: false,
        hasPrevPage: false,
      },
    };
  }
}

/**
 * Dialog용 자재 목록 조회 함수 - 페이지네이션
 * Dialog에서는 효율적인 사용자 경험을 위해 10개씩 페이지네이션하여 조회
 * 자재 레코드가 수억개 수준이므로 무한 스크롤이나 전체 로드가 아닌 페이지네이션 사용
 */
export async function searchMaterialsForDialog(
  query: string,
  page: number = 1,
  perPage: number = 10
): Promise<{
  success: boolean;
  data: MaterialSearchItem[];
  pagination: {
    page: number;
    perPage: number;
    total: number;
    pageCount: number;
    hasNextPage: boolean;
    hasPrevPage: boolean;
  };
  error?: string;
}> {
  try {
    const result = await searchMaterialsForSelector(query, page, perPage);

    return {
      success: result.success,
      data: result.data,
      pagination: result.pagination,
      error: result.success ? undefined : "검색 중 오류가 발생했습니다.",
    };
  } catch (error) {
    console.error("Dialog용 자재 검색 오류:", error);
    return {
      success: false,
      data: [],
      pagination: {
        page: 1,
        perPage: 10,
        total: 0,
        pageCount: 0,
        hasNextPage: false,
        hasPrevPage: false,
      },
      error: "데이터를 불러오는데 실패했습니다.",
    };
  }
}