@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,378 @@
1
+ 'use client';
2
+
3
+ import { Page, PageHeader } from '@/components/entity-list';
4
+ import {
5
+ AlertDialog,
6
+ AlertDialogAction,
7
+ AlertDialogCancel,
8
+ AlertDialogContent,
9
+ AlertDialogDescription,
10
+ AlertDialogFooter,
11
+ AlertDialogHeader,
12
+ AlertDialogTitle,
13
+ } from '@/components/ui/alert-dialog';
14
+ import { Badge } from '@/components/ui/badge';
15
+ import { Button } from '@/components/ui/button';
16
+ import {
17
+ Card,
18
+ CardContent,
19
+ CardDescription,
20
+ CardHeader,
21
+ CardTitle,
22
+ } from '@/components/ui/card';
23
+ import {
24
+ Form,
25
+ FormControl,
26
+ FormField,
27
+ FormItem,
28
+ FormLabel,
29
+ FormMessage,
30
+ } from '@/components/ui/form';
31
+ import { Input } from '@/components/ui/input';
32
+ import {
33
+ Sheet,
34
+ SheetContent,
35
+ SheetDescription,
36
+ SheetHeader,
37
+ SheetTitle,
38
+ } from '@/components/ui/sheet';
39
+ import { useApp, useQuery } from '@hed-hog/next-app-provider';
40
+ import { zodResolver } from '@hookform/resolvers/zod';
41
+ import { Building2, Pencil, Plus, Trash2 } from 'lucide-react';
42
+ import { useTranslations } from 'next-intl';
43
+ import { useEffect, useState } from 'react';
44
+ import { useForm } from 'react-hook-form';
45
+ import { z } from 'zod';
46
+
47
+ type CostCenterFormValues = {
48
+ nome: string;
49
+ };
50
+
51
+ type CostCenter = {
52
+ id: string;
53
+ codigo: string;
54
+ nome: string;
55
+ status: 'active' | 'inactive';
56
+ ativo: boolean;
57
+ };
58
+
59
+ function CentroCustoSheet({
60
+ open,
61
+ onOpenChange,
62
+ onSaved,
63
+ editingCostCenter,
64
+ onEditingChange,
65
+ t,
66
+ }: {
67
+ open: boolean;
68
+ onOpenChange: (open: boolean) => void;
69
+ onSaved: () => Promise<any> | void;
70
+ editingCostCenter: CostCenter | null;
71
+ onEditingChange: (costCenter: CostCenter | null) => void;
72
+ t: ReturnType<typeof useTranslations>;
73
+ }) {
74
+ const { request, showToastHandler } = useApp();
75
+
76
+ const costCenterFormSchema = z.object({
77
+ nome: z.string().trim().min(1, t('sheet.validation.nameRequired')),
78
+ });
79
+
80
+ const form = useForm<CostCenterFormValues>({
81
+ resolver: zodResolver(costCenterFormSchema),
82
+ defaultValues: {
83
+ nome: '',
84
+ },
85
+ });
86
+
87
+ useEffect(() => {
88
+ if (!open) {
89
+ form.reset({ nome: '' });
90
+ return;
91
+ }
92
+
93
+ if (editingCostCenter) {
94
+ form.reset({ nome: editingCostCenter.nome });
95
+ return;
96
+ }
97
+
98
+ form.reset({ nome: '' });
99
+ }, [open, editingCostCenter, form]);
100
+
101
+ const handleSubmit = async (values: CostCenterFormValues) => {
102
+ try {
103
+ if (editingCostCenter) {
104
+ await request({
105
+ url: `/finance/cost-centers/${editingCostCenter.id}`,
106
+ method: 'PATCH',
107
+ data: {
108
+ name: values.nome,
109
+ },
110
+ });
111
+ } else {
112
+ await request({
113
+ url: '/finance/cost-centers',
114
+ method: 'POST',
115
+ data: {
116
+ name: values.nome,
117
+ },
118
+ });
119
+ }
120
+
121
+ await onSaved();
122
+ form.reset({ nome: '' });
123
+ onEditingChange(null);
124
+ onOpenChange(false);
125
+ showToastHandler?.(
126
+ 'success',
127
+ editingCostCenter
128
+ ? t('messages.updateSuccess')
129
+ : t('messages.createSuccess')
130
+ );
131
+ } catch {
132
+ showToastHandler?.(
133
+ 'error',
134
+ editingCostCenter
135
+ ? t('messages.updateError')
136
+ : t('messages.createError')
137
+ );
138
+ }
139
+ };
140
+
141
+ const handleOpenChange = (nextOpen: boolean) => {
142
+ onOpenChange(nextOpen);
143
+
144
+ if (!nextOpen) {
145
+ form.reset({ nome: '' });
146
+ onEditingChange(null);
147
+ }
148
+ };
149
+
150
+ return (
151
+ <Sheet open={open} onOpenChange={handleOpenChange}>
152
+ <SheetContent className="w-full sm:max-w-lg">
153
+ <SheetHeader>
154
+ <SheetTitle>
155
+ {editingCostCenter ? t('sheet.editTitle') : t('sheet.newTitle')}
156
+ </SheetTitle>
157
+ <SheetDescription>
158
+ {editingCostCenter
159
+ ? t('sheet.editDescription')
160
+ : t('sheet.newDescription')}
161
+ </SheetDescription>
162
+ </SheetHeader>
163
+
164
+ <Form {...form}>
165
+ <form
166
+ className="space-y-4 p-4"
167
+ onSubmit={form.handleSubmit(handleSubmit)}
168
+ >
169
+ <FormField
170
+ control={form.control}
171
+ name="nome"
172
+ render={({ field }) => (
173
+ <FormItem>
174
+ <FormLabel>{t('sheet.fields.name')}</FormLabel>
175
+ <FormControl>
176
+ <Input
177
+ placeholder={t('sheet.fields.namePlaceholder')}
178
+ {...field}
179
+ />
180
+ </FormControl>
181
+ <FormMessage />
182
+ </FormItem>
183
+ )}
184
+ />
185
+
186
+ <div className="flex justify-end gap-2">
187
+ <Button
188
+ type="button"
189
+ variant="outline"
190
+ onClick={() => handleOpenChange(false)}
191
+ >
192
+ {t('common.cancel')}
193
+ </Button>
194
+ <Button type="submit" disabled={form.formState.isSubmitting}>
195
+ {t('common.save')}
196
+ </Button>
197
+ </div>
198
+ </form>
199
+ </Form>
200
+ </SheetContent>
201
+ </Sheet>
202
+ );
203
+ }
204
+
205
+ export default function CostCentersPage() {
206
+ const t = useTranslations('finance.AdminCostCentersPage');
207
+ const { request, showToastHandler } = useApp();
208
+
209
+ const [sheetOpen, setSheetOpen] = useState(false);
210
+ const [editingCostCenter, setEditingCostCenter] = useState<CostCenter | null>(
211
+ null
212
+ );
213
+ const [costCenterIdToDelete, setCostCenterIdToDelete] = useState<
214
+ string | null
215
+ >(null);
216
+
217
+ const { data: costCenters, refetch } = useQuery<CostCenter[]>({
218
+ queryKey: ['finance-cost-centers'],
219
+ queryFn: async () => {
220
+ const response = await request({
221
+ url: '/finance/cost-centers',
222
+ method: 'GET',
223
+ });
224
+
225
+ return (response.data || []) as CostCenter[];
226
+ },
227
+ placeholderData: [],
228
+ });
229
+
230
+ const handleDelete = async () => {
231
+ if (!costCenterIdToDelete) {
232
+ return;
233
+ }
234
+
235
+ try {
236
+ await request({
237
+ url: `/finance/cost-centers/${costCenterIdToDelete}`,
238
+ method: 'DELETE',
239
+ });
240
+
241
+ await refetch();
242
+ setCostCenterIdToDelete(null);
243
+ showToastHandler?.('success', t('messages.deleteSuccess'));
244
+ } catch {
245
+ showToastHandler?.('error', t('messages.deleteError'));
246
+ }
247
+ };
248
+
249
+ const centers = costCenters || [];
250
+
251
+ return (
252
+ <Page>
253
+ <PageHeader
254
+ title={t('header.title')}
255
+ description={t('header.description')}
256
+ breadcrumbs={[
257
+ { label: t('breadcrumbs.finance'), href: '/finance' },
258
+ {
259
+ label: t('breadcrumbs.administration'),
260
+ href: '/finance/administration',
261
+ },
262
+ { label: t('breadcrumbs.current') },
263
+ ]}
264
+ />
265
+
266
+ <div className="grid gap-4">
267
+ <Card>
268
+ <CardHeader className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
269
+ <div>
270
+ <CardTitle>{t('card.title')}</CardTitle>
271
+ <CardDescription>{t('card.description')}</CardDescription>
272
+ </div>
273
+ <Button
274
+ onClick={() => {
275
+ setEditingCostCenter(null);
276
+ setSheetOpen(true);
277
+ }}
278
+ className="gap-2"
279
+ >
280
+ <Plus className="h-4 w-4" />
281
+ {t('actions.newCostCenter')}
282
+ </Button>
283
+ </CardHeader>
284
+
285
+ <CardContent>
286
+ {centers.length === 0 ? (
287
+ <div className="rounded-md border border-dashed p-8 text-center text-sm text-muted-foreground">
288
+ {t('table.empty')}
289
+ </div>
290
+ ) : (
291
+ <div className="grid gap-3">
292
+ {centers.map((costCenter) => (
293
+ <div
294
+ key={costCenter.id}
295
+ className="flex flex-col gap-3 rounded-md border p-4 sm:flex-row sm:items-center sm:justify-between"
296
+ >
297
+ <div className="flex items-start gap-3">
298
+ <div className="rounded-md bg-muted p-2">
299
+ <Building2 className="h-4 w-4" />
300
+ </div>
301
+ <div>
302
+ <p className="text-sm font-medium">{costCenter.nome}</p>
303
+ <p className="text-xs text-muted-foreground">
304
+ {t('table.code', { code: costCenter.codigo })}
305
+ </p>
306
+ </div>
307
+ </div>
308
+
309
+ <div className="flex items-center gap-2">
310
+ <Badge
311
+ variant={costCenter.ativo ? 'default' : 'secondary'}
312
+ >
313
+ {costCenter.ativo
314
+ ? t('table.status.active')
315
+ : t('table.status.inactive')}
316
+ </Badge>
317
+ <Button
318
+ variant="outline"
319
+ size="icon"
320
+ onClick={() => {
321
+ setEditingCostCenter(costCenter);
322
+ setSheetOpen(true);
323
+ }}
324
+ >
325
+ <Pencil className="h-4 w-4" />
326
+ </Button>
327
+ <Button
328
+ variant="outline"
329
+ size="icon"
330
+ onClick={() => setCostCenterIdToDelete(costCenter.id)}
331
+ disabled={!costCenter.ativo}
332
+ >
333
+ <Trash2 className="h-4 w-4" />
334
+ </Button>
335
+ </div>
336
+ </div>
337
+ ))}
338
+ </div>
339
+ )}
340
+ </CardContent>
341
+ </Card>
342
+ </div>
343
+
344
+ <CentroCustoSheet
345
+ open={sheetOpen}
346
+ onOpenChange={setSheetOpen}
347
+ onSaved={refetch}
348
+ editingCostCenter={editingCostCenter}
349
+ onEditingChange={setEditingCostCenter}
350
+ t={t}
351
+ />
352
+
353
+ <AlertDialog
354
+ open={!!costCenterIdToDelete}
355
+ onOpenChange={(open) => {
356
+ if (!open) {
357
+ setCostCenterIdToDelete(null);
358
+ }
359
+ }}
360
+ >
361
+ <AlertDialogContent>
362
+ <AlertDialogHeader>
363
+ <AlertDialogTitle>{t('deleteDialog.title')}</AlertDialogTitle>
364
+ <AlertDialogDescription>
365
+ {t('deleteDialog.description')}
366
+ </AlertDialogDescription>
367
+ </AlertDialogHeader>
368
+ <AlertDialogFooter>
369
+ <AlertDialogCancel>{t('common.cancel')}</AlertDialogCancel>
370
+ <AlertDialogAction onClick={handleDelete}>
371
+ {t('deleteDialog.confirm')}
372
+ </AlertDialogAction>
373
+ </AlertDialogFooter>
374
+ </AlertDialogContent>
375
+ </AlertDialog>
376
+ </Page>
377
+ );
378
+ }