diff --git a/src/services/changeWellItemOrderBulk.js b/src/services/changeWellItemOrderBulk.js index 757d3c7..476e1d9 100644 --- a/src/services/changeWellItemOrderBulk.js +++ b/src/services/changeWellItemOrderBulk.js @@ -11,6 +11,7 @@ import { handleSqlError } from '@frolog/express-api-server'; export default async function changeWellItemOrderBulk(reqDto, user) { const t = await mysql.transaction(); try { + // (1) ID 디코딩 및 유효성 검사 const wellId = decodeHashId(reqDto.well_id); const userId = decodeHashId(user.id); @@ -35,7 +36,7 @@ export default async function changeWellItemOrderBulk(reqDto, user) { }; } - // (1) 우물 존재 및 권한 확인 + // (2) 우물 존재 및 권한 확인 const well = await Well.findByPk(wellId).catch(handleSqlError); if (!well) { await t.rollback(); @@ -46,7 +47,7 @@ export default async function changeWellItemOrderBulk(reqDto, user) { return { result: false, message: 'Unauthorized access.' }; } - // (2) 전체 아이템 조회 + // (3) 기존 우물 아이템 전체 조회 const allItems = await WellItem.findAll({ where: { well_id: wellId }, order: [['order', 'ASC']], @@ -61,51 +62,62 @@ export default async function changeWellItemOrderBulk(reqDto, user) { }; } - // (3) 요청 대상 분리 + // (4) 고정 순서 맵 구성 const fixedMap = new Map(); - const fixedSet = new Set(); for (const { id, order } of changes) { + if (fixedMap.has(order)) { + await t.rollback(); + return { + result: false, + message: `Duplicate order ${order} in changes.`, + }; + } fixedMap.set(order, id); - fixedSet.add(id); } - const restItems = allItems.filter((item) => !fixedSet.has(item.id)); - const newOrderList = Array(allItems.length); - let restIdx = 0; + // (5) 나머지 아이템 필터링 + const fixedIds = new Set(changes.map((c) => c.id)); + const remainingItems = allItems.filter( + (item) => !fixedIds.has(item.item_id), + ); - for (let i = 0; i < newOrderList.length; i++) { + // (6) 순서대로 배치할 새 배열 구성 + const totalLength = allItems.length; + const newOrderList = Array(totalLength); + let remainIdx = 0; + + for (let i = 0; i < totalLength; i++) { const fixedId = fixedMap.get(i); if (fixedId != null) { - const item = allItems.find((item) => item.item_id === fixedId); - if (!item) { + const found = allItems.find((item) => item.item_id === fixedId); + if (!found) { await t.rollback(); return { result: false, - message: `Item with ID ${fixedId} not found among existing items.`, + message: `Item with ID ${fixedId} not found.`, }; } - newOrderList[i] = item; + newOrderList[i] = found; } else { - if (restIdx >= restItems.length) { + if (remainIdx >= remainingItems.length) { await t.rollback(); return { result: false, - message: - 'Mismatch between expected and available items.', + message: 'Mismatch in remaining item distribution.', }; } - newOrderList[i] = restItems[restIdx++]; + newOrderList[i] = remainingItems[remainIdx++]; } } - // (4) 실제 update 수행 + // (7) 실제 DB 업데이트 수행 for (let i = 0; i < newOrderList.length; i++) { const item = newOrderList[i]; if (!item) { await t.rollback(); return { result: false, - message: `Item missing at index ${i} in new order list.`, + message: `Missing item at index ${i}.`, }; } @@ -114,14 +126,15 @@ export default async function changeWellItemOrderBulk(reqDto, user) { } } + // (8) 트랜잭션 커밋 await t.commit(); return { result: true }; } catch (err) { - console.error('[changeWellItemOrderBulk] Error occurred:', err); + console.error('[changeWellItemOrderBulk] Error:', err); await t.rollback(); return { result: false, - message: 'Failed to reorder well items due to unexpected error.', + message: 'Unexpected error occurred while reordering items.', }; } }