[feat] negodata/front: 상품 UI 보강 — 매입가·판매가 입력 등
상품 등록/목록·엑셀 업로드 화면에 매입가·판매가 등 가격 필드 반영. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a40257ddc1
commit
b42d084063
@ -171,7 +171,9 @@ function toItemCreate(row: RawRow): ItemCreate {
|
||||
delivery_type: DELIVERY_LABEL_TO_CODE[row.delivery_type.trim()] ?? undefined,
|
||||
vat_yn: row.vat_yn.trim() ? parseYn(row.vat_yn) : undefined,
|
||||
delivery_fee_yn: row.delivery_fee_yn.trim() ? parseYn(row.delivery_fee_yn) : undefined,
|
||||
internet_lowest_price_yn: false,
|
||||
// minPrice(최저한도) = 인터넷 최저가(실값) → internet_lowest_price 로 저장(수기 폼과 동일).
|
||||
internet_lowest_price: row.minPrice,
|
||||
internet_lowest_price_yn: row.minPrice > 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Sheet } from '@/components/ui/sheet';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { type Product, toMinPrice } from '../types';
|
||||
import { type Product } from '../types';
|
||||
|
||||
// 폼 검증 스키마. 필수: 상품명/상품코드/단가/최저가. 나머지는 선택.
|
||||
const schema = z.object({
|
||||
@ -60,7 +60,7 @@ function buildDefaults(mode: 'create' | 'edit', product: Product | null): FormVa
|
||||
code: product.code || '',
|
||||
category: product.category || '',
|
||||
price: product.price || 0,
|
||||
minPrice: toMinPrice(product.price),
|
||||
minPrice: product.internet_lowest_price ?? 0,
|
||||
modelName: product.model_name || '',
|
||||
specification: product.spec || '',
|
||||
manufacturer: product.manufacturer || '',
|
||||
@ -129,7 +129,7 @@ export function ProductFormSheet({
|
||||
|
||||
const deliveryTypes = DELIVERY_TYPE_OPTIONS;
|
||||
|
||||
// minPrice는 화면 전용(서버 미전송). 검증된 값만 payload로.
|
||||
// minPrice = 인터넷 최저가(실값) → internet_lowest_price 로 저장한다.
|
||||
const onValid = async (v: FormValues) => {
|
||||
// 기존 카테고리면 그 category_type(id) 재사용, 처음 쓰는 카테고리면 max+1 부여.
|
||||
const categoryName = v.category.trim();
|
||||
@ -151,6 +151,7 @@ export function ProductFormSheet({
|
||||
vat_yn: v.vatYn,
|
||||
delivery_fee_yn: v.deliveryFeeYn,
|
||||
internet_lowest_price_yn: v.internetLowestPriceYn,
|
||||
internet_lowest_price: v.minPrice,
|
||||
purchase_price: v.purchasePrice,
|
||||
selling_price: v.sellingPrice,
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@ import { Image as ImageIcon } from 'lucide-react';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { DataTable } from '@/components/ui/data-table';
|
||||
import { TablePagination } from '@/components/ui/table-pagination';
|
||||
import { type Product, toMinPrice } from '../types';
|
||||
import { type Product } from '../types';
|
||||
|
||||
type ProductTableProps = {
|
||||
data: Product[];
|
||||
@ -91,7 +91,7 @@ export function ProductTable({
|
||||
header: '인터넷 최저가',
|
||||
align: 'right',
|
||||
cellClassName: 'font-mono font-semibold text-rose-600 dark:text-rose-400',
|
||||
cell: (prod) => `₩${(prod.minPrice || toMinPrice(prod.price)).toLocaleString()}`,
|
||||
cell: (prod) => (prod.internet_lowest_price != null ? `₩${Number(prod.internet_lowest_price).toLocaleString()}` : '-'),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
@ -12,7 +12,7 @@ import type { ReqUpdateItem } from '@/api/generated/model/reqUpdateItem';
|
||||
import type { ResItem } from '@/api/generated/model/resItem';
|
||||
import type { ItemData } from '@/api/generated/model/itemData';
|
||||
import type { BulkFailure } from '@/lib/excel';
|
||||
import { type Product, toMinPrice } from '../types';
|
||||
import { type Product } from '../types';
|
||||
|
||||
// 엑셀 중복검사 + 최저가 모달은 "현재 페이지 밖"의 상품도 코드/ID로 조회해야 해서
|
||||
// 전체 목록(최대 100건)을 따로 받는다. (카테고리 목록은 더 이상 여기서 만들지 않는다 — 아래 categoriesQuery.)
|
||||
@ -20,7 +20,7 @@ const META_PARAMS: ListItemsParams = { size: 100 };
|
||||
|
||||
// 서버 ItemData → UI Product (화면 전용 파생 필드 부여).
|
||||
function toProduct(it: ItemData): Product {
|
||||
return { ...it, id: it.item_id, minPrice: toMinPrice(it.price), status: 'ACTIVE' };
|
||||
return { ...it, id: it.item_id, minPrice: it.internet_lowest_price ?? 0, status: 'ACTIVE' };
|
||||
}
|
||||
|
||||
// 서버 공통응답(result.success=false)을 한글 사유로 변환. 정상이면 null.
|
||||
|
||||
@ -1,4 +1 @@
|
||||
export type { Product } from '@/types';
|
||||
|
||||
// 인터넷 최저가 데모 산정(표준 단가의 83%). 서버 미연동 — 표시/초기값 용도.
|
||||
export const toMinPrice = (price?: number | null) => Math.round((price || 0) * 0.83);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user