fix: [material] 입고관리 코드 정리 + 단가목록 동기화버튼 주석처리
- 입고 상세/처리 다이얼로그 코드 간소화 - 단가 목록 품목마스터 동기화 버튼 주석처리 (미구현) - 테넌트 모듈 분리 분석/계획 문서 추가
This commit is contained in:
@@ -91,16 +91,6 @@ const INITIAL_FORM_DATA: Partial<ReceivingDetailType> = {
|
||||
inventoryAdjustments: [],
|
||||
};
|
||||
|
||||
// 로트번호 생성 (YYMMDD-NN)
|
||||
function generateLotNo(): string {
|
||||
const now = new Date();
|
||||
const yy = String(now.getFullYear()).slice(-2);
|
||||
const mm = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const dd = String(now.getDate()).padStart(2, '0');
|
||||
const seq = String(Math.floor(Math.random() * 100)).padStart(2, '0');
|
||||
return `${yy}${mm}${dd}-${seq}`;
|
||||
}
|
||||
|
||||
// localStorage에서 로그인 사용자 정보 가져오기
|
||||
function getLoggedInUser(): { name: string; department: string } {
|
||||
if (typeof window === 'undefined') return { name: '', department: '' };
|
||||
@@ -169,7 +159,6 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
|
||||
const data = generateReceivingData();
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
lotNo: generateLotNo(),
|
||||
itemCode: data.itemCode,
|
||||
itemName: data.itemName,
|
||||
specification: data.specification,
|
||||
@@ -574,15 +563,12 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 원자재로트 - 수정 가능 */}
|
||||
{/* 원자재로트 - 자동채번 (readOnly) */}
|
||||
<div>
|
||||
<Label className="text-sm text-muted-foreground">원자재로트</Label>
|
||||
<Input
|
||||
className="mt-1.5"
|
||||
value={formData.lotNo || ''}
|
||||
onChange={(e) => setFormData((prev) => ({ ...prev, lotNo: e.target.value }))}
|
||||
placeholder="원자재로트를 입력하세요"
|
||||
/>
|
||||
<div className="mt-1.5 px-3 py-2 bg-gray-200 border border-gray-300 rounded-md text-sm text-gray-500 cursor-not-allowed select-none">
|
||||
{formData.lotNo || (isNewMode ? '저장 시 자동 생성' : '-')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 품목코드 - 검색 모달 선택 */}
|
||||
|
||||
@@ -23,16 +23,6 @@ import {
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import type { ReceivingDetail, ReceivingProcessFormData } from './types';
|
||||
|
||||
// LOT 번호 생성 함수 (YYMMDD-NN 형식)
|
||||
function generateLotNo(): string {
|
||||
const now = new Date();
|
||||
const yy = String(now.getFullYear()).slice(-2);
|
||||
const mm = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const dd = String(now.getDate()).padStart(2, '0');
|
||||
const random = String(Math.floor(Math.random() * 100)).padStart(2, '0');
|
||||
return `${yy}${mm}${dd}-${random}`;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
@@ -42,7 +32,7 @@ interface Props {
|
||||
|
||||
export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete }: Props) {
|
||||
// 폼 데이터
|
||||
const [receivingLot, setReceivingLot] = useState(() => generateLotNo());
|
||||
const [receivingLot, setReceivingLot] = useState('');
|
||||
const [supplierLot, setSupplierLot] = useState('');
|
||||
const [receivingQty, setReceivingQty] = useState<string>((detail.orderQty ?? 0).toString());
|
||||
const [receivingLocation, setReceivingLocation] = useState('');
|
||||
@@ -56,9 +46,7 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete
|
||||
const validateForm = useCallback((): boolean => {
|
||||
const errors: string[] = [];
|
||||
|
||||
if (!receivingLot.trim()) {
|
||||
errors.push('입고LOT는 필수 입력 항목입니다.');
|
||||
}
|
||||
// 입고LOT는 API가 자동 채번하므로 필수 검증 제거
|
||||
|
||||
if (!receivingQty.trim() || isNaN(Number(receivingQty)) || Number(receivingQty) <= 0) {
|
||||
errors.push('입고수량은 필수 입력 항목입니다. 유효한 숫자를 입력해주세요.');
|
||||
@@ -68,7 +56,7 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete
|
||||
|
||||
setValidationErrors(errors);
|
||||
return errors.length === 0;
|
||||
}, [receivingLot, receivingQty]);
|
||||
}, [receivingQty]);
|
||||
|
||||
// 입고 처리
|
||||
const handleSubmit = useCallback(async () => {
|
||||
@@ -161,16 +149,12 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete
|
||||
{/* 입력 필드 */}
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label className="text-sm">
|
||||
입고LOT <span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Label className="text-sm text-muted-foreground">입고LOT</Label>
|
||||
<Input
|
||||
value={receivingLot}
|
||||
onChange={(e) => {
|
||||
setReceivingLot(e.target.value);
|
||||
setValidationErrors([]);
|
||||
}}
|
||||
placeholder="예: 251223-41"
|
||||
readOnly
|
||||
className="bg-gray-50"
|
||||
placeholder="저장 시 자동 생성"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
|
||||
@@ -497,7 +497,7 @@ function transformFrontendToApi(
|
||||
if (data.remark !== undefined) result.remark = data.remark;
|
||||
if (data.receivingQty !== undefined) result.receiving_qty = data.receivingQty;
|
||||
if (data.receivingDate !== undefined) result.receiving_date = data.receivingDate;
|
||||
if (data.lotNo !== undefined) result.lot_no = data.lotNo;
|
||||
// lot_no는 API가 자동 채번하므로 프론트에서 전송하지 않음
|
||||
if (data.supplierMaterialNo !== undefined) result.material_no = data.supplierMaterialNo;
|
||||
if (data.manufacturer !== undefined) result.manufacturer = data.manufacturer;
|
||||
if (data.certificateFileId !== undefined) result.certificate_file_id = data.certificateFileId;
|
||||
@@ -511,7 +511,7 @@ function transformProcessDataToApi(
|
||||
): Record<string, unknown> {
|
||||
return {
|
||||
receiving_qty: data.receivingQty,
|
||||
lot_no: data.receivingLot,
|
||||
// lot_no는 API가 자동 채번하므로 프론트에서 전송하지 않음
|
||||
supplier_lot: data.supplierLot,
|
||||
receiving_location: data.receivingLocation,
|
||||
remark: data.remark,
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
Package,
|
||||
AlertCircle,
|
||||
CheckCircle2,
|
||||
RefreshCw,
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@@ -326,18 +325,19 @@ export function PricingListClient({
|
||||
};
|
||||
|
||||
// 헤더 액션 (함수로 정의)
|
||||
const headerActions = () => (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
// TODO: API 연동 시 품목 마스터 동기화 로직 구현
|
||||
}}
|
||||
className="ml-auto gap-2"
|
||||
>
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
품목 마스터 동기화
|
||||
</Button>
|
||||
);
|
||||
// NOTE: 품목 마스터 동기화 버튼 - 실제 로직 미구현 상태로 주석처리
|
||||
// const headerActions = () => (
|
||||
// <Button
|
||||
// variant="outline"
|
||||
// onClick={() => {
|
||||
// // TODO: API 연동 시 품목 마스터 동기화 로직 구현
|
||||
// }}
|
||||
// className="ml-auto gap-2"
|
||||
// >
|
||||
// <RefreshCw className="h-4 w-4" />
|
||||
// 품목 마스터 동기화
|
||||
// </Button>
|
||||
// );
|
||||
|
||||
// UniversalListPage 설정
|
||||
const pricingConfig: UniversalListConfig<PricingListItem> = {
|
||||
@@ -356,7 +356,7 @@ export function PricingListClient({
|
||||
},
|
||||
|
||||
columns: tableColumns,
|
||||
headerActions,
|
||||
// headerActions, // 품목 마스터 동기화 버튼 미구현으로 주석처리
|
||||
stats,
|
||||
tabs,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user