@hed-hog/finance 0.0.276 → 0.0.279
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -26
- package/hedhog/data/menu.yaml +46 -0
- package/hedhog/frontend/app/reports/_lib/report-aggregations.ts.ejs +275 -0
- package/hedhog/frontend/app/reports/_lib/report-mocks.ts.ejs +186 -0
- package/hedhog/frontend/app/reports/overview-results/page.tsx.ejs +337 -0
- package/hedhog/frontend/app/reports/top-customers/page.tsx.ejs +310 -0
- package/hedhog/frontend/app/reports/top-operational-expenses/page.tsx.ejs +318 -0
- package/hedhog/frontend/messages/en.json +148 -0
- package/hedhog/frontend/messages/pt.json +148 -0
- package/package.json +6 -6
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Page, PageHeader } from '@/components/entity-list';
|
|
4
|
+
import {
|
|
5
|
+
Card,
|
|
6
|
+
CardContent,
|
|
7
|
+
CardDescription,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardTitle,
|
|
10
|
+
} from '@/components/ui/card';
|
|
11
|
+
import { Input } from '@/components/ui/input';
|
|
12
|
+
import { Label } from '@/components/ui/label';
|
|
13
|
+
import { Money } from '@/components/ui/money';
|
|
14
|
+
import {
|
|
15
|
+
Select,
|
|
16
|
+
SelectContent,
|
|
17
|
+
SelectItem,
|
|
18
|
+
SelectTrigger,
|
|
19
|
+
SelectValue,
|
|
20
|
+
} from '@/components/ui/select';
|
|
21
|
+
import {
|
|
22
|
+
Table,
|
|
23
|
+
TableBody,
|
|
24
|
+
TableCell,
|
|
25
|
+
TableHead,
|
|
26
|
+
TableHeader,
|
|
27
|
+
TableRow,
|
|
28
|
+
} from '@/components/ui/table';
|
|
29
|
+
import { Building2, CircleDollarSign, TriangleAlert } from 'lucide-react';
|
|
30
|
+
import { useTranslations } from 'next-intl';
|
|
31
|
+
import { useMemo, useState } from 'react';
|
|
32
|
+
import {
|
|
33
|
+
Bar,
|
|
34
|
+
BarChart,
|
|
35
|
+
Cell,
|
|
36
|
+
Pie,
|
|
37
|
+
PieChart,
|
|
38
|
+
ResponsiveContainer,
|
|
39
|
+
Tooltip,
|
|
40
|
+
XAxis,
|
|
41
|
+
YAxis,
|
|
42
|
+
} from 'recharts';
|
|
43
|
+
import {
|
|
44
|
+
aggregateOperationalExpenses,
|
|
45
|
+
getDefaultDateRange,
|
|
46
|
+
} from '../_lib/report-aggregations';
|
|
47
|
+
import { type GroupBy } from '../_lib/report-mocks';
|
|
48
|
+
|
|
49
|
+
const pieColors = [
|
|
50
|
+
'hsl(var(--chart-1))',
|
|
51
|
+
'hsl(var(--chart-2))',
|
|
52
|
+
'hsl(var(--chart-3))',
|
|
53
|
+
'hsl(var(--chart-4))',
|
|
54
|
+
'hsl(var(--chart-5))',
|
|
55
|
+
'#64748B',
|
|
56
|
+
'#0EA5E9',
|
|
57
|
+
'#22C55E',
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
export default function TopOperationalExpensesReportPage() {
|
|
61
|
+
const t = useTranslations('finance.TopOperationalExpensesReportPage');
|
|
62
|
+
const defaults = getDefaultDateRange();
|
|
63
|
+
|
|
64
|
+
const [from, setFrom] = useState(defaults.from);
|
|
65
|
+
const [to, setTo] = useState(defaults.to);
|
|
66
|
+
const [groupBy, setGroupBy] = useState<GroupBy>('year');
|
|
67
|
+
|
|
68
|
+
const data = useMemo(
|
|
69
|
+
() =>
|
|
70
|
+
aggregateOperationalExpenses({
|
|
71
|
+
from,
|
|
72
|
+
to,
|
|
73
|
+
groupBy,
|
|
74
|
+
topN: 20,
|
|
75
|
+
}),
|
|
76
|
+
[from, to, groupBy]
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const highest = data.topExpenses[0];
|
|
80
|
+
const average =
|
|
81
|
+
data.topExpenses.length > 0
|
|
82
|
+
? data.topExpenses.reduce((acc, item) => acc + item.value, 0) /
|
|
83
|
+
data.topExpenses.length
|
|
84
|
+
: 0;
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Page>
|
|
88
|
+
<PageHeader
|
|
89
|
+
title={t('header.title')}
|
|
90
|
+
description={t('header.description')}
|
|
91
|
+
breadcrumbs={[
|
|
92
|
+
{ label: t('breadcrumbs.home'), href: '/' },
|
|
93
|
+
{ label: t('breadcrumbs.finance'), href: '/finance' },
|
|
94
|
+
{ label: t('breadcrumbs.current') },
|
|
95
|
+
]}
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
<Card>
|
|
99
|
+
<CardHeader>
|
|
100
|
+
<CardTitle>{t('filters.title')}</CardTitle>
|
|
101
|
+
<CardDescription>{t('filters.description')}</CardDescription>
|
|
102
|
+
</CardHeader>
|
|
103
|
+
<CardContent className="grid gap-4 md:grid-cols-3">
|
|
104
|
+
<div className="space-y-2">
|
|
105
|
+
<Label htmlFor="from">{t('filters.from')}</Label>
|
|
106
|
+
<Input
|
|
107
|
+
id="from"
|
|
108
|
+
type="date"
|
|
109
|
+
value={from}
|
|
110
|
+
onChange={(event) => setFrom(event.target.value)}
|
|
111
|
+
max={to}
|
|
112
|
+
/>
|
|
113
|
+
</div>
|
|
114
|
+
<div className="space-y-2">
|
|
115
|
+
<Label htmlFor="to">{t('filters.to')}</Label>
|
|
116
|
+
<Input
|
|
117
|
+
id="to"
|
|
118
|
+
type="date"
|
|
119
|
+
value={to}
|
|
120
|
+
onChange={(event) => setTo(event.target.value)}
|
|
121
|
+
min={from}
|
|
122
|
+
/>
|
|
123
|
+
</div>
|
|
124
|
+
<div className="space-y-2">
|
|
125
|
+
<Label>{t('filters.groupBy')}</Label>
|
|
126
|
+
<Select
|
|
127
|
+
value={groupBy}
|
|
128
|
+
onValueChange={(value) => setGroupBy(value as GroupBy)}
|
|
129
|
+
>
|
|
130
|
+
<SelectTrigger>
|
|
131
|
+
<SelectValue />
|
|
132
|
+
</SelectTrigger>
|
|
133
|
+
<SelectContent>
|
|
134
|
+
<SelectItem value="day">{t('groupBy.day')}</SelectItem>
|
|
135
|
+
<SelectItem value="week">{t('groupBy.week')}</SelectItem>
|
|
136
|
+
<SelectItem value="month">{t('groupBy.month')}</SelectItem>
|
|
137
|
+
<SelectItem value="year">{t('groupBy.year')}</SelectItem>
|
|
138
|
+
</SelectContent>
|
|
139
|
+
</Select>
|
|
140
|
+
</div>
|
|
141
|
+
</CardContent>
|
|
142
|
+
</Card>
|
|
143
|
+
|
|
144
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
145
|
+
<Card>
|
|
146
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
147
|
+
<CardTitle className="text-sm font-medium">
|
|
148
|
+
{t('cards.total')}
|
|
149
|
+
</CardTitle>
|
|
150
|
+
<CircleDollarSign className="h-4 w-4 text-muted-foreground" />
|
|
151
|
+
</CardHeader>
|
|
152
|
+
<CardContent>
|
|
153
|
+
<div className="text-2xl font-bold">
|
|
154
|
+
<Money value={data.total} />
|
|
155
|
+
</div>
|
|
156
|
+
</CardContent>
|
|
157
|
+
</Card>
|
|
158
|
+
|
|
159
|
+
<Card>
|
|
160
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
161
|
+
<CardTitle className="text-sm font-medium">
|
|
162
|
+
{t('cards.highestExpense')}
|
|
163
|
+
</CardTitle>
|
|
164
|
+
<TriangleAlert className="h-4 w-4 text-amber-500" />
|
|
165
|
+
</CardHeader>
|
|
166
|
+
<CardContent>
|
|
167
|
+
<div className="text-lg font-semibold">
|
|
168
|
+
{highest?.category || '-'}
|
|
169
|
+
</div>
|
|
170
|
+
<div className="text-muted-foreground text-sm">
|
|
171
|
+
{highest ? <Money value={highest.value} /> : '-'}
|
|
172
|
+
</div>
|
|
173
|
+
</CardContent>
|
|
174
|
+
</Card>
|
|
175
|
+
|
|
176
|
+
<Card>
|
|
177
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
178
|
+
<CardTitle className="text-sm font-medium">
|
|
179
|
+
{t('cards.average')}
|
|
180
|
+
</CardTitle>
|
|
181
|
+
<Building2 className="h-4 w-4 text-muted-foreground" />
|
|
182
|
+
</CardHeader>
|
|
183
|
+
<CardContent>
|
|
184
|
+
<div className="text-2xl font-bold">
|
|
185
|
+
<Money value={average} />
|
|
186
|
+
</div>
|
|
187
|
+
</CardContent>
|
|
188
|
+
</Card>
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
<div className="grid gap-4 xl:grid-cols-5">
|
|
192
|
+
<Card className="xl:col-span-3">
|
|
193
|
+
<CardHeader>
|
|
194
|
+
<CardTitle>{t('bars.title')}</CardTitle>
|
|
195
|
+
<CardDescription>{t('bars.description')}</CardDescription>
|
|
196
|
+
</CardHeader>
|
|
197
|
+
<CardContent>
|
|
198
|
+
<ResponsiveContainer width="100%" height={560}>
|
|
199
|
+
<BarChart
|
|
200
|
+
data={[...data.topExpenses].reverse()}
|
|
201
|
+
layout="vertical"
|
|
202
|
+
margin={{ left: 80, right: 16 }}
|
|
203
|
+
>
|
|
204
|
+
<XAxis
|
|
205
|
+
type="number"
|
|
206
|
+
tickFormatter={(value) => `${(value / 1000).toFixed(0)}k`}
|
|
207
|
+
/>
|
|
208
|
+
<YAxis dataKey="category" type="category" width={210} />
|
|
209
|
+
<Tooltip
|
|
210
|
+
formatter={(value: number) =>
|
|
211
|
+
new Intl.NumberFormat('pt-BR', {
|
|
212
|
+
style: 'currency',
|
|
213
|
+
currency: 'BRL',
|
|
214
|
+
}).format(value)
|
|
215
|
+
}
|
|
216
|
+
/>
|
|
217
|
+
<Bar
|
|
218
|
+
dataKey="value"
|
|
219
|
+
radius={[0, 6, 6, 0]}
|
|
220
|
+
fill="hsl(var(--chart-5))"
|
|
221
|
+
/>
|
|
222
|
+
</BarChart>
|
|
223
|
+
</ResponsiveContainer>
|
|
224
|
+
</CardContent>
|
|
225
|
+
</Card>
|
|
226
|
+
|
|
227
|
+
<Card className="xl:col-span-2">
|
|
228
|
+
<CardHeader>
|
|
229
|
+
<CardTitle>{t('pie.title')}</CardTitle>
|
|
230
|
+
<CardDescription>{t('pie.description')}</CardDescription>
|
|
231
|
+
</CardHeader>
|
|
232
|
+
<CardContent>
|
|
233
|
+
<ResponsiveContainer width="100%" height={380}>
|
|
234
|
+
<PieChart>
|
|
235
|
+
<Pie
|
|
236
|
+
data={data.pieData}
|
|
237
|
+
dataKey="value"
|
|
238
|
+
nameKey="name"
|
|
239
|
+
innerRadius={65}
|
|
240
|
+
outerRadius={120}
|
|
241
|
+
paddingAngle={2}
|
|
242
|
+
>
|
|
243
|
+
{data.pieData.map((entry, index) => (
|
|
244
|
+
<Cell
|
|
245
|
+
key={entry.name}
|
|
246
|
+
fill={pieColors[index % pieColors.length]}
|
|
247
|
+
/>
|
|
248
|
+
))}
|
|
249
|
+
</Pie>
|
|
250
|
+
<Tooltip
|
|
251
|
+
formatter={(value: number) =>
|
|
252
|
+
new Intl.NumberFormat('pt-BR', {
|
|
253
|
+
style: 'currency',
|
|
254
|
+
currency: 'BRL',
|
|
255
|
+
}).format(value)
|
|
256
|
+
}
|
|
257
|
+
/>
|
|
258
|
+
</PieChart>
|
|
259
|
+
</ResponsiveContainer>
|
|
260
|
+
</CardContent>
|
|
261
|
+
</Card>
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
<Card>
|
|
265
|
+
<CardHeader>
|
|
266
|
+
<CardTitle>{t('table.title')}</CardTitle>
|
|
267
|
+
<CardDescription>{t('table.description')}</CardDescription>
|
|
268
|
+
</CardHeader>
|
|
269
|
+
<CardContent>
|
|
270
|
+
<Table>
|
|
271
|
+
<TableHeader>
|
|
272
|
+
<TableRow>
|
|
273
|
+
<TableHead>{t('table.headers.category')}</TableHead>
|
|
274
|
+
<TableHead>{t('table.headers.costCenter')}</TableHead>
|
|
275
|
+
<TableHead className="text-right">
|
|
276
|
+
{t('table.headers.value')}
|
|
277
|
+
</TableHead>
|
|
278
|
+
<TableHead className="text-right">
|
|
279
|
+
{t('table.headers.participation')}
|
|
280
|
+
</TableHead>
|
|
281
|
+
</TableRow>
|
|
282
|
+
</TableHeader>
|
|
283
|
+
<TableBody>
|
|
284
|
+
{data.topExpenses.length === 0 ? (
|
|
285
|
+
<TableRow>
|
|
286
|
+
<TableCell
|
|
287
|
+
colSpan={4}
|
|
288
|
+
className="text-muted-foreground text-center"
|
|
289
|
+
>
|
|
290
|
+
{t('table.empty')}
|
|
291
|
+
</TableCell>
|
|
292
|
+
</TableRow>
|
|
293
|
+
) : (
|
|
294
|
+
data.topExpenses.map((item) => {
|
|
295
|
+
const participation =
|
|
296
|
+
data.total > 0 ? (item.value / data.total) * 100 : 0;
|
|
297
|
+
|
|
298
|
+
return (
|
|
299
|
+
<TableRow key={item.category}>
|
|
300
|
+
<TableCell>{item.category}</TableCell>
|
|
301
|
+
<TableCell>{item.costCenter}</TableCell>
|
|
302
|
+
<TableCell className="text-right">
|
|
303
|
+
<Money value={item.value} />
|
|
304
|
+
</TableCell>
|
|
305
|
+
<TableCell className="text-right">
|
|
306
|
+
{participation.toFixed(2)}%
|
|
307
|
+
</TableCell>
|
|
308
|
+
</TableRow>
|
|
309
|
+
);
|
|
310
|
+
})
|
|
311
|
+
)}
|
|
312
|
+
</TableBody>
|
|
313
|
+
</Table>
|
|
314
|
+
</CardContent>
|
|
315
|
+
</Card>
|
|
316
|
+
</Page>
|
|
317
|
+
);
|
|
318
|
+
}
|
|
@@ -1582,5 +1582,153 @@
|
|
|
1582
1582
|
"negative": "Negative",
|
|
1583
1583
|
"withGrowth": "With growth of {value}%"
|
|
1584
1584
|
}
|
|
1585
|
+
},
|
|
1586
|
+
"OverviewResultsReportPage": {
|
|
1587
|
+
"header": {
|
|
1588
|
+
"title": "Results Overview",
|
|
1589
|
+
"description": "Compare revenue and expenses in the selected period"
|
|
1590
|
+
},
|
|
1591
|
+
"breadcrumbs": {
|
|
1592
|
+
"home": "Home",
|
|
1593
|
+
"finance": "Finance",
|
|
1594
|
+
"current": "Results Overview"
|
|
1595
|
+
},
|
|
1596
|
+
"filters": {
|
|
1597
|
+
"title": "Filters",
|
|
1598
|
+
"description": "Set period and grouping for analysis",
|
|
1599
|
+
"from": "From",
|
|
1600
|
+
"to": "To",
|
|
1601
|
+
"groupBy": "Group by"
|
|
1602
|
+
},
|
|
1603
|
+
"groupBy": {
|
|
1604
|
+
"day": "Day",
|
|
1605
|
+
"week": "Week",
|
|
1606
|
+
"month": "Month",
|
|
1607
|
+
"year": "Year"
|
|
1608
|
+
},
|
|
1609
|
+
"cards": {
|
|
1610
|
+
"revenue": "Revenue",
|
|
1611
|
+
"expensesAndLoans": "Expenses + Loans",
|
|
1612
|
+
"resultDifference": "Result Difference",
|
|
1613
|
+
"margin": "Margin"
|
|
1614
|
+
},
|
|
1615
|
+
"status": {
|
|
1616
|
+
"positive": "Positive Result",
|
|
1617
|
+
"negative": "Negative Result"
|
|
1618
|
+
},
|
|
1619
|
+
"chart": {
|
|
1620
|
+
"title": "Results Comparison",
|
|
1621
|
+
"description": "Result evolution by grouped period",
|
|
1622
|
+
"revenueLabel": "Revenue",
|
|
1623
|
+
"expensesLabel": "Expenses + Loans",
|
|
1624
|
+
"differenceLabel": "Difference"
|
|
1625
|
+
},
|
|
1626
|
+
"table": {
|
|
1627
|
+
"title": "Period Summary",
|
|
1628
|
+
"description": "Consolidated detail for selected range",
|
|
1629
|
+
"headers": {
|
|
1630
|
+
"period": "Period",
|
|
1631
|
+
"revenue": "Revenue",
|
|
1632
|
+
"expensesAndLoans": "Expenses + Loans",
|
|
1633
|
+
"investorContribution": "Investor Contribution",
|
|
1634
|
+
"difference": "Difference"
|
|
1635
|
+
},
|
|
1636
|
+
"empty": "No data found for selected filters"
|
|
1637
|
+
}
|
|
1638
|
+
},
|
|
1639
|
+
"TopCustomersReportPage": {
|
|
1640
|
+
"header": {
|
|
1641
|
+
"title": "Top Customers",
|
|
1642
|
+
"description": "Customer ranking for the selected period"
|
|
1643
|
+
},
|
|
1644
|
+
"breadcrumbs": {
|
|
1645
|
+
"home": "Home",
|
|
1646
|
+
"finance": "Finance",
|
|
1647
|
+
"current": "Top Customers"
|
|
1648
|
+
},
|
|
1649
|
+
"filters": {
|
|
1650
|
+
"title": "Filters",
|
|
1651
|
+
"description": "Select period and grouping level",
|
|
1652
|
+
"from": "From",
|
|
1653
|
+
"to": "To",
|
|
1654
|
+
"groupBy": "Group by"
|
|
1655
|
+
},
|
|
1656
|
+
"groupBy": {
|
|
1657
|
+
"day": "Day",
|
|
1658
|
+
"week": "Week",
|
|
1659
|
+
"month": "Month",
|
|
1660
|
+
"year": "Year"
|
|
1661
|
+
},
|
|
1662
|
+
"cards": {
|
|
1663
|
+
"total": "Total in Period",
|
|
1664
|
+
"top5Concentration": "Top 5 Concentration",
|
|
1665
|
+
"leader": "Leading Customer"
|
|
1666
|
+
},
|
|
1667
|
+
"bars": {
|
|
1668
|
+
"title": "Top 20 Customers",
|
|
1669
|
+
"description": "Revenue ranking in selected period"
|
|
1670
|
+
},
|
|
1671
|
+
"pie": {
|
|
1672
|
+
"title": "Revenue Share",
|
|
1673
|
+
"description": "Distribution among customers"
|
|
1674
|
+
},
|
|
1675
|
+
"table": {
|
|
1676
|
+
"title": "Share Table",
|
|
1677
|
+
"description": "Individual customer contribution",
|
|
1678
|
+
"headers": {
|
|
1679
|
+
"customer": "Customer",
|
|
1680
|
+
"value": "Value",
|
|
1681
|
+
"participation": "Share"
|
|
1682
|
+
},
|
|
1683
|
+
"empty": "No customers found for selected filters"
|
|
1684
|
+
}
|
|
1685
|
+
},
|
|
1686
|
+
"TopOperationalExpensesReportPage": {
|
|
1687
|
+
"header": {
|
|
1688
|
+
"title": "Top Operational Expenses",
|
|
1689
|
+
"description": "Track the most relevant expenses by category"
|
|
1690
|
+
},
|
|
1691
|
+
"breadcrumbs": {
|
|
1692
|
+
"home": "Home",
|
|
1693
|
+
"finance": "Finance",
|
|
1694
|
+
"current": "Top Operational Expenses"
|
|
1695
|
+
},
|
|
1696
|
+
"filters": {
|
|
1697
|
+
"title": "Filters",
|
|
1698
|
+
"description": "Select period and grouping level",
|
|
1699
|
+
"from": "From",
|
|
1700
|
+
"to": "To",
|
|
1701
|
+
"groupBy": "Group by"
|
|
1702
|
+
},
|
|
1703
|
+
"groupBy": {
|
|
1704
|
+
"day": "Day",
|
|
1705
|
+
"week": "Week",
|
|
1706
|
+
"month": "Month",
|
|
1707
|
+
"year": "Year"
|
|
1708
|
+
},
|
|
1709
|
+
"cards": {
|
|
1710
|
+
"total": "Total Expenses",
|
|
1711
|
+
"highestExpense": "Highest Expense",
|
|
1712
|
+
"average": "Average (Top 20)"
|
|
1713
|
+
},
|
|
1714
|
+
"bars": {
|
|
1715
|
+
"title": "Top 20 Expenses",
|
|
1716
|
+
"description": "Largest values by category"
|
|
1717
|
+
},
|
|
1718
|
+
"pie": {
|
|
1719
|
+
"title": "Cost Center Composition",
|
|
1720
|
+
"description": "Operational expense distribution"
|
|
1721
|
+
},
|
|
1722
|
+
"table": {
|
|
1723
|
+
"title": "Expenses Table",
|
|
1724
|
+
"description": "Detail by category and cost center",
|
|
1725
|
+
"headers": {
|
|
1726
|
+
"category": "Category",
|
|
1727
|
+
"costCenter": "Cost Center",
|
|
1728
|
+
"value": "Value",
|
|
1729
|
+
"participation": "Share"
|
|
1730
|
+
},
|
|
1731
|
+
"empty": "No expenses found for selected filters"
|
|
1732
|
+
}
|
|
1585
1733
|
}
|
|
1586
1734
|
}
|
|
@@ -1582,5 +1582,153 @@
|
|
|
1582
1582
|
"negative": "Negativo",
|
|
1583
1583
|
"withGrowth": "Com crescimento de {value}%"
|
|
1584
1584
|
}
|
|
1585
|
+
},
|
|
1586
|
+
"OverviewResultsReportPage": {
|
|
1587
|
+
"header": {
|
|
1588
|
+
"title": "Visão Geral dos Resultados",
|
|
1589
|
+
"description": "Compare faturamento e despesas no período selecionado"
|
|
1590
|
+
},
|
|
1591
|
+
"breadcrumbs": {
|
|
1592
|
+
"home": "Início",
|
|
1593
|
+
"finance": "Financeiro",
|
|
1594
|
+
"current": "Visão Geral dos Resultados"
|
|
1595
|
+
},
|
|
1596
|
+
"filters": {
|
|
1597
|
+
"title": "Filtros",
|
|
1598
|
+
"description": "Defina período e agrupamento para análise",
|
|
1599
|
+
"from": "Data de",
|
|
1600
|
+
"to": "Data até",
|
|
1601
|
+
"groupBy": "Agrupar por"
|
|
1602
|
+
},
|
|
1603
|
+
"groupBy": {
|
|
1604
|
+
"day": "Dia",
|
|
1605
|
+
"week": "Semana",
|
|
1606
|
+
"month": "Mês",
|
|
1607
|
+
"year": "Ano"
|
|
1608
|
+
},
|
|
1609
|
+
"cards": {
|
|
1610
|
+
"revenue": "Faturamento",
|
|
1611
|
+
"expensesAndLoans": "Despesas + Empréstimos",
|
|
1612
|
+
"resultDifference": "Diferença de Resultado",
|
|
1613
|
+
"margin": "Margem"
|
|
1614
|
+
},
|
|
1615
|
+
"status": {
|
|
1616
|
+
"positive": "Resultado Positivo",
|
|
1617
|
+
"negative": "Resultado Negativo"
|
|
1618
|
+
},
|
|
1619
|
+
"chart": {
|
|
1620
|
+
"title": "Comparativo de Resultados",
|
|
1621
|
+
"description": "Evolução do resultado por período agrupado",
|
|
1622
|
+
"revenueLabel": "Faturamento",
|
|
1623
|
+
"expensesLabel": "Despesas + Empréstimos",
|
|
1624
|
+
"differenceLabel": "Diferença"
|
|
1625
|
+
},
|
|
1626
|
+
"table": {
|
|
1627
|
+
"title": "Resumo por Período",
|
|
1628
|
+
"description": "Detalhamento consolidado do intervalo selecionado",
|
|
1629
|
+
"headers": {
|
|
1630
|
+
"period": "Período",
|
|
1631
|
+
"revenue": "Faturamento",
|
|
1632
|
+
"expensesAndLoans": "Despesas + Empréstimos",
|
|
1633
|
+
"investorContribution": "Aporte Investidor",
|
|
1634
|
+
"difference": "Diferença"
|
|
1635
|
+
},
|
|
1636
|
+
"empty": "Nenhum dado encontrado para os filtros selecionados"
|
|
1637
|
+
}
|
|
1638
|
+
},
|
|
1639
|
+
"TopCustomersReportPage": {
|
|
1640
|
+
"header": {
|
|
1641
|
+
"title": "Principais Clientes",
|
|
1642
|
+
"description": "Ranking de clientes do período selecionado"
|
|
1643
|
+
},
|
|
1644
|
+
"breadcrumbs": {
|
|
1645
|
+
"home": "Início",
|
|
1646
|
+
"finance": "Financeiro",
|
|
1647
|
+
"current": "Principais Clientes"
|
|
1648
|
+
},
|
|
1649
|
+
"filters": {
|
|
1650
|
+
"title": "Filtros",
|
|
1651
|
+
"description": "Selecione o período e o nível de agrupamento",
|
|
1652
|
+
"from": "Data de",
|
|
1653
|
+
"to": "Data até",
|
|
1654
|
+
"groupBy": "Agrupar por"
|
|
1655
|
+
},
|
|
1656
|
+
"groupBy": {
|
|
1657
|
+
"day": "Dia",
|
|
1658
|
+
"week": "Semana",
|
|
1659
|
+
"month": "Mês",
|
|
1660
|
+
"year": "Ano"
|
|
1661
|
+
},
|
|
1662
|
+
"cards": {
|
|
1663
|
+
"total": "Total no Período",
|
|
1664
|
+
"top5Concentration": "Concentração Top 5",
|
|
1665
|
+
"leader": "Cliente Líder"
|
|
1666
|
+
},
|
|
1667
|
+
"bars": {
|
|
1668
|
+
"title": "Top 20 Clientes",
|
|
1669
|
+
"description": "Ranking por faturamento no período"
|
|
1670
|
+
},
|
|
1671
|
+
"pie": {
|
|
1672
|
+
"title": "Participação na Receita",
|
|
1673
|
+
"description": "Distribuição entre clientes"
|
|
1674
|
+
},
|
|
1675
|
+
"table": {
|
|
1676
|
+
"title": "Tabela de Participação",
|
|
1677
|
+
"description": "Contribuição individual por cliente",
|
|
1678
|
+
"headers": {
|
|
1679
|
+
"customer": "Cliente",
|
|
1680
|
+
"value": "Valor",
|
|
1681
|
+
"participation": "Participação"
|
|
1682
|
+
},
|
|
1683
|
+
"empty": "Nenhum cliente encontrado para os filtros selecionados"
|
|
1684
|
+
}
|
|
1685
|
+
},
|
|
1686
|
+
"TopOperationalExpensesReportPage": {
|
|
1687
|
+
"header": {
|
|
1688
|
+
"title": "Principais Gastos Operacionais",
|
|
1689
|
+
"description": "Acompanhe os gastos mais relevantes por categoria"
|
|
1690
|
+
},
|
|
1691
|
+
"breadcrumbs": {
|
|
1692
|
+
"home": "Início",
|
|
1693
|
+
"finance": "Financeiro",
|
|
1694
|
+
"current": "Principais Gastos Operacionais"
|
|
1695
|
+
},
|
|
1696
|
+
"filters": {
|
|
1697
|
+
"title": "Filtros",
|
|
1698
|
+
"description": "Selecione o período e o nível de agrupamento",
|
|
1699
|
+
"from": "Data de",
|
|
1700
|
+
"to": "Data até",
|
|
1701
|
+
"groupBy": "Agrupar por"
|
|
1702
|
+
},
|
|
1703
|
+
"groupBy": {
|
|
1704
|
+
"day": "Dia",
|
|
1705
|
+
"week": "Semana",
|
|
1706
|
+
"month": "Mês",
|
|
1707
|
+
"year": "Ano"
|
|
1708
|
+
},
|
|
1709
|
+
"cards": {
|
|
1710
|
+
"total": "Total de Gastos",
|
|
1711
|
+
"highestExpense": "Maior Gasto",
|
|
1712
|
+
"average": "Média (Top 20)"
|
|
1713
|
+
},
|
|
1714
|
+
"bars": {
|
|
1715
|
+
"title": "Top 20 Gastos",
|
|
1716
|
+
"description": "Maiores valores por categoria"
|
|
1717
|
+
},
|
|
1718
|
+
"pie": {
|
|
1719
|
+
"title": "Composição por Centro de Custo",
|
|
1720
|
+
"description": "Distribuição dos gastos operacionais"
|
|
1721
|
+
},
|
|
1722
|
+
"table": {
|
|
1723
|
+
"title": "Tabela de Gastos",
|
|
1724
|
+
"description": "Detalhamento por categoria e centro de custo",
|
|
1725
|
+
"headers": {
|
|
1726
|
+
"category": "Categoria",
|
|
1727
|
+
"costCenter": "Centro de Custo",
|
|
1728
|
+
"value": "Valor",
|
|
1729
|
+
"participation": "Participação"
|
|
1730
|
+
},
|
|
1731
|
+
"empty": "Nenhum gasto encontrado para os filtros selecionados"
|
|
1732
|
+
}
|
|
1585
1733
|
}
|
|
1586
1734
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/finance",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.279",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
"@nestjs/core": "^11",
|
|
10
10
|
"@nestjs/jwt": "^11",
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
|
-
"@hed-hog/
|
|
13
|
-
"@hed-hog/
|
|
12
|
+
"@hed-hog/tag": "0.0.279",
|
|
13
|
+
"@hed-hog/contact": "0.0.279",
|
|
14
14
|
"@hed-hog/api-prisma": "0.0.5",
|
|
15
|
-
"@hed-hog/
|
|
15
|
+
"@hed-hog/api": "0.0.4",
|
|
16
16
|
"@hed-hog/api-locale": "0.0.13",
|
|
17
|
+
"@hed-hog/core": "0.0.279",
|
|
17
18
|
"@hed-hog/api-types": "0.0.1",
|
|
18
|
-
"@hed-hog/api-pagination": "0.0.6"
|
|
19
|
-
"@hed-hog/core": "0.0.276"
|
|
19
|
+
"@hed-hog/api-pagination": "0.0.6"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|