feat(dashboard): add datorat/achitat/sold breakdown for budget debts
Replaces "luna prec / luna curentă" columns with a clearer accounting reconciliation flow: Datorat (owed) → Achitat (paid) → Sold (remaining). Backend models gain 3 new fields per sub-account and group. Frontend shows ✓ when a debt is fully cleared. Mobile TVA card now shows both total and remaining sold. SwipeableCards gains fixedDots/fillHeight props for better layout above MobileBottomNav. Telegram formatter updated to use new fields and drops redundant RON suffix from amounts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,9 +8,18 @@
|
||||
<div class="solduri-compact-card__header">
|
||||
<div class="solduri-compact-card__content">
|
||||
<span class="solduri-compact-card__label">{{ label }}</span>
|
||||
<span class="solduri-compact-card__value" :class="valueColorClass">
|
||||
<!-- type !== 'tva': simple value -->
|
||||
<span v-if="type !== 'tva'" class="solduri-compact-card__value" :class="valueColorClass">
|
||||
{{ formatAmount(total) }}
|
||||
</span>
|
||||
<!-- type === 'tva': datorat · sold on same line, same font -->
|
||||
<div v-else class="solduri-compact-card__debt-line">
|
||||
<span class="solduri-compact-card__value" :class="valueColorClass">{{ formatAmount(total) }}</span>
|
||||
<span class="solduri-compact-card__debt-sep">·</span>
|
||||
<span class="solduri-compact-card__value solduri-compact-card__value--sold">
|
||||
{{ soldTotal !== undefined && soldTotal > 0 ? formatAmount(soldTotal) : '0 ✓' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<i
|
||||
class="pi pi-chevron-down solduri-compact-card__chevron"
|
||||
@@ -90,10 +99,17 @@
|
||||
<!-- TVA / Datorii Buget: Breakdown pe grupe (TVA/BASS/CAM) cu sub-conturi -->
|
||||
<template v-else-if="type === 'tva'">
|
||||
<template v-if="Array.isArray(breakdown) && (breakdown as any[]).length">
|
||||
<!-- Header coloane -->
|
||||
<div class="solduri-compact-card__debt-header">
|
||||
<span></span>
|
||||
<span class="solduri-compact-card__col-head">Datorat</span>
|
||||
<span class="solduri-compact-card__col-head">Sold</span>
|
||||
</div>
|
||||
|
||||
<div v-for="group in (breakdown as any[])" :key="group.key">
|
||||
<!-- Rând grup -->
|
||||
<div
|
||||
class="solduri-compact-card__breakdown-item solduri-compact-card__breakdown-group"
|
||||
class="solduri-compact-card__breakdown-group"
|
||||
@click.stop="toggleGroup(group.key)"
|
||||
>
|
||||
<span class="solduri-compact-card__breakdown-label solduri-compact-card__group-label">
|
||||
@@ -102,10 +118,14 @@
|
||||
{{ group.label }}
|
||||
</span>
|
||||
<span class="solduri-compact-card__breakdown-value">
|
||||
{{ group.precedent !== 0 ? formatAmount(group.precedent) : '-' }}
|
||||
{{ group.datorat > 0 ? formatAmount(group.datorat) : '-' }}
|
||||
</span>
|
||||
<span class="solduri-compact-card__breakdown-value"
|
||||
:class="group.sold <= 0 && group.datorat > 0 ? 'solduri-compact-card__cleared' : ''">
|
||||
{{ group.sold > 0 ? formatAmount(group.sold) : (group.datorat > 0 ? '✓' : '-') }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- Sub-conturi -->
|
||||
<!-- Sub-conturi expandabile -->
|
||||
<div v-show="expandedGroups.has(group.key)">
|
||||
<div
|
||||
v-for="acc in group.sub_accounts"
|
||||
@@ -114,11 +134,32 @@
|
||||
>
|
||||
<span class="solduri-compact-card__breakdown-sublabel">{{ acc.label }}</span>
|
||||
<span class="solduri-compact-card__breakdown-subvalue">
|
||||
{{ acc.precedent !== 0 ? formatAmount(acc.precedent) : '-' }}
|
||||
{{ acc.datorat > 0 ? formatAmount(acc.datorat) : '-' }}
|
||||
</span>
|
||||
<span class="solduri-compact-card__breakdown-subvalue">
|
||||
{{ acc.sold > 0 ? formatAmount(acc.sold) : (acc.datorat > 0 ? '✓' : '-') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Obligații luna curentă -->
|
||||
<template v-if="(breakdown as any[]).some((g: any) => g.curent > 0)">
|
||||
<div class="solduri-compact-card__divider"></div>
|
||||
<div class="solduri-compact-card__curent-summary">
|
||||
<span class="solduri-compact-card__curent-title">Obligații curente:</span>
|
||||
<span
|
||||
v-for="g in (breakdown as any[]).filter((g: any) => g.curent > 0)"
|
||||
:key="'c-' + g.key"
|
||||
class="solduri-compact-card__curent-chip"
|
||||
>
|
||||
{{ g.label }} {{ formatAmount(g.curent) }}
|
||||
</span>
|
||||
<span class="solduri-compact-card__curent-total">
|
||||
= {{ formatAmount(curentTotal) }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="solduri-compact-card__breakdown-item">
|
||||
@@ -163,6 +204,7 @@ type BreakdownType = TrezorerieBreakdown | ClientiFurnizoriBreakdown | null
|
||||
const props = defineProps<{
|
||||
type: CardType
|
||||
total: number
|
||||
soldTotal?: number
|
||||
breakdown?: BreakdownType
|
||||
casaTotal?: number
|
||||
bancaTotal?: number
|
||||
@@ -203,6 +245,14 @@ const valueColorClass = computed(() => {
|
||||
return ''
|
||||
})
|
||||
|
||||
// Computed: Total obligații curente (doar pentru type === 'tva')
|
||||
const curentTotal = computed(() => {
|
||||
if (!Array.isArray(props.breakdown)) return 0
|
||||
return (props.breakdown as any[])
|
||||
.filter((g: any) => Number(g.curent || 0) > 0)
|
||||
.reduce((sum: number, g: any) => sum + Number(g.curent || 0), 0)
|
||||
})
|
||||
|
||||
// Computed: Check if breakdown data exists
|
||||
const hasBreakdown = computed(() => {
|
||||
if (props.type === 'trezorerie') {
|
||||
@@ -303,6 +353,24 @@ const formatPeriodLabel = (key: string): string => {
|
||||
line-height: var(--leading-tight);
|
||||
}
|
||||
|
||||
/* Debt line: datorat · sold inline, same font */
|
||||
.solduri-compact-card__debt-line {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: var(--space-xs);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.solduri-compact-card__debt-sep {
|
||||
color: var(--text-color-secondary);
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-bold);
|
||||
}
|
||||
|
||||
.solduri-compact-card__value--sold {
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
/* Value color modifiers */
|
||||
.solduri-compact-card__value--success {
|
||||
color: var(--green-600);
|
||||
@@ -385,10 +453,35 @@ const formatPeriodLabel = (key: string): string => {
|
||||
font-family: var(--font-mono, monospace);
|
||||
}
|
||||
|
||||
/* TVA: 3-column grid layout (label | datorat | sold) */
|
||||
.solduri-compact-card__debt-header,
|
||||
.solduri-compact-card__breakdown-group,
|
||||
.solduri-compact-card__breakdown-subitem {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
gap: var(--space-sm);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.solduri-compact-card__col-head {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
text-align: right;
|
||||
min-width: 54px;
|
||||
}
|
||||
|
||||
/* Override: breakdown-value/subvalue right-aligned with min-width in grid */
|
||||
.solduri-compact-card__breakdown-group .solduri-compact-card__breakdown-value,
|
||||
.solduri-compact-card__breakdown-subitem .solduri-compact-card__breakdown-subvalue {
|
||||
text-align: right;
|
||||
min-width: 54px;
|
||||
}
|
||||
|
||||
/* TVA grup toggle */
|
||||
.solduri-compact-card__breakdown-group {
|
||||
cursor: pointer;
|
||||
font-weight: var(--font-semibold);
|
||||
padding: var(--space-xs) 0;
|
||||
}
|
||||
.solduri-compact-card__breakdown-group:hover { background: var(--surface-hover); }
|
||||
|
||||
@@ -405,6 +498,49 @@ const formatPeriodLabel = (key: string): string => {
|
||||
}
|
||||
.solduri-compact-card__group-toggle--expanded { transform: rotate(90deg); }
|
||||
|
||||
/* Cleared (paid) indicator */
|
||||
.solduri-compact-card__cleared {
|
||||
color: var(--green-600);
|
||||
font-weight: var(--font-semibold);
|
||||
}
|
||||
|
||||
/* Divider between breakdown and obligații curente */
|
||||
.solduri-compact-card__divider {
|
||||
height: 1px;
|
||||
background: var(--surface-border);
|
||||
margin: var(--space-sm) 0;
|
||||
}
|
||||
|
||||
/* Obligații curente section */
|
||||
.solduri-compact-card__curent-summary {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-xs);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.solduri-compact-card__curent-title {
|
||||
font-size: var(--text-xs);
|
||||
color: var(--text-color-secondary);
|
||||
}
|
||||
|
||||
.solduri-compact-card__curent-chip {
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-semibold);
|
||||
background: var(--surface-hover);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 2px var(--space-xs);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.solduri-compact-card__curent-total {
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-bold);
|
||||
font-family: var(--font-mono, monospace);
|
||||
color: var(--text-color);
|
||||
margin-left: var(--space-xs);
|
||||
}
|
||||
|
||||
/* Responsive - Mobile */
|
||||
@media (max-width: 768px) {
|
||||
.solduri-compact-card {
|
||||
|
||||
Reference in New Issue
Block a user