fix: 프로젝트 전체 TypeScript 타입에러 408개 수정 (tsc --noEmit 0 errors)
- 공통 템플릿 타입 수정 (IntegratedDetailTemplate, UniversalListPage) - 페이지(app/[locale]) 타입 호환성 수정 (80개) - 재고/자재 모듈 타입 수정 (StockStatus, ReceivingManagement) - 생산 모듈 타입 수정 (WorkOrders, WorkerScreen, WorkResults) - 주문/출고 모듈 타입 수정 (ShipmentManagement, Orders) - 견적/단가 모듈 타입 수정 (Quotes, Pricing) - 건설 모듈 타입 수정 (49개, 17개 하위 모듈) - HR 모듈 타입 수정 (CardManagement, VacationManagement 등) - 설정 모듈 타입 수정 (PermissionManagement, AccountManagement 등) - 게시판 모듈 타입 수정 (BoardManagement, BoardList 등) - 회계 모듈 타입 수정 (VendorManagement, BadDebtCollection 등) - 기타 모듈 타입 수정 (CEODashboard, clients, vehicle 등) - 유틸/훅/API 타입 수정 (hooks, contexts, lib) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,20 +28,26 @@ import {
|
||||
} from "@/components/ui/select";
|
||||
import { Package } from "lucide-react";
|
||||
|
||||
// 품목 타입
|
||||
// 품목 타입 - actions.ts의 OrderItem과 호환
|
||||
export interface OrderItem {
|
||||
id: string;
|
||||
itemCode: string; // 품목코드
|
||||
itemId?: number;
|
||||
itemCode?: string; // 품목코드
|
||||
itemName: string; // 품명
|
||||
type: string; // 층
|
||||
symbol: string; // 부호
|
||||
spec: string; // 규격
|
||||
width: number; // 가로 (mm)
|
||||
height: number; // 세로 (mm)
|
||||
specification?: string;
|
||||
type?: string; // 층
|
||||
symbol?: string; // 부호
|
||||
spec?: string; // 규격
|
||||
width?: number; // 가로 (mm)
|
||||
height?: number; // 세로 (mm)
|
||||
quantity: number; // 수량
|
||||
unit: string; // 단위
|
||||
unit?: string; // 단위
|
||||
unitPrice: number; // 단가
|
||||
amount: number; // 금액
|
||||
supplyAmount?: number;
|
||||
taxAmount?: number;
|
||||
totalAmount?: number;
|
||||
amount?: number; // 금액
|
||||
sortOrder?: number;
|
||||
guideRailType?: string; // 가이드레일 타입
|
||||
finish?: string; // 마감
|
||||
floor?: string; // 층
|
||||
|
||||
@@ -62,7 +62,10 @@ import { useDevFill } from "@/components/dev";
|
||||
import { generateOrderData } from "@/components/dev/generators/orderData";
|
||||
|
||||
// 수주 폼 데이터 타입
|
||||
// Index signature allows compatibility with Record<string, unknown> (required by actions API)
|
||||
export interface OrderFormData {
|
||||
[key: string]: unknown;
|
||||
|
||||
// 견적 정보
|
||||
selectedQuotation?: QuotationForSelect;
|
||||
|
||||
@@ -208,7 +211,7 @@ export function OrderRegistration({
|
||||
|
||||
// 금액 계산
|
||||
useEffect(() => {
|
||||
const subtotal = form.items.reduce((sum, item) => sum + item.amount, 0);
|
||||
const subtotal = form.items.reduce((sum, item) => sum + (item.amount ?? 0), 0);
|
||||
const discountAmount = subtotal * (form.discountRate / 100);
|
||||
const totalAmount = subtotal - discountAmount;
|
||||
|
||||
@@ -349,7 +352,7 @@ export function OrderRegistration({
|
||||
}, []);
|
||||
|
||||
// 저장 핸들러
|
||||
const handleSave = useCallback(async () => {
|
||||
const handleSave = useCallback(async (): Promise<{ success: boolean; error?: string }> => {
|
||||
// 유효성 검사
|
||||
const errors = validateForm();
|
||||
setFieldErrors(errors);
|
||||
@@ -357,12 +360,16 @@ export function OrderRegistration({
|
||||
const errorCount = Object.keys(errors).length;
|
||||
if (errorCount > 0) {
|
||||
toast.error(`입력 내용을 확인해주세요. (${errorCount}개 오류)`);
|
||||
return;
|
||||
return { success: false, error: `입력 내용을 확인해주세요. (${errorCount}개 오류)` };
|
||||
}
|
||||
|
||||
setIsSaving(true);
|
||||
try {
|
||||
await onSave(form);
|
||||
return { success: true };
|
||||
} catch (e) {
|
||||
const errorMsg = e instanceof Error ? e.message : '저장 중 오류가 발생했습니다.';
|
||||
return { success: false, error: errorMsg };
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
@@ -813,7 +820,7 @@ export function OrderRegistration({
|
||||
{formatAmount(item.unitPrice)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right font-medium">
|
||||
{formatAmount(item.amount)}
|
||||
{formatAmount(item.amount ?? 0)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Button
|
||||
@@ -894,10 +901,8 @@ export function OrderRegistration({
|
||||
config={config}
|
||||
mode={isEditMode ? "edit" : "create"}
|
||||
isLoading={false}
|
||||
isSubmitting={isSaving}
|
||||
onBack={onBack}
|
||||
onCancel={onBack}
|
||||
onSubmit={handleSave}
|
||||
onSubmit={() => handleSave()}
|
||||
renderForm={renderFormContent}
|
||||
/>
|
||||
|
||||
|
||||
@@ -337,8 +337,8 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
|
||||
<InfoItem label="발주처" value={order.client} />
|
||||
<InfoItem label="현장명" value={order.siteName} />
|
||||
<InfoItem label="담당자" value={order.manager} />
|
||||
<InfoItem label="연락처" value={order.contact} />
|
||||
<InfoItem label="담당자" value={order.manager || ""} />
|
||||
<InfoItem label="연락처" value={order.contact || ""} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -352,12 +352,12 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-6">
|
||||
<InfoItem label="수주일자" value={order.orderDate} />
|
||||
<InfoItem label="출고예정일" value={order.expectedShipDate || "미정"} />
|
||||
<InfoItem label="납품요청일" value={order.deliveryRequestDate} />
|
||||
<InfoItem label="배송방식" value={order.deliveryMethodLabel} />
|
||||
<InfoItem label="운임비용" value={order.shippingCostLabel} />
|
||||
<InfoItem label="수신(반장/업체)" value={order.receiver} />
|
||||
<InfoItem label="수신처 연락처" value={order.receiverContact} />
|
||||
<InfoItem label="수신처 주소" value={order.address} />
|
||||
<InfoItem label="납품요청일" value={order.deliveryRequestDate || ""} />
|
||||
<InfoItem label="배송방식" value={order.deliveryMethodLabel || ""} />
|
||||
<InfoItem label="운임비용" value={order.shippingCostLabel || ""} />
|
||||
<InfoItem label="수신(반장/업체)" value={order.receiver || ""} />
|
||||
<InfoItem label="수신처 연락처" value={order.receiverContact || ""} />
|
||||
<InfoItem label="수신처 주소" value={order.address || ""} />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -397,7 +397,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{order.items.map((item, index) => (
|
||||
{(order.items || []).map((item, index) => (
|
||||
<TableRow key={item.id}>
|
||||
<TableCell className="text-center">{index + 1}</TableCell>
|
||||
<TableCell>
|
||||
@@ -415,7 +415,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
{formatAmount(item.unitPrice)}원
|
||||
</TableCell>
|
||||
<TableCell className="text-right font-medium">
|
||||
{formatAmount(item.amount)}원
|
||||
{formatAmount(item.amount ?? 0)}원
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
@@ -428,7 +428,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<span className="text-muted-foreground">소계:</span>
|
||||
<span className="w-32 text-right">
|
||||
{formatAmount(order.subtotal)}원
|
||||
{formatAmount(order.subtotal ?? 0)}원
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
@@ -438,7 +438,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
<div className="flex items-center gap-4 text-lg font-semibold">
|
||||
<span>총금액:</span>
|
||||
<span className="w-32 text-right text-green-600">
|
||||
{formatAmount(order.totalAmount)}원
|
||||
{formatAmount(order.totalAmount ?? 0)}원
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -624,7 +624,7 @@ export function OrderSalesDetailView({ orderId }: OrderSalesDetailViewProps) {
|
||||
<div className="flex justify-between">
|
||||
<span className="text-muted-foreground">총금액</span>
|
||||
<span className="font-medium text-green-600">
|
||||
{formatAmount(order.totalAmount)}원
|
||||
{formatAmount(order.totalAmount ?? 0)}원
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
|
||||
@@ -75,6 +75,7 @@ interface ApiClient {
|
||||
manager_name?: string;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
grade?: string;
|
||||
}
|
||||
|
||||
interface ApiQuote {
|
||||
@@ -116,6 +117,7 @@ interface ApiQuoteForSelect {
|
||||
name: string;
|
||||
contact_person?: string; // 담당자
|
||||
phone?: string;
|
||||
grade?: string; // 등급 (A, B, C)
|
||||
} | null;
|
||||
items?: ApiQuoteItem[];
|
||||
}
|
||||
@@ -279,6 +281,8 @@ export interface OrderItem {
|
||||
totalAmount: number;
|
||||
amount?: number; // totalAmount alias
|
||||
sortOrder: number;
|
||||
width?: number; // 가로 (mm) - ItemAddDialog 호환
|
||||
height?: number; // 세로 (mm) - ItemAddDialog 호환
|
||||
}
|
||||
|
||||
export interface OrderFormData {
|
||||
@@ -330,6 +334,11 @@ export interface OrderStats {
|
||||
cancelled: number;
|
||||
totalAmount: number;
|
||||
confirmedAmount: number;
|
||||
// 대시보드 통계용 추가 필드 (API에서 선택적으로 반환)
|
||||
thisMonthAmount?: number;
|
||||
splitPending?: number;
|
||||
productionPending?: number;
|
||||
shipPending?: number;
|
||||
}
|
||||
|
||||
// 견적→수주 변환용
|
||||
@@ -771,7 +780,7 @@ export async function getOrderById(id: string): Promise<{
|
||||
/**
|
||||
* 수주 생성
|
||||
*/
|
||||
export async function createOrder(data: OrderFormData): Promise<{
|
||||
export async function createOrder(data: OrderFormData | Record<string, unknown>): Promise<{
|
||||
success: boolean;
|
||||
data?: Order;
|
||||
error?: string;
|
||||
@@ -809,7 +818,7 @@ export async function createOrder(data: OrderFormData): Promise<{
|
||||
/**
|
||||
* 수주 수정
|
||||
*/
|
||||
export async function updateOrder(id: string, data: OrderFormData): Promise<{
|
||||
export async function updateOrder(id: string, data: OrderFormData | Record<string, unknown>): Promise<{
|
||||
success: boolean;
|
||||
data?: Order;
|
||||
error?: string;
|
||||
|
||||
@@ -28,6 +28,7 @@ interface SalesOrderDocumentProps {
|
||||
recipientName?: string;
|
||||
recipientContact?: string;
|
||||
shutterCount?: number;
|
||||
fee?: number;
|
||||
items?: OrderItem[];
|
||||
products?: ProductInfo[];
|
||||
remarks?: string;
|
||||
|
||||
@@ -165,7 +165,7 @@ export function TransactionDocument({
|
||||
<td className="p-2 text-center border-r border-gray-300">{formatQuantity(item.quantity, item.unit)}</td>
|
||||
<td className="p-2 text-center border-r border-gray-300">{item.unit}</td>
|
||||
<td className="p-2 text-right border-r border-gray-300">{formatAmount(item.unitPrice)}</td>
|
||||
<td className="p-2 text-right">{formatAmount(item.amount)}</td>
|
||||
<td className="p-2 text-right">{formatAmount(item.amount ?? 0)}</td>
|
||||
</tr>
|
||||
))
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user