summaryrefslogtreecommitdiff
path: root/lib/material/material-group-service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/material/material-group-service.ts')
-rw-r--r--lib/material/material-group-service.ts105
1 files changed, 105 insertions, 0 deletions
diff --git a/lib/material/material-group-service.ts b/lib/material/material-group-service.ts
new file mode 100644
index 00000000..216cd0e6
--- /dev/null
+++ b/lib/material/material-group-service.ts
@@ -0,0 +1,105 @@
+"use server";
+
+import { sql, SQL } from "drizzle-orm";
+import db from "@/db/db";
+import { materialSearchView } from "@/db/schema/items";
+
+export interface MaterialSearchItem {
+ materialGroupCode: string;
+ materialName: string;
+ displayText: string;
+}
+
+export interface MaterialSearchResult {
+ success: boolean;
+ data: MaterialSearchItem[];
+ pagination: {
+ page: number;
+ perPage: number;
+ total: number;
+ pageCount: number;
+ hasNextPage: boolean;
+ hasPrevPage: boolean;
+ };
+}
+
+/**
+ * 자재 검색 함수 - material_search_view에서 검색
+ */
+export async function searchMaterialsForSelector(
+ query: string,
+ page: number = 1,
+ perPage: number = 10
+): Promise<MaterialSearchResult> {
+ try {
+ const offset = (page - 1) * perPage;
+
+ // 검색 조건
+ let searchWhere: SQL<unknown> | undefined;
+ if (query.trim()) {
+ const searchPattern = `%${query.trim()}%`;
+ searchWhere = sql`(
+ ${materialSearchView.materialGroupCode} ILIKE ${searchPattern} OR
+ ${materialSearchView.materialName} ILIKE ${searchPattern} OR
+ ${materialSearchView.displayText} ILIKE ${searchPattern}
+ )`;
+ }
+
+ const { data, total } = await db.transaction(async (tx) => {
+ // 데이터 조회
+ const data = await tx
+ .select()
+ .from(materialSearchView)
+ .where(searchWhere)
+ .orderBy(materialSearchView.materialGroupCode, materialSearchView.materialName)
+ .limit(perPage)
+ .offset(offset);
+
+ // 총 개수 조회
+ const countResult = await tx
+ .select({ count: sql<number>`count(*)` })
+ .from(materialSearchView)
+ .where(searchWhere);
+
+ const total = countResult[0]?.count || 0;
+
+ return {
+ data: data.map((row) => ({
+ materialGroupCode: row.materialGroupCode,
+ materialName: row.materialName,
+ displayText: row.displayText,
+ })),
+ 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,
+ },
+ };
+ }
+}