diff --git a/next.config.ts b/next.config.ts index 7a28a123..73a3226e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -6,6 +6,7 @@ const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts'); const nextConfig: NextConfig = { reactStrictMode: false, // ๐Ÿงช TEST: Strict Mode ๋น„ํ™œ์„ฑํ™”๋กœ ์ค‘๋ณต ์š”์ฒญ ํ…Œ์ŠคํŠธ turbopack: {}, // โœ… CRITICAL: Next.js 15 + next-intl compatibility + serverExternalPackages: ['puppeteer'], // puppeteer๋Š” Node.js ์ „์šฉ - Webpack ๋ฒˆ๋“ค ์ œ์™ธ images: { remotePatterns: [ { diff --git a/package-lock.json b/package-lock.json index 293a7d7e..88a82e40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,7 +47,7 @@ "lucide-react": "^0.552.0", "next": "^15.5.9", "next-intl": "^4.4.0", - "puppeteer": "^24.36.0", + "puppeteer": "^23.11.1", "react": "^19.2.3", "react-day-picker": "^9.11.1", "react-dom": "^19.2.3", @@ -1535,17 +1535,18 @@ } }, "node_modules/@puppeteer/browsers": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.11.1.tgz", - "integrity": "sha512-YmhAxs7XPuxN0j7LJloHpfD1ylhDuFmmwMvfy/+6nBSrETT2ycL53LrhgPtR+f+GcPSybQVuQ5inWWu5MrWCpA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.6.1.tgz", + "integrity": "sha512-aBSREisdsGH890S2rQqK82qmQYU3uFpSH8wcZWHgHzl3LfzsxAKbLNiAG9mO8v1Y0UICBeClICxPJvyr0rcuxg==", "license": "Apache-2.0", "dependencies": { - "debug": "^4.4.3", + "debug": "^4.4.0", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.5.0", - "semver": "^7.7.3", - "tar-fs": "^3.1.1", + "semver": "^7.6.3", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", "yargs": "^17.7.2" }, "bin": { @@ -4944,6 +4945,26 @@ "node": ">= 0.6.0" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/basic-ftp": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.1.0.tgz", @@ -4976,6 +4997,30 @@ "node": ">=8" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -5115,22 +5160,22 @@ } }, "node_modules/chromium-bidi": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-13.0.1.tgz", - "integrity": "sha512-c+RLxH0Vg2x2syS9wPw378oJgiJNXtYXUvnVAldUlt5uaHekn0CCU7gPksNgHjrH1qFhmjVXQj4esvuthuC7OQ==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.11.0.tgz", + "integrity": "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==", "license": "Apache-2.0", "dependencies": { - "mitt": "^3.0.1", - "zod": "^3.24.1" + "mitt": "3.0.1", + "zod": "3.23.8" }, "peerDependencies": { "devtools-protocol": "*" } }, "node_modules/chromium-bidi/node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -5623,9 +5668,9 @@ "license": "MIT" }, "node_modules/devtools-protocol": { - "version": "0.0.1551306", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1551306.tgz", - "integrity": "sha512-CFx8QdSim8iIv+2ZcEOclBKTQY6BI1IEDa7Tm9YkwAXzEWFndTEzpTo5jAUhSnq24IC7xaDw0wvGcm96+Y3PEg==", + "version": "0.0.1367902", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1367902.tgz", + "integrity": "sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==", "license": "BSD-3-Clause" }, "node_modules/doctrine": { @@ -7001,6 +7046,26 @@ "node": ">= 14" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -8312,6 +8377,17 @@ } } }, + "node_modules/next-intl/node_modules/@swc/helpers": { + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", + "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==", + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -9043,17 +9119,18 @@ } }, "node_modules/puppeteer": { - "version": "24.36.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.36.0.tgz", - "integrity": "sha512-BD/VCyV/Uezvd6o7Fd1DmEJSxTzofAKplzDy6T9d4WbLTQ5A+06zY7VwO91ZlNU22vYE8sidVEsTpTrKc+EEnQ==", + "version": "23.11.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.11.1.tgz", + "integrity": "sha512-53uIX3KR5en8l7Vd8n5DUv90Ae9QDQsyIthaUFVzwV6yU750RjqRznEtNMBT20VthqAdemnJN+hxVdmMHKt7Zw==", + "deprecated": "< 24.15.0 is no longer supported", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.11.1", - "chromium-bidi": "13.0.1", + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1551306", - "puppeteer-core": "24.36.0", + "devtools-protocol": "0.0.1367902", + "puppeteer-core": "23.11.1", "typed-query-selector": "^2.12.0" }, "bin": { @@ -9064,18 +9141,17 @@ } }, "node_modules/puppeteer-core": { - "version": "24.36.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.36.0.tgz", - "integrity": "sha512-P3Ou0MAFDCQ0dK1d9F9+8jTrg6JvXjUacgG0YkJQP4kbEnUOGokSDEMmMId5ZhXD5HwsHM202E9VwEpEjWfwxg==", + "version": "23.11.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.11.1.tgz", + "integrity": "sha512-3HZ2/7hdDKZvZQ7dhhITOUg4/wOrDRjyK2ZBllRB0ZCOi9u0cwq1ACHDjBB+nX+7+kltHjQvBRdeY7+W0T+7Gg==", "license": "Apache-2.0", "dependencies": { - "@puppeteer/browsers": "2.11.1", - "chromium-bidi": "13.0.1", - "debug": "^4.4.3", - "devtools-protocol": "0.0.1551306", + "@puppeteer/browsers": "2.6.1", + "chromium-bidi": "0.11.0", + "debug": "^4.4.0", + "devtools-protocol": "0.0.1367902", "typed-query-selector": "^2.12.0", - "webdriver-bidi-protocol": "0.4.0", - "ws": "^8.19.0" + "ws": "^8.18.0" }, "engines": { "node": ">=18" @@ -10169,6 +10245,12 @@ "utrie": "^1.0.2" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT" + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -10403,6 +10485,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "license": "MIT", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -10571,12 +10663,6 @@ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "license": "MIT" }, - "node_modules/webdriver-bidi-protocol": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.0.tgz", - "integrity": "sha512-U9VIlNRrq94d1xxR9JrCEAx5Gv/2W7ERSv8oWRoNe/QYbfccS0V3h/H6qeNeCRJxXGMhhnkqvwNrvPAYeuP9VA==", - "license": "Apache-2.0" - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 6f873c77..b2f4b8aa 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "lucide-react": "^0.552.0", "next": "^15.5.9", "next-intl": "^4.4.0", - "puppeteer": "^24.36.0", + "puppeteer": "^23.11.1", "react": "^19.2.3", "react-day-picker": "^9.11.1", "react-dom": "^19.2.3", diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx index b19118a9..bd80be06 100644 --- a/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx +++ b/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx @@ -522,15 +522,15 @@ function OrderListContent() { {order.expectedShipDate || "-"} {order.orderDate || "-"} {order.client || "-"} - {(order as any).productName || "-"} - {(order as any).receiver || "-"} - {(order as any).receiverAddress || "-"} - {(order as any).receiverPlace || "-"} + {order.productName || "-"} + {order.receiver || "-"} + {order.receiverAddress || "-"} + {order.receiverPlace || "-"} {order.deliveryMethodLabel || "-"} - {(order as any).manager || "-"} - {(order as any).frameCount || "-"} + {order.manager || "-"} + {order.frameCount || "-"} {getOrderStatusBadge(order.status)} - {(order as any).remarks || "-"} + {order.remarks || "-"} ); }; diff --git a/src/app/api/pdf/generate/route.ts b/src/app/api/pdf/generate/route.ts index a70abf4e..2057349f 100644 --- a/src/app/api/pdf/generate/route.ts +++ b/src/app/api/pdf/generate/route.ts @@ -35,14 +35,16 @@ export async function POST(request: NextRequest) { ); } - // Puppeteer ๋ธŒ๋ผ์šฐ์ € ์‹คํ–‰ + // Puppeteer ๋ธŒ๋ผ์šฐ์ € ์‹คํ–‰ (Docker Alpine์—์„œ๋Š” ์‹œ์Šคํ…œ Chromium ์‚ฌ์šฉ) const browser = await puppeteer.launch({ headless: true, + executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || undefined, args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu', + '--disable-software-rasterizer', ], }); diff --git a/src/components/orders/OrderSalesDetailEdit.tsx b/src/components/orders/OrderSalesDetailEdit.tsx index 9508332d..02e33ea7 100644 --- a/src/components/orders/OrderSalesDetailEdit.tsx +++ b/src/components/orders/OrderSalesDetailEdit.tsx @@ -45,6 +45,7 @@ import { updateOrder, type OrderStatus, } from "@/components/orders"; +import { getDeliveryMethodOptions, getCommonCodeOptions } from "@/lib/api/common-codes"; // ์ˆ˜์ • ํผ ๋ฐ์ดํ„ฐ interface EditFormData { @@ -88,22 +89,11 @@ interface EditFormData { }>; } -// ๋ฐฐ์†ก๋ฐฉ์‹ ์˜ต์…˜ -const DELIVERY_METHODS = [ - { value: "direct", label: "์ง์ ‘๋ฐฐ์ฐจ" }, - { value: "pickup", label: "์ƒ์ฐจ" }, - { value: "courier", label: "ํƒ๋ฐฐ" }, - { value: "self", label: "์ง์ ‘์ˆ˜๋ น" }, - { value: "freight", label: "ํ™”๋ฌผ" }, -]; - -// ์šด์ž„๋น„์šฉ ์˜ต์…˜ -const SHIPPING_COSTS = [ - { value: "free", label: "๋ฌด๋ฃŒ" }, - { value: "prepaid", label: "์„ ๋ถˆ" }, - { value: "collect", label: "์ฐฉ๋ถˆ" }, - { value: "negotiable", label: "ํ˜‘์˜" }, -]; +// ์˜ต์…˜ ํƒ€์ž… ์ •์˜ +interface SelectOption { + value: string; + label: string; +} // ์ƒํƒœ ๋ฑƒ์ง€ ํ—ฌํผ @@ -141,6 +131,10 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) { const [isSaving, setIsSaving] = useState(false); const [expandedProducts, setExpandedProducts] = useState>(new Set()); + // ๊ณตํ†ต์ฝ”๋“œ ์˜ต์…˜ + const [deliveryMethods, setDeliveryMethods] = useState([]); + const [shippingCosts, setShippingCosts] = useState([]); + // ์ œํ’ˆ-๋ถ€ํ’ˆ ํŠธ๋ฆฌ ํ† ๊ธ€ const toggleProduct = (key: string) => { setExpandedProducts((prev) => { @@ -265,6 +259,24 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) { loadOrder(); }, [orderId, router]); + // ๊ณตํ†ต์ฝ”๋“œ ์˜ต์…˜ ๋กœ๋“œ + useEffect(() => { + async function loadCommonCodes() { + const [deliveryResult, shippingResult] = await Promise.all([ + getDeliveryMethodOptions(), + getCommonCodeOptions('shipping_cost'), + ]); + + if (deliveryResult.success && deliveryResult.data) { + setDeliveryMethods(deliveryResult.data); + } + if (shippingResult.success && shippingResult.data) { + setShippingCosts(shippingResult.data); + } + } + loadCommonCodes(); + }, []); + const handleCancel = () => { // V2 ํŒจํ„ด: ?mode=view๋กœ ์ด๋™ router.push(`/sales/order-management-sales/${orderId}?mode=view`); @@ -453,7 +465,7 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) { - {DELIVERY_METHODS.map((method) => ( + {deliveryMethods.map((method) => ( {method.label} @@ -476,7 +488,7 @@ export function OrderSalesDetailEdit({ orderId }: OrderSalesDetailEditProps) { - {SHIPPING_COSTS.map((cost) => ( + {shippingCosts.map((cost) => ( {cost.label} diff --git a/src/components/orders/OrderSalesDetailView.tsx b/src/components/orders/OrderSalesDetailView.tsx index 90fe2059..79146f5a 100644 --- a/src/components/orders/OrderSalesDetailView.tsx +++ b/src/components/orders/OrderSalesDetailView.tsx @@ -354,7 +354,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) { - + diff --git a/src/components/orders/actions.ts b/src/components/orders/actions.ts index 28da348a..df399dd0 100644 --- a/src/components/orders/actions.ts +++ b/src/components/orders/actions.ts @@ -27,6 +27,7 @@ interface ApiOrder { delivery_date: string | null; delivery_method_code: string | null; delivery_method_label?: string; // API์—์„œ ์กฐํšŒํ•œ ๋ฐฐ์†ก๋ฐฉ์‹ ๋ผ๋ฒจ + shipping_cost_label?: string; // API์—์„œ ์กฐํšŒํ•œ ์šด์ž„๋น„์šฉ ๋ผ๋ฒจ received_at: string | null; memo: string | null; remarks: string | null; @@ -231,11 +232,17 @@ export interface Order { remarks?: string; note?: string; items?: OrderItem[]; + // ๋ชฉ๋ก ํŽ˜์ด์ง€์šฉ ์ถ”๊ฐ€ ํ•„๋“œ + productName?: string; // ์ œํ’ˆ๋ช… (์ฒซ ๋ฒˆ์งธ ํ’ˆ๋ชฉ๋ช…) + receiverAddress?: string; // ์ˆ˜์‹ ์ฃผ์†Œ + receiverPlace?: string; // ์ˆ˜์‹ ์ฒ˜ (์ „ํ™”๋ฒˆํ˜ธ) + frameCount?: number; // ํ‹€์ˆ˜ (์ˆ˜๋Ÿ‰) // ์ƒ์„ธ ํŽ˜์ด์ง€์šฉ ์ถ”๊ฐ€ ํ•„๋“œ manager?: string; // ๋‹ด๋‹น์ž contact?: string; // ์—ฐ๋ฝ์ฒ˜ (client_contact) deliveryRequestDate?: string; // ๋‚ฉํ’ˆ์š”์ฒญ์ผ - shippingCost?: string; // ์šด์ž„๋น„์šฉ + shippingCost?: string; // ์šด์ž„๋น„์šฉ (์ฝ”๋“œ) + shippingCostLabel?: string; // ์šด์ž„๋น„์šฉ (๋ผ๋ฒจ) receiver?: string; // ์ˆ˜์‹ ์ž receiverContact?: string; // ์ˆ˜์‹ ์ฒ˜ ์—ฐ๋ฝ์ฒ˜ address?: string; // ์ˆ˜์‹ ์ฒ˜ ์ฃผ์†Œ @@ -457,12 +464,19 @@ function transformApiToFrontend(apiData: ApiOrder): Order { memo: apiData.memo ?? undefined, remarks: apiData.remarks ?? undefined, note: apiData.note ?? undefined, - items: apiData.items?.map(transformItemApiToFrontend) || [], // ์ƒ์„ธ ํŽ˜์ด์ง€์šฉ ์ถ”๊ฐ€ ํ•„๋“œ (API์—์„œ ๋งคํ•‘) + items: apiData.items?.map(transformItemApiToFrontend) || [], + // ๋ชฉ๋ก ํŽ˜์ด์ง€์šฉ ์ถ”๊ฐ€ ํ•„๋“œ + productName: apiData.items?.[0]?.item_name ?? undefined, + receiverAddress: apiData.options?.shipping_address ?? undefined, + receiverPlace: apiData.options?.receiver_contact ?? undefined, + frameCount: apiData.quantity ?? undefined, + // ์ƒ์„ธ ํŽ˜์ด์ง€์šฉ ์ถ”๊ฐ€ ํ•„๋“œ (API์—์„œ ๋งคํ•‘) manager: apiData.client?.manager_name ?? undefined, contact: apiData.client_contact ?? apiData.client?.phone ?? undefined, deliveryRequestDate: apiData.delivery_date ?? undefined, // delivery_date๋ฅผ ๊ณต์œ  // options JSON์—์„œ ์ถ”์ถœ shippingCost: apiData.options?.shipping_cost_code ?? undefined, + shippingCostLabel: apiData.shipping_cost_label ?? undefined, receiver: apiData.options?.receiver ?? undefined, receiverContact: apiData.options?.receiver_contact ?? undefined, address: apiData.options?.shipping_address ?? undefined, diff --git a/src/components/quotes/LocationDetailPanel.tsx b/src/components/quotes/LocationDetailPanel.tsx index 2cfa271a..a8287819 100644 --- a/src/components/quotes/LocationDetailPanel.tsx +++ b/src/components/quotes/LocationDetailPanel.tsx @@ -402,7 +402,7 @@ export function LocationDetailPanel({ {finishedGoods.map((fg) => ( - {fg.item_code} + {fg.item_code} {fg.item_name} ))} @@ -477,8 +477,8 @@ export function LocationDetailPanel({ - {/* 3ํ–‰: ์ œ์ž‘์‚ฌ์ด์ฆˆ, ์‚ฐ์ถœ์ค‘๋Ÿ‰, ์‚ฐ์ถœ๋ฉด์ , ์ˆ˜๋Ÿ‰ */} -
+ {/* 3ํ–‰: ์ œ์ž‘์‚ฌ์ด์ฆˆ, ์‚ฐ์ถœ์ค‘๋Ÿ‰, ์‚ฐ์ถœ๋ฉด์ , ์ˆ˜๋Ÿ‰, ์‚ฐ์ถœํ•˜๊ธฐ */} +
์ œ์ž‘์‚ฌ์ด์ฆˆ

@@ -503,6 +503,24 @@ export function LocationDetailPanel({ : "-"}

+
+ ์ˆ˜๋Ÿ‰ (QTY) + { + if (!location || disabled) return; + // ์ˆ˜๋Ÿ‰ ๋ณ€๊ฒฝ ์‹œ totalPrice ์žฌ๊ณ„์‚ฐ + const unitPrice = location.unitPrice || 0; + onUpdateLocation(location.id, { + quantity: newQty, + totalPrice: unitPrice * newQty, + }); + }} + className="h-8 text-sm font-semibold" + min={1} + disabled={disabled} + /> +