From 7151a401d4e3e08fa01721d605f11c37bac7fdec Mon Sep 17 00:00:00 2001 From: chpark Date: Wed, 13 May 2026 11:49:26 +0900 Subject: [PATCH] =?UTF-8?q?fix(orders):=20=EC=9D=BC=EB=B0=98=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EA=B6=8C=ED=95=9C=20=EB=A7=A4=EC=B9=AD=20?= =?UTF-8?q?(objid=20+=20userId)=20+=20=EC=B6=9C=EA=B3=A0=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EA=B0=80=EB=A1=9C=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=A1=A4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 권한 fix — order.customer_objid 와 매칭 시: - 기존: user.objid 만 비교 → FITO 사용자(objid 없음)는 항상 fail → "권한 없음" - 변경: user.objid ?? user.userId 와 customer_objid 매칭, 또는 user.userId 와 직접 매칭 - 적용: items/update, lines/save, cancel, statement, items/remark (5개 API) 출고요청 리스트(m/orders/new) UI: - table 의 min-w-[640px] 제거 + table-fixed 적용 - 수량 컬럼 폭 180px → 112px, "담기" 버튼 텍스트 제거 (+ 아이콘만) - 폰트 11~12px 로 축소 - 모바일 화면 한 줄에 들어오도록 Co-Authored-By: Claude Opus 4.7 (1M context) --- src/app/(main)/m/orders/new/page.tsx | 53 ++++++++++---------- src/app/api/m/orders/cancel/route.ts | 4 +- src/app/api/m/orders/items/remark/route.ts | 3 +- src/app/api/m/orders/items/update/route.ts | 5 +- src/app/api/m/orders/lines/save/route.ts | 4 +- src/app/api/m/orders/statement/[id]/route.ts | 3 +- 6 files changed, 40 insertions(+), 32 deletions(-) diff --git a/src/app/(main)/m/orders/new/page.tsx b/src/app/(main)/m/orders/new/page.tsx index 1c4941b..69e48ca 100644 --- a/src/app/(main)/m/orders/new/page.tsx +++ b/src/app/(main)/m/orders/new/page.tsx @@ -618,15 +618,15 @@ function ListView({ items, cart, unlimitedQty, onAdd, onPlus, onMinus, onSetQty, }) { return (
-
- - +
+
+ - - - - - + + + + + @@ -639,26 +639,25 @@ function ListView({ items, cart, unlimitedQty, onAdd, onPlus, onMinus, onSetQty, const soldOut = stock === 0; return ( 0 ? "bg-emerald-50/40" : "hover:bg-slate-50"}`}> - - - - - + + diff --git a/src/app/api/m/orders/cancel/route.ts b/src/app/api/m/orders/cancel/route.ts index 6ac088b..ef1e829 100644 --- a/src/app/api/m/orders/cancel/route.ts +++ b/src/app/api/m/orders/cancel/route.ts @@ -12,7 +12,9 @@ export async function POST(req: NextRequest) { [objid] ); if (!order) return NextResponse.json({ success: false, message: "발주를 찾을 수 없습니다." }, { status: 404 }); - if (r.user.role === "USER" && order.customer_objid !== r.user.objid) { + // 본인 발주 매칭 (user.objid 또는 user.userId 와 customer_objid 일치) + const userOwn = r.user.objid ?? r.user.userId; + if (r.user.role === "USER" && order.customer_objid !== userOwn && order.customer_objid !== r.user.userId) { return NextResponse.json({ success: false, message: "권한이 없습니다." }, { status: 403 }); } if (order.status !== "REQUESTED") { diff --git a/src/app/api/m/orders/items/remark/route.ts b/src/app/api/m/orders/items/remark/route.ts index 138a7be..bb74386 100644 --- a/src/app/api/m/orders/items/remark/route.ts +++ b/src/app/api/m/orders/items/remark/route.ts @@ -28,7 +28,8 @@ export async function POST(req: NextRequest) { return NextResponse.json({ success: false, message: "라인을 찾을 수 없습니다." }, { status: 404 }); } const row = own.rows[0]; - if (!isAdmin && row.customer_objid !== r.user.objid) { + const userOwn = r.user.objid ?? r.user.userId; + if (!isAdmin && row.customer_objid !== userOwn && row.customer_objid !== r.user.userId) { return NextResponse.json({ success: false, message: "권한이 없습니다." }, { status: 403 }); } if (row.status !== "REQUESTED") { diff --git a/src/app/api/m/orders/items/update/route.ts b/src/app/api/m/orders/items/update/route.ts index f99cbfc..0a26283 100644 --- a/src/app/api/m/orders/items/update/route.ts +++ b/src/app/api/m/orders/items/update/route.ts @@ -35,7 +35,10 @@ export async function POST(req: NextRequest) { return NextResponse.json({ success: false, message: "발주를 찾을 수 없습니다." }, { status: 404 }); } const order = orderRes.rows[0]; - if (!isAdmin && order.customer_objid !== r.user.objid) { + // 본인 발주 매칭: customer_objid 가 user.objid 또는 user.userId 와 일치하면 OK + // (momo 가입자는 user.objid, FITO 사용자는 user.userId 가 customer_objid 로 들어감) + const userOwn = r.user.objid ?? r.user.userId; + if (!isAdmin && order.customer_objid !== userOwn && order.customer_objid !== r.user.userId) { await client.query("ROLLBACK"); return NextResponse.json({ success: false, message: "권한이 없습니다." }, { status: 403 }); } diff --git a/src/app/api/m/orders/lines/save/route.ts b/src/app/api/m/orders/lines/save/route.ts index d7217f2..5ced23b 100644 --- a/src/app/api/m/orders/lines/save/route.ts +++ b/src/app/api/m/orders/lines/save/route.ts @@ -40,7 +40,9 @@ export async function POST(req: NextRequest) { return NextResponse.json({ success: false, message: "발주를 찾을 수 없습니다." }, { status: 404 }); } const order = orderRes.rows[0]; - if (!isAdmin && order.customer_objid !== r.user.objid) { + // 본인 발주 매칭: customer_objid 가 user.objid 또는 user.userId 와 일치 + const userOwn = r.user.objid ?? r.user.userId; + if (!isAdmin && order.customer_objid !== userOwn && order.customer_objid !== r.user.userId) { await client.query("ROLLBACK"); return NextResponse.json({ success: false, message: "권한이 없습니다." }, { status: 403 }); } diff --git a/src/app/api/m/orders/statement/[id]/route.ts b/src/app/api/m/orders/statement/[id]/route.ts index e982add..28dd80d 100644 --- a/src/app/api/m/orders/statement/[id]/route.ts +++ b/src/app/api/m/orders/statement/[id]/route.ts @@ -26,7 +26,8 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string [id] ); if (!order) return NextResponse.json({ success: false, message: "찾을 수 없습니다." }, { status: 404 }); - if (r.user.role === "USER" && order.customer_objid !== r.user.objid) { + const userOwn = r.user.objid ?? r.user.userId; + if (r.user.role === "USER" && order.customer_objid !== userOwn && order.customer_objid !== r.user.userId) { return NextResponse.json({ success: false, message: "권한 없음" }, { status: 403 }); }
품목구분단가재고수량품목구분단가재고수량
-
+
+
{it.ITEM_NAME} {it.REQUIRES_DELIVERY === "Y" && 택배} - {inCart > 0 && 담은 {inCart}}
-
{it.MAKER_NAME || "-"}
+ {inCart > 0 &&
담은 {inCart}
}
- + + {it.IS_TAX_FREE === "Y" ? "면세" : "과세"} ₩{Number(it.UNIT_PRICE).toLocaleString("ko-KR")}{Number(stock).toLocaleString("ko-KR")} + ₩{Number(it.UNIT_PRICE).toLocaleString("ko-KR")}{Number(stock).toLocaleString("ko-KR")} {soldOut ? ( -
품절
+
품절
) : inCart === 0 ? ( -
+
) : ( -
- +
+ onSetQty(it.OBJID, Number(e.target.value))} - className="w-12 h-8 text-center font-bold text-sm tabular-nums border border-emerald-200 rounded" /> - - + className="w-10 h-7 text-center font-bold text-[11px] tabular-nums border border-emerald-200 rounded" /> + +
)}