fix(WEB): 기타 버그 수정 및 개선
- CardTransactionInquiry: account_code 'unset' 처리 개선 - WorkOrderCreate: DevFill 공정 옵션 로딩 타이밍 수정 - accountingData: 생성기 개선 - api/errors: 에러 처리 개선
This commit is contained in:
@@ -296,7 +296,7 @@ export async function createCardTransaction(data: {
|
||||
merchant_name: data.merchantName,
|
||||
amount: data.amount,
|
||||
description: data.memo,
|
||||
account_code: data.usageType,
|
||||
account_code: data.usageType === 'unset' ? null : data.usageType,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -349,7 +349,7 @@ export async function updateCardTransaction(
|
||||
merchant_name: data.merchantName,
|
||||
amount: data.amount,
|
||||
description: data.memo,
|
||||
account_code: data.usageType,
|
||||
account_code: data.usageType === 'unset' ? null : data.usageType,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -164,6 +164,19 @@ export interface Vendor {
|
||||
}
|
||||
|
||||
// ===== API 응답 타입 =====
|
||||
export interface SaleApiOrderItem {
|
||||
id: number;
|
||||
order_id: number;
|
||||
item_name: string;
|
||||
quantity: string | number;
|
||||
unit_price: string | number;
|
||||
supply_amount: string | number;
|
||||
tax_amount: string | number;
|
||||
total_amount: string | number;
|
||||
note: string | null;
|
||||
sort_order: number;
|
||||
}
|
||||
|
||||
export interface SaleApiData {
|
||||
id: number;
|
||||
sale_number: string;
|
||||
@@ -173,6 +186,10 @@ export interface SaleApiData {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
order?: {
|
||||
id: number;
|
||||
items?: SaleApiOrderItem[];
|
||||
};
|
||||
supply_amount: string | number;
|
||||
tax_amount: string | number;
|
||||
total_amount: string | number;
|
||||
@@ -197,6 +214,17 @@ export const API_STATUS_MAP: Record<string, SalesStatus> = {
|
||||
|
||||
// API 응답 → 프론트엔드 타입 변환
|
||||
export function transformApiToFrontend(apiData: SaleApiData): SalesRecord {
|
||||
// 수주(Order)의 품목(items)을 매출 품목으로 변환
|
||||
const items: SalesItem[] = (apiData.order?.items ?? []).map((item, index) => ({
|
||||
id: String(item.id),
|
||||
itemName: item.item_name ?? '',
|
||||
quantity: parseFloat(String(item.quantity)) || 0,
|
||||
unitPrice: parseFloat(String(item.unit_price)) || 0,
|
||||
supplyAmount: parseFloat(String(item.supply_amount)) || 0,
|
||||
vat: parseFloat(String(item.tax_amount)) || 0,
|
||||
note: item.note ?? '',
|
||||
}));
|
||||
|
||||
return {
|
||||
id: String(apiData.id),
|
||||
salesNo: apiData.sale_number,
|
||||
@@ -205,7 +233,7 @@ export function transformApiToFrontend(apiData: SaleApiData): SalesRecord {
|
||||
vendorName: apiData.client?.name ?? '',
|
||||
salesType: 'other', // API에 없음, 기본값
|
||||
accountSubject: 'other', // API에 없음, 기본값
|
||||
items: [], // API에 없음, 빈 배열
|
||||
items, // 수주 품목에서 가져옴
|
||||
totalSupplyAmount: parseFloat(String(apiData.supply_amount)) || 0,
|
||||
totalVat: parseFloat(String(apiData.tax_amount)) || 0,
|
||||
totalAmount: parseFloat(String(apiData.total_amount)) || 0,
|
||||
|
||||
@@ -60,7 +60,7 @@ const DEPOSIT_NOTES = [
|
||||
|
||||
export interface DepositFormData {
|
||||
depositDate: string;
|
||||
accountName: string;
|
||||
bankAccountId: string;
|
||||
depositorName: string;
|
||||
depositAmount: number;
|
||||
note: string;
|
||||
@@ -70,15 +70,17 @@ export interface DepositFormData {
|
||||
|
||||
export interface GenerateDepositDataOptions {
|
||||
vendors?: Array<{ id: string; name: string }>;
|
||||
bankAccounts?: Array<{ id: string; name: string }>;
|
||||
}
|
||||
|
||||
export function generateDepositData(options: GenerateDepositDataOptions = {}): DepositFormData {
|
||||
const { vendors = SAMPLE_VENDORS } = options;
|
||||
const { vendors = SAMPLE_VENDORS, bankAccounts = [] } = options;
|
||||
const vendor = randomPick(vendors);
|
||||
const bankAccount = bankAccounts.length > 0 ? randomPick(bankAccounts) : null;
|
||||
|
||||
return {
|
||||
depositDate: today(),
|
||||
accountName: randomPick(ACCOUNT_NAMES),
|
||||
bankAccountId: bankAccount?.id || '',
|
||||
depositorName: randomPick(DEPOSITOR_NAMES),
|
||||
depositAmount: randomInt(100000, 10000000),
|
||||
note: randomPick(DEPOSIT_NOTES),
|
||||
@@ -119,7 +121,7 @@ const WITHDRAWAL_NOTES = [
|
||||
|
||||
export interface WithdrawalFormData {
|
||||
withdrawalDate: string;
|
||||
accountName: string;
|
||||
bankAccountId: string;
|
||||
recipientName: string;
|
||||
withdrawalAmount: number;
|
||||
note: string;
|
||||
@@ -129,15 +131,17 @@ export interface WithdrawalFormData {
|
||||
|
||||
export interface GenerateWithdrawalDataOptions {
|
||||
vendors?: Array<{ id: string; name: string }>;
|
||||
bankAccounts?: Array<{ id: string; name: string }>;
|
||||
}
|
||||
|
||||
export function generateWithdrawalData(options: GenerateWithdrawalDataOptions = {}): WithdrawalFormData {
|
||||
const { vendors = SAMPLE_VENDORS } = options;
|
||||
const { vendors = SAMPLE_VENDORS, bankAccounts = [] } = options;
|
||||
const vendor = randomPick(vendors);
|
||||
const bankAccount = bankAccounts.length > 0 ? randomPick(bankAccounts) : null;
|
||||
|
||||
return {
|
||||
withdrawalDate: today(),
|
||||
accountName: randomPick(ACCOUNT_NAMES),
|
||||
bankAccountId: bankAccount?.id || '',
|
||||
recipientName: randomPick(RECIPIENT_NAMES),
|
||||
withdrawalAmount: randomInt(50000, 5000000),
|
||||
note: randomPick(WITHDRAWAL_NOTES),
|
||||
@@ -264,6 +268,7 @@ export function generatePurchaseApprovalData(options: GeneratePurchaseApprovalDa
|
||||
approvalLine: [currentUser],
|
||||
references: [randomReference],
|
||||
proposalData: {
|
||||
vendorId: vendor.id,
|
||||
vendor: vendor.name,
|
||||
vendorPaymentDate: today(),
|
||||
title: randomPick(PROPOSAL_TITLES),
|
||||
|
||||
@@ -119,8 +119,12 @@ export function WorkOrderCreate() {
|
||||
// DevToolbar 자동 채우기
|
||||
useDevFill(
|
||||
'workOrder',
|
||||
useCallback(() => {
|
||||
const sampleData = generateWorkOrderData({ processOptions });
|
||||
useCallback(async () => {
|
||||
// 공정 옵션 직접 가져오기 (state가 아직 로딩 전일 수 있음)
|
||||
const processResult = await getProcessOptions();
|
||||
const processes = processResult.success ? processResult.data : [];
|
||||
|
||||
const sampleData = generateWorkOrderData({ processOptions: processes });
|
||||
|
||||
// 수동 등록 모드로 변경
|
||||
setMode('manual');
|
||||
@@ -139,7 +143,7 @@ export function WorkOrderCreate() {
|
||||
}));
|
||||
|
||||
toast.success('[Dev] 작업지시 폼이 자동으로 채워졌습니다.');
|
||||
}, [processOptions])
|
||||
}, [])
|
||||
);
|
||||
|
||||
// 수주 선택 핸들러
|
||||
|
||||
@@ -48,13 +48,14 @@ export function createAuthErrorResponse(message?: string): ApiErrorResponse {
|
||||
|
||||
/**
|
||||
* 일반 API 에러 응답 생성 헬퍼
|
||||
* - 디버깅을 위해 상태 코드를 메시지에 포함
|
||||
*/
|
||||
export function createErrorResponse(status: number, message: string, code?: string): ApiErrorResponse {
|
||||
return {
|
||||
__error: true,
|
||||
__authError: status === 401,
|
||||
status,
|
||||
message,
|
||||
message: `[${status}] ${message}`,
|
||||
code,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user