@hed-hog/finance 0.0.235 → 0.0.237

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.
Files changed (75) hide show
  1. package/dist/dto/create-cost-center.dto.d.ts +4 -0
  2. package/dist/dto/create-cost-center.dto.d.ts.map +1 -0
  3. package/dist/dto/create-cost-center.dto.js +24 -0
  4. package/dist/dto/create-cost-center.dto.js.map +1 -0
  5. package/dist/dto/create-finance-category.dto.d.ts +6 -0
  6. package/dist/dto/create-finance-category.dto.d.ts.map +1 -0
  7. package/dist/dto/create-finance-category.dto.js +37 -0
  8. package/dist/dto/create-finance-category.dto.js.map +1 -0
  9. package/dist/dto/create-period-close.dto.d.ts +7 -0
  10. package/dist/dto/create-period-close.dto.d.ts.map +1 -0
  11. package/dist/dto/create-period-close.dto.js +44 -0
  12. package/dist/dto/create-period-close.dto.js.map +1 -0
  13. package/dist/dto/move-finance-category.dto.d.ts +5 -0
  14. package/dist/dto/move-finance-category.dto.d.ts.map +1 -0
  15. package/dist/dto/move-finance-category.dto.js +32 -0
  16. package/dist/dto/move-finance-category.dto.js.map +1 -0
  17. package/dist/dto/update-cost-center.dto.d.ts +5 -0
  18. package/dist/dto/update-cost-center.dto.d.ts.map +1 -0
  19. package/dist/dto/update-cost-center.dto.js +32 -0
  20. package/dist/dto/update-cost-center.dto.js.map +1 -0
  21. package/dist/dto/update-finance-category.dto.d.ts +7 -0
  22. package/dist/dto/update-finance-category.dto.d.ts.map +1 -0
  23. package/dist/dto/update-finance-category.dto.js +46 -0
  24. package/dist/dto/update-finance-category.dto.js.map +1 -0
  25. package/dist/finance-audit-logs.controller.d.ts +13 -0
  26. package/dist/finance-audit-logs.controller.d.ts.map +1 -0
  27. package/dist/finance-audit-logs.controller.js +54 -0
  28. package/dist/finance-audit-logs.controller.js.map +1 -0
  29. package/dist/finance-categories.controller.d.ts +42 -0
  30. package/dist/finance-categories.controller.d.ts.map +1 -0
  31. package/dist/finance-categories.controller.js +84 -0
  32. package/dist/finance-categories.controller.js.map +1 -0
  33. package/dist/finance-cost-centers.controller.d.ts +32 -0
  34. package/dist/finance-cost-centers.controller.d.ts.map +1 -0
  35. package/dist/finance-cost-centers.controller.js +72 -0
  36. package/dist/finance-cost-centers.controller.js.map +1 -0
  37. package/dist/finance-period-close.controller.d.ts +27 -0
  38. package/dist/finance-period-close.controller.d.ts.map +1 -0
  39. package/dist/finance-period-close.controller.js +64 -0
  40. package/dist/finance-period-close.controller.js.map +1 -0
  41. package/dist/finance.module.d.ts.map +1 -1
  42. package/dist/finance.module.js +8 -0
  43. package/dist/finance.module.js.map +1 -1
  44. package/dist/finance.service.d.ts +111 -0
  45. package/dist/finance.service.d.ts.map +1 -1
  46. package/dist/finance.service.js +446 -17
  47. package/dist/finance.service.js.map +1 -1
  48. package/dist/index.d.ts +4 -0
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +4 -0
  51. package/dist/index.js.map +1 -1
  52. package/hedhog/data/route.yaml +108 -0
  53. package/hedhog/frontend/app/_components/person-field-with-create.tsx.ejs +627 -0
  54. package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +865 -883
  55. package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +838 -861
  56. package/hedhog/frontend/app/administration/audit-logs/page.tsx.ejs +309 -0
  57. package/hedhog/frontend/app/administration/categories/page.tsx.ejs +725 -0
  58. package/hedhog/frontend/app/administration/cost-centers/page.tsx.ejs +378 -0
  59. package/hedhog/frontend/app/administration/period-close/page.tsx.ejs +502 -0
  60. package/hedhog/frontend/messages/en.json +225 -0
  61. package/hedhog/frontend/messages/pt.json +225 -0
  62. package/package.json +5 -5
  63. package/src/dto/create-cost-center.dto.ts +9 -0
  64. package/src/dto/create-finance-category.dto.ts +21 -0
  65. package/src/dto/create-period-close.dto.ts +34 -0
  66. package/src/dto/move-finance-category.dto.ts +18 -0
  67. package/src/dto/update-cost-center.dto.ts +17 -0
  68. package/src/dto/update-finance-category.dto.ts +30 -0
  69. package/src/finance-audit-logs.controller.ts +30 -0
  70. package/src/finance-categories.controller.ts +52 -0
  71. package/src/finance-cost-centers.controller.ts +43 -0
  72. package/src/finance-period-close.controller.ts +34 -0
  73. package/src/finance.module.ts +8 -0
  74. package/src/finance.service.ts +578 -9
  75. package/src/index.ts +4 -0
@@ -0,0 +1,309 @@
1
+ 'use client';
2
+
3
+ import { Page, PageHeader, PaginationFooter } from '@/components/entity-list';
4
+ import { Badge } from '@/components/ui/badge';
5
+ import { Button } from '@/components/ui/button';
6
+ import {
7
+ Card,
8
+ CardContent,
9
+ CardDescription,
10
+ CardHeader,
11
+ CardTitle,
12
+ } from '@/components/ui/card';
13
+ import { Input } from '@/components/ui/input';
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 { useApp, useQuery } from '@hed-hog/next-app-provider';
30
+ import { Search, X } from 'lucide-react';
31
+ import { useTranslations } from 'next-intl';
32
+ import { useMemo, useState } from 'react';
33
+
34
+ type AuditLog = {
35
+ id: string;
36
+ actorUserId: string | null;
37
+ actorName: string;
38
+ actorEmail: string;
39
+ action: string;
40
+ entityTable: string;
41
+ entityId: string;
42
+ summary: string;
43
+ ipAddress: string;
44
+ createdAt: string | null;
45
+ };
46
+
47
+ type PaginatedAuditLogs = {
48
+ total: number;
49
+ lastPage: number;
50
+ page: number;
51
+ pageSize: number;
52
+ data: AuditLog[];
53
+ };
54
+
55
+ export default function AuditLogsPage() {
56
+ const t = useTranslations('finance.AdminAuditLogsPage');
57
+ const { request } = useApp();
58
+
59
+ const [page, setPage] = useState(1);
60
+ const [pageSize, setPageSize] = useState(10);
61
+ const [search, setSearch] = useState('');
62
+ const [action, setAction] = useState('all');
63
+ const [entityTable, setEntityTable] = useState('all');
64
+ const [actorUserId, setActorUserId] = useState('');
65
+ const [from, setFrom] = useState('');
66
+ const [to, setTo] = useState('');
67
+
68
+ const { data, isLoading, refetch } = useQuery<PaginatedAuditLogs>({
69
+ queryKey: [
70
+ 'finance-audit-logs',
71
+ page,
72
+ pageSize,
73
+ search,
74
+ action,
75
+ entityTable,
76
+ actorUserId,
77
+ from,
78
+ to,
79
+ ],
80
+ queryFn: async () => {
81
+ const params = new URLSearchParams();
82
+ params.set('page', String(page));
83
+ params.set('pageSize', String(pageSize));
84
+ params.set('sortField', 'created_at');
85
+ params.set('sortOrder', 'desc');
86
+
87
+ if (search.trim()) params.set('search', search.trim());
88
+ if (action !== 'all') params.set('action', action);
89
+ if (entityTable !== 'all') params.set('entity_table', entityTable);
90
+ if (actorUserId.trim()) params.set('actor_user_id', actorUserId.trim());
91
+ if (from) params.set('from', from);
92
+ if (to) params.set('to', to);
93
+
94
+ const response = await request({
95
+ url: `/finance/audit-logs?${params.toString()}`,
96
+ method: 'GET',
97
+ });
98
+
99
+ return (response.data || {
100
+ total: 0,
101
+ lastPage: 1,
102
+ page: 1,
103
+ pageSize,
104
+ data: [],
105
+ }) as PaginatedAuditLogs;
106
+ },
107
+ placeholderData: (old) => old,
108
+ });
109
+
110
+ const rows = data?.data || [];
111
+
112
+ const entityOptions = useMemo(() => {
113
+ const unique = new Set(rows.map((row) => row.entityTable).filter(Boolean));
114
+ return ['all', ...Array.from(unique).sort()];
115
+ }, [rows]);
116
+
117
+ return (
118
+ <Page>
119
+ <PageHeader
120
+ title={t('header.title')}
121
+ description={t('header.description')}
122
+ breadcrumbs={[
123
+ { label: t('breadcrumbs.finance'), href: '/finance' },
124
+ {
125
+ label: t('breadcrumbs.administration'),
126
+ href: '/finance/administration',
127
+ },
128
+ { label: t('breadcrumbs.current') },
129
+ ]}
130
+ />
131
+
132
+ <Card>
133
+ <CardHeader>
134
+ <CardTitle>{t('card.title')}</CardTitle>
135
+ <CardDescription>{t('card.description')}</CardDescription>
136
+ </CardHeader>
137
+
138
+ <CardContent className="space-y-4">
139
+ <div className="grid gap-3 md:grid-cols-2 lg:grid-cols-4">
140
+ <div className="relative lg:col-span-2">
141
+ <Search className="pointer-events-none absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
142
+ <Input
143
+ placeholder={t('filters.searchPlaceholder')}
144
+ value={search}
145
+ onChange={(event) => {
146
+ setSearch(event.target.value);
147
+ setPage(1);
148
+ }}
149
+ className="pl-8"
150
+ />
151
+ </div>
152
+
153
+ <Select
154
+ value={action}
155
+ onValueChange={(value) => {
156
+ setAction(value);
157
+ setPage(1);
158
+ }}
159
+ >
160
+ <SelectTrigger>
161
+ <SelectValue placeholder={t('filters.action')} />
162
+ </SelectTrigger>
163
+ <SelectContent>
164
+ <SelectItem value="all">{t('filters.allActions')}</SelectItem>
165
+ <SelectItem value="create">create</SelectItem>
166
+ <SelectItem value="update">update</SelectItem>
167
+ <SelectItem value="delete">delete</SelectItem>
168
+ </SelectContent>
169
+ </Select>
170
+
171
+ <Input
172
+ placeholder={t('filters.userPlaceholder')}
173
+ value={actorUserId}
174
+ onChange={(event) => {
175
+ setActorUserId(event.target.value);
176
+ setPage(1);
177
+ }}
178
+ />
179
+
180
+ <Select
181
+ value={entityTable}
182
+ onValueChange={(value) => {
183
+ setEntityTable(value);
184
+ setPage(1);
185
+ }}
186
+ >
187
+ <SelectTrigger>
188
+ <SelectValue placeholder={t('filters.entity')} />
189
+ </SelectTrigger>
190
+ <SelectContent>
191
+ {entityOptions.map((option) => (
192
+ <SelectItem key={option} value={option}>
193
+ {option === 'all' ? t('filters.allEntities') : option}
194
+ </SelectItem>
195
+ ))}
196
+ </SelectContent>
197
+ </Select>
198
+
199
+ <Input
200
+ type="date"
201
+ value={from}
202
+ onChange={(event) => {
203
+ setFrom(event.target.value);
204
+ setPage(1);
205
+ }}
206
+ />
207
+
208
+ <Input
209
+ type="date"
210
+ value={to}
211
+ onChange={(event) => {
212
+ setTo(event.target.value);
213
+ setPage(1);
214
+ }}
215
+ />
216
+
217
+ <Button
218
+ variant="outline"
219
+ className="gap-2"
220
+ onClick={() => {
221
+ setSearch('');
222
+ setAction('all');
223
+ setEntityTable('all');
224
+ setActorUserId('');
225
+ setFrom('');
226
+ setTo('');
227
+ setPage(1);
228
+ refetch();
229
+ }}
230
+ >
231
+ <X className="h-4 w-4" />
232
+ {t('filters.clear')}
233
+ </Button>
234
+ </div>
235
+
236
+ <div className="rounded-md border">
237
+ <Table>
238
+ <TableHeader>
239
+ <TableRow>
240
+ <TableHead>{t('table.headers.date')}</TableHead>
241
+ <TableHead>{t('table.headers.author')}</TableHead>
242
+ <TableHead>{t('table.headers.action')}</TableHead>
243
+ <TableHead>{t('table.headers.entity')}</TableHead>
244
+ <TableHead>{t('table.headers.record')}</TableHead>
245
+ <TableHead>{t('table.headers.summary')}</TableHead>
246
+ <TableHead>IP</TableHead>
247
+ </TableRow>
248
+ </TableHeader>
249
+ <TableBody>
250
+ {isLoading ? (
251
+ <TableRow>
252
+ <TableCell colSpan={7} className="h-24 text-center">
253
+ {t('table.loading')}
254
+ </TableCell>
255
+ </TableRow>
256
+ ) : rows.length === 0 ? (
257
+ <TableRow>
258
+ <TableCell colSpan={7} className="h-24 text-center">
259
+ {t('table.empty')}
260
+ </TableCell>
261
+ </TableRow>
262
+ ) : (
263
+ rows.map((row) => (
264
+ <TableRow key={row.id}>
265
+ <TableCell>
266
+ {row.createdAt
267
+ ? new Date(row.createdAt).toLocaleString('pt-BR')
268
+ : '-'}
269
+ </TableCell>
270
+ <TableCell>
271
+ <div className="flex flex-col">
272
+ <span>{row.actorName || '-'}</span>
273
+ <span className="text-xs text-muted-foreground">
274
+ {row.actorEmail || row.actorUserId || '-'}
275
+ </span>
276
+ </div>
277
+ </TableCell>
278
+ <TableCell>
279
+ <Badge variant="outline">{row.action}</Badge>
280
+ </TableCell>
281
+ <TableCell>{row.entityTable}</TableCell>
282
+ <TableCell>{row.entityId}</TableCell>
283
+ <TableCell className="max-w-[360px] truncate">
284
+ {row.summary || '-'}
285
+ </TableCell>
286
+ <TableCell>{row.ipAddress || '-'}</TableCell>
287
+ </TableRow>
288
+ ))
289
+ )}
290
+ </TableBody>
291
+ </Table>
292
+ </div>
293
+
294
+ <PaginationFooter
295
+ currentPage={data?.page || page}
296
+ pageSize={data?.pageSize || pageSize}
297
+ totalItems={data?.total || 0}
298
+ onPageChange={(newPage) => setPage(newPage)}
299
+ onPageSizeChange={(newPageSize) => {
300
+ setPageSize(newPageSize);
301
+ setPage(1);
302
+ }}
303
+ pageSizeOptions={[10, 20, 30, 40, 50]}
304
+ />
305
+ </CardContent>
306
+ </Card>
307
+ </Page>
308
+ );
309
+ }