feat: 회계 모듈 전면 개선 — 계정과목 공통화·전표·세금계산서·어음·상품권

- AccountSubjectSelect 공통 컴포넌트 신규 (계정과목 선택 통합)
- 일반전표 수동입력/수정 모달 계정과목 연동
- 세금계산서 관리 타입 시스템 재정의 + 전표 연동 모달
- 어음관리 리팩토링 + 상품권 접대비 연동
- 카드거래 조회 전표 연동 모달 개선
- 악성채권/입출금/매입매출/거래처 상세 뷰 보강
This commit is contained in:
2026-03-10 11:35:26 +09:00
parent 72cf5d86a2
commit 81373281ea
40 changed files with 863 additions and 531 deletions

View File

@@ -33,6 +33,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { AccountSubjectSelect } from '@/components/accounting/common';
import {
Table,
TableBody,
@@ -56,14 +57,12 @@ import {
getJournalDetail,
updateJournalDetail,
deleteJournalDetail,
getAccountSubjects,
getVendorList,
} from './actions';
import type {
GeneralJournalRecord,
JournalEntryRow,
JournalSide,
AccountSubject,
VendorOption,
} from './types';
import { JOURNAL_SIDE_OPTIONS, JOURNAL_DIVISION_LABELS } from './types';
@@ -109,7 +108,6 @@ export function JournalEditModal({
const [accountNumber, setAccountNumber] = useState('');
// 옵션 데이터
const [accountSubjects, setAccountSubjects] = useState<AccountSubject[]>([]);
const [vendors, setVendors] = useState<VendorOption[]>([]);
// 데이터 로드
@@ -119,15 +117,11 @@ export function JournalEditModal({
const loadData = async () => {
setIsLoading(true);
try {
const [detailRes, subjectsRes, vendorsRes] = await Promise.all([
const [detailRes, vendorsRes] = await Promise.all([
getJournalDetail(record.id),
getAccountSubjects({ category: 'all' }),
getVendorList(),
]);
if (subjectsRes.success && subjectsRes.data) {
setAccountSubjects(subjectsRes.data.filter((s) => s.isActive));
}
if (vendorsRes.success && vendorsRes.data) {
setVendors(vendorsRes.data);
}
@@ -361,24 +355,14 @@ export function JournalEditModal({
</div>
</TableCell>
<TableCell className="p-1">
<Select
value={row.accountSubjectId || 'none'}
<AccountSubjectSelect
value={row.accountSubjectId}
onValueChange={(v) =>
handleRowChange(row.id, 'accountSubjectId', v === 'none' ? '' : v)
handleRowChange(row.id, 'accountSubjectId', v)
}
>
<SelectTrigger className="h-8 text-sm">
<SelectValue placeholder="선택" />
</SelectTrigger>
<SelectContent>
<SelectItem value="none"></SelectItem>
{accountSubjects.map((s) => (
<SelectItem key={s.id} value={s.id}>
{s.name}
</SelectItem>
))}
</SelectContent>
</Select>
size="sm"
placeholder="선택"
/>
</TableCell>
<TableCell className="p-1">
<Select