feat: Add multiple TVA entries support for Romanian receipts
- Add TvaEntry schema supporting multiple TVA rates (A, B, C, D codes) - Update OCR extractor to extract multiple TVA entries from receipts - Support both old (19%, 9%, 5%) and new Romanian rates (21%, 11% from Aug 2025) - Add tva_breakdown, tva_total, items_count, vendor_address to Receipt model - Update OCRPreview.vue to display TVA entries with rate badges - Add "Detalii Suplimentare" section in ReceiptCreateView with editable TVA table - Add TVA breakdown display in ReceiptDetailView - Create database migration for new TVA columns 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -112,6 +112,43 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detalii Suplimentare (TVA, items, address from OCR) -->
|
||||
<template v-if="hasTvaData || receipt.items_count || receipt.vendor_address">
|
||||
<Divider />
|
||||
|
||||
<h4 style="margin-bottom: 0.75rem; color: #0284c7;">
|
||||
<i class="pi pi-list"></i>
|
||||
Detalii Suplimentare
|
||||
</h4>
|
||||
|
||||
<div class="detail-list">
|
||||
<!-- TVA Breakdown -->
|
||||
<div v-if="parsedTvaBreakdown?.length > 0" class="detail-item tva-detail">
|
||||
<span class="label">TVA</span>
|
||||
<div class="tva-breakdown-display">
|
||||
<div v-for="(entry, idx) in parsedTvaBreakdown" :key="idx" class="tva-line">
|
||||
<span class="tva-code" v-if="entry.code">{{ entry.code }}:</span>
|
||||
<span class="tva-percent">{{ entry.percent }}%</span>
|
||||
<span class="tva-amount">= {{ formatAmount(entry.amount) }}</span>
|
||||
</div>
|
||||
<div v-if="receipt.tva_total && parsedTvaBreakdown.length > 1" class="tva-total-line">
|
||||
<strong>Total TVA: {{ formatAmount(receipt.tva_total) }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-item" v-if="receipt.items_count">
|
||||
<span class="label">Nr. Articole</span>
|
||||
<span class="value">{{ receipt.items_count }} articole</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-item" v-if="receipt.vendor_address">
|
||||
<span class="label">Adresa Furnizor</span>
|
||||
<span class="value">{{ receipt.vendor_address }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<Divider />
|
||||
|
||||
<div class="detail-list">
|
||||
@@ -283,6 +320,22 @@ const isBalanced = computed(() => {
|
||||
return Math.abs(totalDebit.value - totalCredit.value) < 0.01
|
||||
})
|
||||
|
||||
const parsedTvaBreakdown = computed(() => {
|
||||
if (!receipt.value?.tva_breakdown) return []
|
||||
try {
|
||||
// Handle both string (JSON) and array formats
|
||||
return typeof receipt.value.tva_breakdown === 'string'
|
||||
? JSON.parse(receipt.value.tva_breakdown)
|
||||
: receipt.value.tva_breakdown
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
const hasTvaData = computed(() => {
|
||||
return parsedTvaBreakdown.value?.length > 0 || receipt.value?.tva_total
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await loadReceipt()
|
||||
})
|
||||
@@ -521,4 +574,56 @@ const resubmitReceipt = async () => {
|
||||
border-radius: 8px;
|
||||
color: #f57c00;
|
||||
}
|
||||
|
||||
/* TVA Breakdown Display */
|
||||
.detail-item.tva-detail {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.tva-breakdown-display {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
padding: 0.5rem;
|
||||
background: #f0f9ff;
|
||||
border-radius: 6px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tva-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.tva-code {
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
min-width: 1.5rem;
|
||||
}
|
||||
|
||||
.tva-percent {
|
||||
display: inline-block;
|
||||
padding: 0.1rem 0.4rem;
|
||||
background: #dbeafe;
|
||||
border-radius: 4px;
|
||||
font-size: 0.85rem;
|
||||
color: #1e40af;
|
||||
min-width: 2.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tva-amount {
|
||||
font-weight: 500;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.tva-total-line {
|
||||
margin-top: 0.25rem;
|
||||
padding-top: 0.25rem;
|
||||
border-top: 1px dashed #0284c7;
|
||||
color: #0284c7;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user