- 계정과목 관리를 accounting/common/으로 통합 (AccountSubjectSettingModal 이동) - GeneralJournalEntry: 계정과목 actions/types 분리, 모달 import 경로 변경 - CardTransactionInquiry: JournalEntryModal/ManualInputModal 개선 - TaxInvoiceManagement: actions/types 리팩토링 - DepositManagement/WithdrawalManagement: 소폭 개선 - ExpectedExpenseManagement: UI 개선 - GiftCertificateManagement: 상세/목록 개선 - BillManagement: BillDetail/Client/index 소폭 추가 - PurchaseManagement/SalesManagement: 상세뷰 개선 - CEO 대시보드: dashboard-invalidation 유틸 추가, useCEODashboard 확장 - OrderRegistration/OrderSalesDetailView 소폭 수정 - claudedocs: 계정과목 통합 계획/분석/체크리스트, 대시보드 검증 문서 추가
160 lines
4.8 KiB
TypeScript
160 lines
4.8 KiB
TypeScript
'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 {
|
|
TaxInvoiceMgmtRecord,
|
|
TaxInvoiceMgmtApiData,
|
|
TaxInvoiceSummary,
|
|
TaxInvoiceSummaryApiData,
|
|
CardHistoryApiData,
|
|
CardHistoryRecord,
|
|
ManualEntryFormData,
|
|
JournalEntryRow,
|
|
} from './types';
|
|
import {
|
|
transformApiToFrontend,
|
|
transformFrontendToApi,
|
|
transformCardHistoryApi,
|
|
transformSummaryApi,
|
|
} from './types';
|
|
|
|
// ===== 세금계산서 목록 조회 =====
|
|
export async function getTaxInvoices(params: {
|
|
division?: string;
|
|
dateType?: string;
|
|
startDate?: string;
|
|
endDate?: string;
|
|
vendorSearch?: string;
|
|
page?: number;
|
|
perPage?: number;
|
|
}) {
|
|
// frontend 'purchase' → backend 'purchases'
|
|
const direction = params.division === 'purchase' ? 'purchases' : params.division;
|
|
|
|
return executePaginatedAction<TaxInvoiceMgmtApiData, TaxInvoiceMgmtRecord>({
|
|
url: buildApiUrl('/api/v1/tax-invoices', {
|
|
direction,
|
|
issue_date_from: params.startDate,
|
|
issue_date_to: params.endDate,
|
|
corp_name: params.vendorSearch || undefined,
|
|
page: params.page,
|
|
per_page: params.perPage,
|
|
}),
|
|
transform: transformApiToFrontend,
|
|
errorMessage: '세금계산서 목록 조회에 실패했습니다.',
|
|
});
|
|
}
|
|
|
|
// ===== 세금계산서 요약 조회 =====
|
|
export async function getTaxInvoiceSummary(params: {
|
|
dateType?: string;
|
|
startDate?: string;
|
|
endDate?: string;
|
|
vendorSearch?: string;
|
|
}): Promise<ActionResult<TaxInvoiceSummary>> {
|
|
return executeServerAction<TaxInvoiceSummaryApiData, TaxInvoiceSummary>({
|
|
url: buildApiUrl('/api/v1/tax-invoices/summary', {
|
|
issue_date_from: params.startDate,
|
|
issue_date_to: params.endDate,
|
|
corp_name: params.vendorSearch || undefined,
|
|
}),
|
|
transform: transformSummaryApi,
|
|
errorMessage: '세금계산서 요약 조회에 실패했습니다.',
|
|
});
|
|
}
|
|
|
|
// ===== 세금계산서 수기 등록 =====
|
|
export async function createTaxInvoice(
|
|
data: ManualEntryFormData
|
|
): Promise<ActionResult<TaxInvoiceMgmtRecord>> {
|
|
return executeServerAction({
|
|
url: buildApiUrl('/api/v1/tax-invoices'),
|
|
method: 'POST',
|
|
body: transformFrontendToApi(data),
|
|
transform: (d: TaxInvoiceMgmtApiData) => transformApiToFrontend(d),
|
|
errorMessage: '세금계산서 등록에 실패했습니다.',
|
|
});
|
|
}
|
|
|
|
// ===== 카드 내역 조회 =====
|
|
export async function getCardHistory(params: {
|
|
startDate?: string;
|
|
endDate?: string;
|
|
search?: string;
|
|
page?: number;
|
|
perPage?: number;
|
|
}) {
|
|
return executePaginatedAction<CardHistoryApiData, CardHistoryRecord>({
|
|
url: buildApiUrl('/api/v1/card-transactions', {
|
|
start_date: params.startDate,
|
|
end_date: params.endDate,
|
|
search: params.search || undefined,
|
|
page: params.page,
|
|
per_page: params.perPage,
|
|
}),
|
|
transform: transformCardHistoryApi,
|
|
errorMessage: '카드 내역 조회에 실패했습니다.',
|
|
});
|
|
}
|
|
|
|
// ===== 분개 내역 조회 =====
|
|
export async function getJournalEntries(invoiceId: string): Promise<ActionResult<{
|
|
rows: { id: string; side: string; account_subject: string; debit_amount: number; credit_amount: number }[];
|
|
}>> {
|
|
return executeServerAction({
|
|
url: buildApiUrl(`/api/v1/tax-invoices/${invoiceId}/journal-entries`),
|
|
errorMessage: '분개 내역 조회에 실패했습니다.',
|
|
});
|
|
}
|
|
|
|
// ===== 분개 수정 =====
|
|
export async function updateJournalEntry(
|
|
invoiceId: string,
|
|
rows: JournalEntryRow[]
|
|
): Promise<ActionResult> {
|
|
return executeServerAction({
|
|
url: buildApiUrl(`/api/v1/tax-invoices/${invoiceId}/journal-entries`),
|
|
method: 'PUT',
|
|
body: {
|
|
rows: rows.map((r) => ({
|
|
side: r.side,
|
|
account_subject: r.accountSubject,
|
|
debit_amount: r.debitAmount,
|
|
credit_amount: r.creditAmount,
|
|
})),
|
|
},
|
|
errorMessage: '분개 수정에 실패했습니다.',
|
|
});
|
|
}
|
|
|
|
// ===== 분개 삭제 =====
|
|
export async function deleteJournalEntry(invoiceId: string): Promise<ActionResult> {
|
|
return executeServerAction({
|
|
url: buildApiUrl(`/api/v1/tax-invoices/${invoiceId}/journal-entries`),
|
|
method: 'DELETE',
|
|
errorMessage: '분개 삭제에 실패했습니다.',
|
|
});
|
|
}
|
|
|
|
// ===== 엑셀 다운로드 =====
|
|
export async function downloadTaxInvoiceExcel(params: {
|
|
division?: string;
|
|
dateType?: string;
|
|
startDate?: string;
|
|
endDate?: string;
|
|
vendorSearch?: string;
|
|
}): Promise<ActionResult<{ url: string }>> {
|
|
return executeServerAction({
|
|
url: buildApiUrl('/api/v1/tax-invoices/export', {
|
|
division: params.division,
|
|
date_type: params.dateType,
|
|
start_date: params.startDate,
|
|
end_date: params.endDate,
|
|
vendor_search: params.vendorSearch || undefined,
|
|
}),
|
|
errorMessage: '엑셀 다운로드에 실패했습니다.',
|
|
});
|
|
}
|