summaryrefslogtreecommitdiff
path: root/lib/items-tech
diff options
context:
space:
mode:
Diffstat (limited to 'lib/items-tech')
-rw-r--r--lib/items-tech/service.ts236
1 files changed, 157 insertions, 79 deletions
diff --git a/lib/items-tech/service.ts b/lib/items-tech/service.ts
index 0cc08d23..bf2684d7 100644
--- a/lib/items-tech/service.ts
+++ b/lib/items-tech/service.ts
@@ -13,9 +13,9 @@ import { GetShipbuildingSchema, GetOffshoreTopSchema, GetOffshoreHullSchema, Shi
import { itemShipbuilding, itemOffshoreTop, itemOffshoreHull } from "@/db/schema/items";
// 타입 정의 추가
-export type ShipbuildingWorkType = '기장' | '전장' | '선실' | '배관' | '철의';
+export type ShipbuildingWorkType = '기장' | '전장' | '선실' | '배관' | '철의' | '선체';
export type OffshoreTopWorkType = 'TM' | 'TS' | 'TE' | 'TP';
-export type OffshoreHullWorkType = 'HA' | 'HE' | 'HH' | 'HM' | 'NC';
+export type OffshoreHullWorkType = 'HA' | 'HE' | 'HH' | 'HM' | 'HO' | 'HP' | 'NC';
export interface ShipbuildingItem {
id: number;
@@ -62,7 +62,7 @@ export async function getShipbuildingItems(input: GetShipbuildingSchema) {
try {
const offset = (input.page - 1) * input.perPage;
- // advancedTable 모드면 filterColumns()로 where 절 구성
+ // advancedTable 모드면 filterColumns()로 where 절 구성 (기존 필터)
const advancedWhere = filterColumns({
table: itemShipbuilding,
filters: input.filters.filter(filter => {
@@ -73,6 +73,17 @@ export async function getShipbuildingItems(input: GetShipbuildingSchema) {
joinOperator: input.joinOperator,
});
+ // 필터 시트에서 온 shipFilters 처리
+ const shipFilterWhere = filterColumns({
+ table: itemShipbuilding,
+ filters: input.shipFilters?.filter(filter => {
+ // enum 필드에 대한 isEmpty/isNotEmpty는 제외
+ return !((filter.id === 'workType' || filter.id === 'shipTypes') &&
+ (filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
+ }) || [],
+ joinOperator: input.shipJoinOperator,
+ });
+
let globalWhere;
if (input.search) {
const s = `%${input.search}%`;
@@ -82,7 +93,7 @@ export async function getShipbuildingItems(input: GetShipbuildingSchema) {
);
}
- // enum 필드에 대한 isEmpty/isNotEmpty 처리
+ // enum 필드에 대한 isEmpty/isNotEmpty 처리 (기존 필터)
const enumConditions = input.filters
.filter(filter => (filter.id === 'workType' || filter.id === 'shipTypes') &&
(filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
@@ -91,10 +102,21 @@ export async function getShipbuildingItems(input: GetShipbuildingSchema) {
return filter.operator === 'isEmpty' ? sql`${column} is null` : sql`${column} is not null`;
});
+ // enum 필드에 대한 isEmpty/isNotEmpty 처리 (필터 시트)
+ const shipEnumConditions = input.shipFilters
+ ?.filter(filter => (filter.id === 'workType' || filter.id === 'shipTypes') &&
+ (filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
+ .map(filter => {
+ const column = itemShipbuilding[filter.id];
+ return filter.operator === 'isEmpty' ? sql`${column} is null` : sql`${column} is not null`;
+ }) || [];
+
const finalWhere = and(
advancedWhere,
+ shipFilterWhere,
globalWhere,
- ...enumConditions
+ ...enumConditions,
+ ...shipEnumConditions
);
const where = finalWhere;
@@ -152,7 +174,7 @@ export async function getOffshoreTopItems(input: GetOffshoreTopSchema) {
try {
const offset = (input.page - 1) * input.perPage;
- // advancedTable 모드면 filterColumns()로 where 절 구성
+ // advancedTable 모드면 filterColumns()로 where 절 구성 (기존 필터)
const advancedWhere = filterColumns({
table: itemOffshoreTop,
filters: input.filters.filter(filter => {
@@ -163,6 +185,17 @@ export async function getOffshoreTopItems(input: GetOffshoreTopSchema) {
joinOperator: input.joinOperator,
});
+ // 필터 시트에서 온 topFilters 처리
+ const topFilterWhere = filterColumns({
+ table: itemOffshoreTop,
+ filters: input.topFilters?.filter(filter => {
+ // enum 필드에 대한 isEmpty/isNotEmpty는 제외
+ return !((filter.id === 'workType') &&
+ (filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
+ }) || [],
+ joinOperator: input.topJoinOperator,
+ });
+
let globalWhere;
if (input.search) {
const s = `%${input.search}%`;
@@ -173,7 +206,7 @@ export async function getOffshoreTopItems(input: GetOffshoreTopSchema) {
);
}
- // enum 필드에 대한 isEmpty/isNotEmpty 처리
+ // enum 필드에 대한 isEmpty/isNotEmpty 처리 (기존 필터)
const enumConditions = input.filters
.filter(filter => (filter.id === 'workType') &&
(filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
@@ -182,10 +215,21 @@ export async function getOffshoreTopItems(input: GetOffshoreTopSchema) {
return filter.operator === 'isEmpty' ? sql`${column} is null` : sql`${column} is not null`;
});
+ // enum 필드에 대한 isEmpty/isNotEmpty 처리 (필터 시트)
+ const topEnumConditions = input.topFilters
+ ?.filter(filter => (filter.id === 'workType') &&
+ (filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
+ .map(filter => {
+ const column = itemOffshoreTop.workType;
+ return filter.operator === 'isEmpty' ? sql`${column} is null` : sql`${column} is not null`;
+ }) || [];
+
const finalWhere = and(
advancedWhere,
+ topFilterWhere,
globalWhere,
- ...enumConditions
+ ...enumConditions,
+ ...topEnumConditions
);
const where = finalWhere;
@@ -243,7 +287,7 @@ export async function getOffshoreHullItems(input: GetOffshoreHullSchema) {
try {
const offset = (input.page - 1) * input.perPage;
- // advancedTable 모드면 filterColumns()로 where 절 구성
+ // advancedTable 모드면 filterColumns()로 where 절 구성 (기존 필터)
const advancedWhere = filterColumns({
table: itemOffshoreHull,
filters: input.filters.filter(filter => {
@@ -254,6 +298,17 @@ export async function getOffshoreHullItems(input: GetOffshoreHullSchema) {
joinOperator: input.joinOperator,
});
+ // 필터 시트에서 온 hullFilters 처리
+ const hullFilterWhere = filterColumns({
+ table: itemOffshoreHull,
+ filters: input.hullFilters?.filter(filter => {
+ // enum 필드에 대한 isEmpty/isNotEmpty는 제외
+ return !((filter.id === 'workType') &&
+ (filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
+ }) || [],
+ joinOperator: input.hullJoinOperator,
+ });
+
let globalWhere;
if (input.search) {
const s = `%${input.search}%`;
@@ -264,7 +319,7 @@ export async function getOffshoreHullItems(input: GetOffshoreHullSchema) {
);
}
- // enum 필드에 대한 isEmpty/isNotEmpty 처리
+ // enum 필드에 대한 isEmpty/isNotEmpty 처리 (기존 필터)
const enumConditions = input.filters
.filter(filter => (filter.id === 'workType') &&
(filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
@@ -273,10 +328,21 @@ export async function getOffshoreHullItems(input: GetOffshoreHullSchema) {
return filter.operator === 'isEmpty' ? sql`${column} is null` : sql`${column} is not null`;
});
+ // enum 필드에 대한 isEmpty/isNotEmpty 처리 (필터 시트)
+ const hullEnumConditions = input.hullFilters
+ ?.filter(filter => (filter.id === 'workType') &&
+ (filter.operator === 'isEmpty' || filter.operator === 'isNotEmpty'))
+ .map(filter => {
+ const column = itemOffshoreHull.workType;
+ return filter.operator === 'isEmpty' ? sql`${column} is null` : sql`${column} is not null`;
+ }) || [];
+
const finalWhere = and(
advancedWhere,
+ hullFilterWhere,
globalWhere,
- ...enumConditions
+ ...enumConditions,
+ ...hullEnumConditions
);
const where = finalWhere;
@@ -339,19 +405,12 @@ export async function createShipbuildingItem(input: TypedItemCreateData) {
unstable_noStore()
try {
- if (!input.itemCode) {
- return {
- success: false,
- message: "아이템 코드는 필수입니다",
- data: null,
- error: "필수 필드 누락"
- }
- }
+ // itemCode는 nullable하게 변경
const shipData = input as ShipbuildingItemCreateData;
const result = await db.insert(itemShipbuilding).values({
- itemCode: input.itemCode,
- workType: shipData.workType ? (shipData.workType as '기장' | '전장' | '선실' | '배관' | '철의') : '기장',
+ itemCode: input.itemCode || "",
+ workType: shipData.workType ? (shipData.workType as '기장' | '전장' | '선실' | '배관' | '철의' | '선체') : '기장',
shipTypes: shipData.shipTypes || '',
itemList: shipData.itemList || null,
createdAt: new Date(),
@@ -391,8 +450,8 @@ export async function createShipbuildingItem(input: TypedItemCreateData) {
* 하나의 아이템 코드에 대해 여러 선종을 처리 (1:N 관계)
*/
export async function createShipbuildingImportItem(input: {
- itemCode: string;
- workType: '기장' | '전장' | '선실' | '배관' | '철의';
+ itemCode?: string | null;
+ workType: '기장' | '전장' | '선실' | '배관' | '철의' | '선체';
itemList?: string | null;
subItemList?: string | null;
shipTypes?: string | null;
@@ -400,35 +459,30 @@ export async function createShipbuildingImportItem(input: {
unstable_noStore();
try {
- if (!input.itemCode) {
- return {
- success: false,
- message: "아이템 코드는 필수입니다",
- data: null,
- error: "필수 필드 누락"
- }
- }
+ // itemCode는 nullable하게 변경
- // 기존 아이템 및 선종 확인
- const existingItem = await db.select().from(itemShipbuilding)
- .where(
- and(
- eq(itemShipbuilding.itemCode, input.itemCode),
- eq(itemShipbuilding.shipTypes, input.shipTypes || '')
- )
- );
-
- if (existingItem.length > 0) {
- return {
- success: false,
- message: "이미 존재하는 아이템 코드 및 선종입니다",
- data: null,
- error: "중복 키 오류"
+ // 기존 아이템 및 선종 확인 (itemCode가 있을 경우에만)
+ if (input.itemCode) {
+ const existingItem = await db.select().from(itemShipbuilding)
+ .where(
+ and(
+ eq(itemShipbuilding.itemCode, input.itemCode),
+ eq(itemShipbuilding.shipTypes, input.shipTypes || '')
+ )
+ );
+
+ if (existingItem.length > 0) {
+ return {
+ success: false,
+ message: "이미 존재하는 아이템 코드 및 선종입니다",
+ data: null,
+ error: "중복 키 오류"
+ }
}
}
const result = await db.insert(itemShipbuilding).values({
- itemCode: input.itemCode,
+ itemCode: input.itemCode || "",
workType: input.workType,
shipTypes: input.shipTypes || '',
itemList: input.itemList || '',
@@ -464,21 +518,32 @@ export async function createShipbuildingImportItem(input: {
}
}
+/**
+ * 해양 TOP 아이템 생성 (중복 아이템코드 방지)
+ */
export async function createOffshoreTopItem(data: OffshoreTopItemCreateData) {
- unstable_noStore()
-
+ unstable_noStore();
+
try {
- if (!data.itemCode) {
- return {
- success: false,
- message: "아이템 코드는 필수입니다",
- data: null,
- error: "필수 필드 누락"
+ // itemCode가 있는 경우 중복 체크
+ if (data.itemCode && data.itemCode.trim() !== "") {
+ const existingItem = await db
+ .select({ id: itemOffshoreTop.id })
+ .from(itemOffshoreTop)
+ .where(eq(itemOffshoreTop.itemCode, data.itemCode.trim()));
+
+ if (existingItem.length > 0) {
+ return {
+ success: false,
+ message: "이미 존재하는 아이템 코드입니다",
+ data: null,
+ error: "중복 키 오류"
+ };
}
}
-
+
const result = await db.insert(itemOffshoreTop).values({
- itemCode: data.itemCode,
+ itemCode: data.itemCode || "",
workType: data.workType,
itemList: data.itemList,
subItemList: data.subItemList,
@@ -486,23 +551,23 @@ export async function createOffshoreTopItem(data: OffshoreTopItemCreateData) {
updatedAt: new Date()
}).returning();
- revalidateTag("items")
+ revalidateTag("items");
return {
success: true,
data: result[0],
error: null
- }
+ };
} catch (err) {
- console.error("아이템 생성 오류:", err)
-
+ console.error("해양 TOP 아이템 생성 오류:", err);
+
if (err instanceof Error && err.message.includes("unique constraint")) {
return {
success: false,
message: "이미 존재하는 아이템 코드입니다",
data: null,
error: "중복 키 오류"
- }
+ };
}
return {
@@ -510,25 +575,36 @@ export async function createOffshoreTopItem(data: OffshoreTopItemCreateData) {
message: getErrorMessage(err),
data: null,
error: getErrorMessage(err)
- }
+ };
}
}
+/**
+ * 해양 HULL 아이템 생성 (중복 아이템코드 방지)
+ */
export async function createOffshoreHullItem(data: OffshoreHullItemCreateData) {
- unstable_noStore()
-
+ unstable_noStore();
+
try {
- if (!data.itemCode) {
- return {
- success: false,
- message: "아이템 코드는 필수입니다",
- data: null,
- error: "필수 필드 누락"
+ // itemCode가 있는 경우 중복 체크
+ if (data.itemCode && data.itemCode.trim() !== "") {
+ const existingItem = await db
+ .select({ id: itemOffshoreHull.id })
+ .from(itemOffshoreHull)
+ .where(eq(itemOffshoreHull.itemCode, data.itemCode.trim()));
+
+ if (existingItem.length > 0) {
+ return {
+ success: false,
+ message: "이미 존재하는 아이템 코드입니다",
+ data: null,
+ error: "중복 키 오류"
+ };
}
}
-
+
const result = await db.insert(itemOffshoreHull).values({
- itemCode: data.itemCode,
+ itemCode: data.itemCode || "",
workType: data.workType,
itemList: data.itemList,
subItemList: data.subItemList,
@@ -536,23 +612,23 @@ export async function createOffshoreHullItem(data: OffshoreHullItemCreateData) {
updatedAt: new Date()
}).returning();
- revalidateTag("items")
+ revalidateTag("items");
return {
success: true,
data: result[0],
error: null
- }
+ };
} catch (err) {
- console.error("아이템 생성 오류:", err)
-
+ console.error("해양 HULL 아이템 생성 오류:", err);
+
if (err instanceof Error && err.message.includes("unique constraint")) {
return {
success: false,
message: "이미 존재하는 아이템 코드입니다",
data: null,
error: "중복 키 오류"
- }
+ };
}
return {
@@ -560,7 +636,7 @@ export async function createOffshoreHullItem(data: OffshoreHullItemCreateData) {
message: getErrorMessage(err),
data: null,
error: getErrorMessage(err)
- }
+ };
}
}
@@ -1126,6 +1202,8 @@ export async function getOffshoreHullWorkTypes() {
{ code: 'HE' as OffshoreHullWorkType, name: 'HE'},
{ code: 'HH' as OffshoreHullWorkType, name: 'HH'},
{ code: 'HM' as OffshoreHullWorkType, name: 'HM'},
+ { code: 'HO' as OffshoreHullWorkType, name: 'HO'},
+ { code: 'HP' as OffshoreHullWorkType, name: 'HP'},
{ code: 'NC' as OffshoreHullWorkType, name: 'NC'},
]
}