feat:부가세 관리 구분 6개로 확장 (전자/종이세금계산서 분리)
- 매출(세금계산서) → 매출(전자세금계산서) + 매출(종이세금계산서) 분리 - 매입(세금계산서) → 매입(전자세금계산서) + 매입(종이세금계산서) 분리 - 매입(카드) → 매입(신용카드) 명칭 변경 - 요약 테이블 6행으로 확장, 필터 드롭다운 업데이트 - 컨트롤러 stats에 hometaxSales/manualSales/manualPurchase 분리 반환 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -195,12 +195,12 @@ public function index(Request $request): JsonResponse
|
||||
->concat($manualRecords)
|
||||
->values();
|
||||
|
||||
// 홈택스 매출 (과세 + 영세만, 면세 제외)
|
||||
// 홈택스 매출 전자세금계산서 (과세 + 영세만, 면세 제외)
|
||||
$hometaxSalesTaxable = $hometaxSalesRecords->whereIn('taxType', ['taxable', 'zero_rated']);
|
||||
$hometaxSalesSupply = $hometaxSalesTaxable->sum('supplyAmount');
|
||||
$hometaxSalesVat = $hometaxSalesTaxable->sum('vatAmount');
|
||||
|
||||
// 홈택스 매입 세금계산서 (과세 + 영세만, 면세 제외)
|
||||
// 홈택스 매입 전자세금계산서 (과세 + 영세만, 면세 제외)
|
||||
$hometaxPurchaseTaxable = $hometaxPurchaseRecords->whereIn('taxType', ['taxable', 'zero_rated']);
|
||||
$hometaxPurchaseSupply = $hometaxPurchaseTaxable->sum('supplyAmount');
|
||||
$hometaxPurchaseVat = $hometaxPurchaseTaxable->sum('vatAmount');
|
||||
@@ -208,23 +208,42 @@ public function index(Request $request): JsonResponse
|
||||
// 홈택스 면세 계산서 (매입 + 매출 모두)
|
||||
$exemptSalesSupply = $hometaxSalesRecords->where('taxType', 'exempt')->sum('supplyAmount');
|
||||
$exemptPurchaseSupply = $hometaxPurchaseRecords->where('taxType', 'exempt')->sum('supplyAmount');
|
||||
$exemptSupply = $exemptSalesSupply + $exemptPurchaseSupply;
|
||||
|
||||
// 카드 매입
|
||||
$cardPurchaseSupply = $cardRecords->sum('supplyAmount');
|
||||
$cardPurchaseVat = $cardRecords->sum('vatAmount');
|
||||
$manualSalesSupply = $manualRecords->where('type', 'sales')->sum('supplyAmount');
|
||||
$manualSalesVat = $manualRecords->where('type', 'sales')->sum('vatAmount');
|
||||
$manualPurchaseSupply = $manualRecords->where('type', 'purchase')->sum('supplyAmount');
|
||||
$manualPurchaseVat = $manualRecords->where('type', 'purchase')->sum('vatAmount');
|
||||
|
||||
// 수동입력 매출 종이세금계산서 (과세+영세)
|
||||
$manualSalesTaxable = $manualRecords->where('type', 'sales')->whereIn('taxType', ['taxable', 'zero_rated']);
|
||||
$manualSalesSupply = $manualSalesTaxable->sum('supplyAmount');
|
||||
$manualSalesVat = $manualSalesTaxable->sum('vatAmount');
|
||||
|
||||
// 수동입력 매입 종이세금계산서 (과세+영세)
|
||||
$manualPurchaseTaxable = $manualRecords->where('type', 'purchase')->whereIn('taxType', ['taxable', 'zero_rated']);
|
||||
$manualPurchaseSupply = $manualPurchaseTaxable->sum('supplyAmount');
|
||||
$manualPurchaseVat = $manualPurchaseTaxable->sum('vatAmount');
|
||||
|
||||
// 수동입력 면세 계산서
|
||||
$manualExemptSalesSupply = $manualRecords->where('type', 'sales')->where('taxType', 'exempt')->sum('supplyAmount');
|
||||
$manualExemptPurchaseSupply = $manualRecords->where('type', 'purchase')->where('taxType', 'exempt')->sum('supplyAmount');
|
||||
|
||||
// 면세 계산서 합계 (홈택스 + 수동)
|
||||
$exemptSupply = $exemptSalesSupply + $exemptPurchaseSupply + $manualExemptSalesSupply + $manualExemptPurchaseSupply;
|
||||
|
||||
$stats = [
|
||||
'salesSupply' => $hometaxSalesSupply + $manualSalesSupply,
|
||||
'salesVat' => $hometaxSalesVat + $manualSalesVat,
|
||||
'purchaseSupply' => $hometaxPurchaseSupply + $cardPurchaseSupply + $manualPurchaseSupply,
|
||||
'purchaseVat' => $hometaxPurchaseVat + $cardPurchaseVat + $manualPurchaseVat,
|
||||
'hometaxSalesSupply' => $hometaxSalesSupply,
|
||||
'hometaxSalesVat' => $hometaxSalesVat,
|
||||
'manualSalesSupply' => $manualSalesSupply,
|
||||
'manualSalesVat' => $manualSalesVat,
|
||||
'hometaxPurchaseSupply' => $hometaxPurchaseSupply,
|
||||
'hometaxPurchaseVat' => $hometaxPurchaseVat,
|
||||
'exemptSupply' => $exemptSupply, // 면세 계산서 공급가액
|
||||
'manualPurchaseSupply' => $manualPurchaseSupply,
|
||||
'manualPurchaseVat' => $manualPurchaseVat,
|
||||
'exemptSupply' => $exemptSupply,
|
||||
'cardPurchaseSupply' => $cardPurchaseSupply,
|
||||
'cardPurchaseVat' => $cardPurchaseVat,
|
||||
'total' => $allRecords->count(),
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
function VatManagement() {
|
||||
const [vatRecords, setVatRecords] = useState([]);
|
||||
const [stats, setStats] = useState({ salesSupply: 0, salesVat: 0, purchaseSupply: 0, purchaseVat: 0, hometaxPurchaseSupply: 0, hometaxPurchaseVat: 0, exemptSupply: 0, cardPurchaseSupply: 0, cardPurchaseVat: 0, total: 0 });
|
||||
const [stats, setStats] = useState({ salesSupply: 0, salesVat: 0, purchaseSupply: 0, purchaseVat: 0, hometaxSalesSupply: 0, hometaxSalesVat: 0, manualSalesSupply: 0, manualSalesVat: 0, hometaxPurchaseSupply: 0, hometaxPurchaseVat: 0, manualPurchaseSupply: 0, manualPurchaseVat: 0, exemptSupply: 0, cardPurchaseSupply: 0, cardPurchaseVat: 0, total: 0 });
|
||||
const [periods, setPeriods] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [saving, setSaving] = useState(false);
|
||||
@@ -157,8 +157,10 @@ function VatManagement() {
|
||||
if (!matchesSearch || !matchesTaxType) return false;
|
||||
|
||||
if (filterType === 'all') return true;
|
||||
if (filterType === 'hometax_sales') return item.type === 'sales' && item.taxType !== 'exempt';
|
||||
if (filterType === 'hometax_purchase') return item.source === 'hometax' && item.type === 'purchase' && item.taxType !== 'exempt';
|
||||
if (filterType === 'electronic_sales') return item.source === 'hometax' && item.type === 'sales' && item.taxType !== 'exempt';
|
||||
if (filterType === 'paper_sales') return item.source === 'manual' && item.type === 'sales' && item.taxType !== 'exempt';
|
||||
if (filterType === 'electronic_purchase') return item.source === 'hometax' && item.type === 'purchase' && item.taxType !== 'exempt';
|
||||
if (filterType === 'paper_purchase') return item.source === 'manual' && item.type === 'purchase' && item.taxType !== 'exempt';
|
||||
if (filterType === 'exempt_purchase') return item.taxType === 'exempt';
|
||||
if (filterType === 'purchase_card') return item.source === 'card';
|
||||
return true;
|
||||
@@ -168,8 +170,14 @@ function VatManagement() {
|
||||
const purchaseVat = stats.purchaseVat || 0;
|
||||
const salesSupply = stats.salesSupply || 0;
|
||||
const purchaseSupply = stats.purchaseSupply || 0;
|
||||
const hometaxSalesSupply = stats.hometaxSalesSupply || 0;
|
||||
const hometaxSalesVat = stats.hometaxSalesVat || 0;
|
||||
const manualSalesSupply = stats.manualSalesSupply || 0;
|
||||
const manualSalesVat = stats.manualSalesVat || 0;
|
||||
const hometaxPurchaseSupply = stats.hometaxPurchaseSupply || 0;
|
||||
const hometaxPurchaseVat = stats.hometaxPurchaseVat || 0;
|
||||
const manualPurchaseSupply = stats.manualPurchaseSupply || 0;
|
||||
const manualPurchaseVat = stats.manualPurchaseVat || 0;
|
||||
const exemptSupply = stats.exemptSupply || 0;
|
||||
const cardPurchaseSupply = stats.cardPurchaseSupply || 0;
|
||||
const cardPurchaseVat = stats.cardPurchaseVat || 0;
|
||||
@@ -246,11 +254,11 @@ function VatManagement() {
|
||||
};
|
||||
|
||||
const getTypeLabel = (type, isCard = false, source = 'manual') => {
|
||||
if (source === 'hometax' && type === 'sales') return '매출';
|
||||
if (source === 'hometax' && type === 'purchase') return '매입';
|
||||
if (source === 'card' || isCard) return '매입(카드)';
|
||||
if (source === 'hometax' && type === 'sales') return '매출(전자)';
|
||||
if (source === 'hometax' && type === 'purchase') return '매입(전자)';
|
||||
if (source === 'card' || isCard) return '매입(신용카드)';
|
||||
if (source === 'manual') {
|
||||
return type === 'sales' ? '매출(수동)' : '매입(수동)';
|
||||
return type === 'sales' ? '매출(종이)' : '매입(종이)';
|
||||
}
|
||||
const labels = { 'sales': '매출', 'purchase': '매입' };
|
||||
return labels[type] || type;
|
||||
@@ -288,6 +296,8 @@ function VatManagement() {
|
||||
if (source === 'card' || isCard) return 'bg-purple-100 text-purple-700';
|
||||
if (source === 'hometax' && type === 'sales') return 'bg-emerald-100 text-emerald-700';
|
||||
if (source === 'hometax' && type === 'purchase') return 'bg-pink-100 text-pink-700';
|
||||
if (source === 'manual' && type === 'sales') return 'bg-emerald-50 text-emerald-600 border border-emerald-200';
|
||||
if (source === 'manual' && type === 'purchase') return 'bg-pink-50 text-pink-600 border border-pink-200';
|
||||
const styles = {
|
||||
'sales': 'bg-emerald-50 text-emerald-600',
|
||||
'purchase': 'bg-pink-50 text-pink-600'
|
||||
@@ -364,22 +374,32 @@ function VatManagement() {
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b border-gray-100">
|
||||
<td className="px-6 py-3 text-sm">매출(세금계산서)</td>
|
||||
<td className="px-6 py-3 text-sm text-right">{formatCurrency(salesSupply)}원</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-emerald-600 font-medium">{formatCurrency(salesVat)}원</td>
|
||||
<td className="px-6 py-3 text-sm">매출(전자세금계산서)</td>
|
||||
<td className="px-6 py-3 text-sm text-right">{formatCurrency(hometaxSalesSupply)}원</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-emerald-600 font-medium">{formatCurrency(hometaxSalesVat)}원</td>
|
||||
</tr>
|
||||
<tr className="border-b border-gray-100 bg-emerald-50/30">
|
||||
<td className="px-6 py-3 text-sm">매출(종이세금계산서)</td>
|
||||
<td className="px-6 py-3 text-sm text-right">{formatCurrency(manualSalesSupply)}원</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-emerald-600 font-medium">{formatCurrency(manualSalesVat)}원</td>
|
||||
</tr>
|
||||
<tr className="border-b border-gray-100">
|
||||
<td className="px-6 py-3 text-sm">매입(세금계산서)</td>
|
||||
<td className="px-6 py-3 text-sm">매입(전자세금계산서)</td>
|
||||
<td className="px-6 py-3 text-sm text-right">{formatCurrency(hometaxPurchaseSupply)}원</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-pink-600 font-medium">({formatCurrency(hometaxPurchaseVat)}원)</td>
|
||||
</tr>
|
||||
<tr className="border-b border-gray-100 bg-pink-50/30">
|
||||
<td className="px-6 py-3 text-sm">매입(종이세금계산서)</td>
|
||||
<td className="px-6 py-3 text-sm text-right">{formatCurrency(manualPurchaseSupply)}원</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-pink-600 font-medium">({formatCurrency(manualPurchaseVat)}원)</td>
|
||||
</tr>
|
||||
<tr className="border-b border-gray-100 bg-gray-50/50">
|
||||
<td className="px-6 py-3 text-sm text-gray-600">매입(계산서)</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-gray-600">{formatCurrency(exemptSupply)}원</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-gray-400">-</td>
|
||||
</tr>
|
||||
<tr className="border-b border-gray-100 bg-purple-50/50">
|
||||
<td className="px-6 py-3 text-sm text-purple-700">매입(카드)</td>
|
||||
<td className="px-6 py-3 text-sm text-purple-700">매입(신용카드)</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-purple-600">{formatCurrency(cardPurchaseSupply)}원</td>
|
||||
<td className="px-6 py-3 text-sm text-right text-purple-600 font-medium">({formatCurrency(cardPurchaseVat)}원)</td>
|
||||
</tr>
|
||||
@@ -400,10 +420,12 @@ function VatManagement() {
|
||||
</div>
|
||||
<select value={filterType} onChange={(e) => setFilterType(e.target.value)} className="px-3 py-2 border border-gray-300 rounded-lg">
|
||||
<option value="all">전체 유형</option>
|
||||
<option value="hometax_sales">매출(세금계산서)</option>
|
||||
<option value="hometax_purchase">매입(세금계산서)</option>
|
||||
<option value="electronic_sales">매출(전자세금계산서)</option>
|
||||
<option value="paper_sales">매출(종이세금계산서)</option>
|
||||
<option value="electronic_purchase">매입(전자세금계산서)</option>
|
||||
<option value="paper_purchase">매입(종이세금계산서)</option>
|
||||
<option value="exempt_purchase">매입(계산서)</option>
|
||||
<option value="purchase_card">매입(카드)</option>
|
||||
<option value="purchase_card">매입(신용카드)</option>
|
||||
</select>
|
||||
<select value={filterTaxType} onChange={(e) => setFilterTaxType(e.target.value)} className="px-3 py-2 border border-gray-300 rounded-lg">
|
||||
<option value="all">전체 세금구분</option>
|
||||
|
||||
Reference in New Issue
Block a user