Files
sam-react-prod/src/components/accounting/GeneralJournalEntry/actions.ts

164 lines
4.6 KiB
TypeScript
Raw Normal View History

'use server';
import { executeServerAction, type ActionResult } from '@/lib/api/execute-server-action';
import { executePaginatedAction } from '@/lib/api/execute-paginated-action';
import { buildApiUrl } from '@/lib/api/query-params';
import type {
GeneralJournalRecord,
GeneralJournalApiData,
GeneralJournalSummary,
GeneralJournalSummaryApiData,
JournalEntryRow,
VendorOption,
} from './types';
import {
transformApiToFrontend,
transformSummaryApi,
} from './types';
// ===== 전표 목록 조회 =====
export async function getJournalEntries(params: {
startDate?: string;
endDate?: string;
search?: string;
page?: number;
perPage?: number;
}) {
const result = await executePaginatedAction<GeneralJournalApiData, GeneralJournalRecord>({
url: buildApiUrl('/api/v1/general-journal-entries', {
start_date: params.startDate,
end_date: params.endDate,
search: params.search || undefined,
page: params.page,
per_page: params.perPage,
}),
transform: transformApiToFrontend,
errorMessage: '전표 목록 조회에 실패했습니다.',
});
return result;
}
// ===== 전표 요약 통계 조회 =====
export async function getJournalSummary(params: {
startDate?: string;
endDate?: string;
search?: string;
}): Promise<ActionResult<GeneralJournalSummary>> {
const result = await executeServerAction({
url: buildApiUrl('/api/v1/general-journal-entries/summary', {
start_date: params.startDate,
end_date: params.endDate,
search: params.search || undefined,
}),
transform: (data: GeneralJournalSummaryApiData) => transformSummaryApi(data),
errorMessage: '전표 요약 조회에 실패했습니다.',
});
return result;
}
// ===== 수기 전표 등록 =====
export async function createManualJournal(data: {
journalDate: string;
description: string;
rows: JournalEntryRow[];
}): Promise<ActionResult> {
return executeServerAction({
url: buildApiUrl('/api/v1/general-journal-entries'),
method: 'POST',
body: {
journal_date: data.journalDate,
description: data.description,
rows: data.rows.map((r) => ({
side: r.side,
account_subject_id: r.accountSubjectId,
vendor_id: r.vendorId || null,
debit_amount: r.debitAmount,
credit_amount: r.creditAmount,
memo: r.memo || null,
})),
},
errorMessage: '수기 전표 등록에 실패했습니다.',
});
}
// ===== 분개 상세 조회 =====
type JournalDetailData = {
id: number;
date: string;
division: string;
amount: number;
description: string;
bank_name: string;
account_number: string;
journal_memo: string;
rows: {
id: number;
side: string;
account_subject_id: number;
account_subject_name: string;
vendor_id: number | null;
vendor_name: string;
debit_amount: number;
credit_amount: number;
memo: string;
}[];
};
export async function getJournalDetail(id: string): Promise<ActionResult<JournalDetailData>> {
const result = await executeServerAction<JournalDetailData>({
url: buildApiUrl(`/api/v1/general-journal-entries/${id}`),
errorMessage: '분개 상세 조회에 실패했습니다.',
});
return result;
}
// ===== 분개 수정 =====
export async function updateJournalDetail(
id: string,
data: {
journalMemo: string;
rows: JournalEntryRow[];
}
): Promise<ActionResult> {
return executeServerAction({
url: buildApiUrl(`/api/v1/general-journal-entries/${id}/journal`),
method: 'PUT',
body: {
journal_memo: data.journalMemo,
rows: data.rows.map((r) => ({
side: r.side,
account_subject_id: r.accountSubjectId,
vendor_id: r.vendorId || null,
debit_amount: r.debitAmount,
credit_amount: r.creditAmount,
memo: r.memo || null,
})),
},
errorMessage: '분개 수정에 실패했습니다.',
});
}
// ===== 분개 삭제 =====
export async function deleteJournalDetail(id: string): Promise<ActionResult> {
return executeServerAction({
url: buildApiUrl(`/api/v1/general-journal-entries/${id}/journal`),
method: 'DELETE',
errorMessage: '분개 삭제에 실패했습니다.',
});
}
// ===== 거래처 목록 조회 =====
export async function getVendorList(): Promise<ActionResult<VendorOption[]>> {
const result = await executeServerAction({
url: buildApiUrl('/api/v1/vendors', { per_page: 9999 }),
transform: (data: { id: number; name: string }[]) =>
data.map((v) => ({ id: String(v.id), name: v.name })),
errorMessage: '거래처 목록 조회에 실패했습니다.',
});
return result;
}