@hed-hog/finance 0.0.274 → 0.0.276
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 +228 -126
- package/dist/dto/create-bank-reconciliation.dto.d.ts +8 -0
- package/dist/dto/create-bank-reconciliation.dto.d.ts.map +1 -0
- package/dist/dto/create-bank-reconciliation.dto.js +43 -0
- package/dist/dto/create-bank-reconciliation.dto.js.map +1 -0
- package/dist/finance-data.controller.d.ts +2 -0
- package/dist/finance-data.controller.d.ts.map +1 -1
- package/dist/finance-statements.controller.d.ts +42 -0
- package/dist/finance-statements.controller.d.ts.map +1 -1
- package/dist/finance-statements.controller.js +13 -0
- package/dist/finance-statements.controller.js.map +1 -1
- package/dist/finance.service.d.ts +44 -0
- package/dist/finance.service.d.ts.map +1 -1
- package/dist/finance.service.js +98 -9
- package/dist/finance.service.js.map +1 -1
- package/hedhog/data/route.yaml +9 -0
- package/hedhog/frontend/app/_components/person-field-with-create.tsx.ejs +126 -126
- package/hedhog/frontend/app/accounts-payable/approvals/page.tsx.ejs +373 -373
- package/hedhog/frontend/app/accounts-payable/installments/[id]/page.tsx.ejs +1270 -1270
- package/hedhog/frontend/app/accounts-receivable/installments/[id]/page.tsx.ejs +982 -982
- package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +686 -686
- package/hedhog/frontend/app/cash-and-banks/bank-reconciliation/page.tsx.ejs +152 -32
- package/hedhog/frontend/app/cash-and-banks/statements/page.tsx.ejs +986 -986
- package/hedhog/frontend/app/cash-and-banks/transfers/page.tsx.ejs +492 -492
- package/hedhog/frontend/app/page.tsx.ejs +372 -372
- package/hedhog/frontend/app/planning/cash-flow-forecast/page.tsx.ejs +329 -329
- package/hedhog/frontend/app/planning/receivables-calendar/page.tsx.ejs +227 -227
- package/hedhog/frontend/app/planning/scenarios/page.tsx.ejs +408 -408
- package/hedhog/frontend/messages/en.json +15 -5
- package/hedhog/frontend/messages/pt.json +15 -5
- package/package.json +7 -7
- package/src/dto/create-bank-reconciliation.dto.ts +24 -0
- package/src/finance-statements.controller.ts +14 -0
- package/src/finance.module.ts +43 -43
- package/src/finance.service.ts +118 -0
- package/src/index.ts +14 -14
- package/dist/finance.controller.d.ts +0 -276
- package/dist/finance.controller.d.ts.map +0 -1
- package/dist/finance.controller.js +0 -110
- package/dist/finance.controller.js.map +0 -1
package/hedhog/data/route.yaml
CHANGED
|
@@ -430,6 +430,15 @@
|
|
|
430
430
|
- where:
|
|
431
431
|
slug: admin-finance
|
|
432
432
|
|
|
433
|
+
- url: /finance/bank-reconciliations
|
|
434
|
+
method: POST
|
|
435
|
+
relations:
|
|
436
|
+
role:
|
|
437
|
+
- where:
|
|
438
|
+
slug: admin
|
|
439
|
+
- where:
|
|
440
|
+
slug: admin-finance
|
|
441
|
+
|
|
433
442
|
- url: /finance/statements/export
|
|
434
443
|
method: GET
|
|
435
444
|
relations:
|
|
@@ -37,29 +37,29 @@ import {
|
|
|
37
37
|
SheetHeader,
|
|
38
38
|
SheetTitle,
|
|
39
39
|
} from '@/components/ui/sheet';
|
|
40
|
-
import { useApp, useQuery } from '@hed-hog/next-app-provider';
|
|
41
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
42
|
-
import { ChevronsUpDown, Plus, X } from 'lucide-react';
|
|
43
|
-
import { useTranslations } from 'next-intl';
|
|
44
|
-
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
45
|
-
import { FieldValues, Path, UseFormReturn, useForm } from 'react-hook-form';
|
|
46
|
-
import { z } from 'zod';
|
|
40
|
+
import { useApp, useQuery } from '@hed-hog/next-app-provider';
|
|
41
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
42
|
+
import { ChevronsUpDown, Plus, X } from 'lucide-react';
|
|
43
|
+
import { useTranslations } from 'next-intl';
|
|
44
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
45
|
+
import { FieldValues, Path, UseFormReturn, useForm } from 'react-hook-form';
|
|
46
|
+
import { z } from 'zod';
|
|
47
47
|
|
|
48
48
|
type PersonOption = {
|
|
49
49
|
id: number | string;
|
|
50
50
|
name: string;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
type CreatePersonValues = {
|
|
54
|
-
name: string;
|
|
55
|
-
type: 'individual' | 'company';
|
|
56
|
-
email?: string;
|
|
57
|
-
phone?: string;
|
|
58
|
-
document?: string;
|
|
59
|
-
line1?: string;
|
|
60
|
-
city?: string;
|
|
61
|
-
state?: string;
|
|
62
|
-
};
|
|
53
|
+
type CreatePersonValues = {
|
|
54
|
+
name: string;
|
|
55
|
+
type: 'individual' | 'company';
|
|
56
|
+
email?: string;
|
|
57
|
+
phone?: string;
|
|
58
|
+
document?: string;
|
|
59
|
+
line1?: string;
|
|
60
|
+
city?: string;
|
|
61
|
+
state?: string;
|
|
62
|
+
};
|
|
63
63
|
|
|
64
64
|
function CreatePersonSheet({
|
|
65
65
|
open,
|
|
@@ -72,33 +72,33 @@ function CreatePersonSheet({
|
|
|
72
72
|
onCreated: (person: PersonOption) => void;
|
|
73
73
|
entityLabel: string;
|
|
74
74
|
}) {
|
|
75
|
-
const { request, showToastHandler, currentLocaleCode, getSettingValue } =
|
|
76
|
-
useApp();
|
|
77
|
-
const t = useTranslations('finance.PersonFieldWithCreate');
|
|
78
|
-
const allowCompanyRegistration =
|
|
79
|
-
getSettingValue('contact-allow-company-registration') !== false;
|
|
80
|
-
|
|
81
|
-
const createPersonSchema = useMemo(
|
|
82
|
-
() =>
|
|
83
|
-
z.object({
|
|
84
|
-
name: z.string().trim().min(2, 'Nome é obrigatório'),
|
|
85
|
-
type: allowCompanyRegistration
|
|
86
|
-
? z.enum(['individual', 'company'])
|
|
87
|
-
: z.literal('individual'),
|
|
88
|
-
email: z
|
|
89
|
-
.string()
|
|
90
|
-
.trim()
|
|
91
|
-
.email('E-mail inválido')
|
|
92
|
-
.optional()
|
|
93
|
-
.or(z.literal('')),
|
|
94
|
-
phone: z.string().trim().optional(),
|
|
95
|
-
document: z.string().trim().optional(),
|
|
96
|
-
line1: z.string().optional(),
|
|
97
|
-
city: z.string().optional(),
|
|
98
|
-
state: z.string().optional(),
|
|
99
|
-
}),
|
|
100
|
-
[allowCompanyRegistration]
|
|
101
|
-
);
|
|
75
|
+
const { request, showToastHandler, currentLocaleCode, getSettingValue } =
|
|
76
|
+
useApp();
|
|
77
|
+
const t = useTranslations('finance.PersonFieldWithCreate');
|
|
78
|
+
const allowCompanyRegistration =
|
|
79
|
+
getSettingValue('contact-allow-company-registration') !== false;
|
|
80
|
+
|
|
81
|
+
const createPersonSchema = useMemo(
|
|
82
|
+
() =>
|
|
83
|
+
z.object({
|
|
84
|
+
name: z.string().trim().min(2, 'Nome é obrigatório'),
|
|
85
|
+
type: allowCompanyRegistration
|
|
86
|
+
? z.enum(['individual', 'company'])
|
|
87
|
+
: z.literal('individual'),
|
|
88
|
+
email: z
|
|
89
|
+
.string()
|
|
90
|
+
.trim()
|
|
91
|
+
.email('E-mail inválido')
|
|
92
|
+
.optional()
|
|
93
|
+
.or(z.literal('')),
|
|
94
|
+
phone: z.string().trim().optional(),
|
|
95
|
+
document: z.string().trim().optional(),
|
|
96
|
+
line1: z.string().optional(),
|
|
97
|
+
city: z.string().optional(),
|
|
98
|
+
state: z.string().optional(),
|
|
99
|
+
}),
|
|
100
|
+
[allowCompanyRegistration]
|
|
101
|
+
);
|
|
102
102
|
|
|
103
103
|
const form = useForm<CreatePersonValues>({
|
|
104
104
|
resolver: zodResolver(createPersonSchema),
|
|
@@ -114,13 +114,13 @@ function CreatePersonSheet({
|
|
|
114
114
|
},
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
-
const selectedType = allowCompanyRegistration ? form.watch('type') : 'individual';
|
|
118
|
-
|
|
119
|
-
useEffect(() => {
|
|
120
|
-
if (!allowCompanyRegistration) {
|
|
121
|
-
form.setValue('type', 'individual');
|
|
122
|
-
}
|
|
123
|
-
}, [allowCompanyRegistration, form]);
|
|
117
|
+
const selectedType = allowCompanyRegistration ? form.watch('type') : 'individual';
|
|
118
|
+
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
if (!allowCompanyRegistration) {
|
|
121
|
+
form.setValue('type', 'individual');
|
|
122
|
+
}
|
|
123
|
+
}, [allowCompanyRegistration, form]);
|
|
124
124
|
|
|
125
125
|
const { data: contactTypes = [] } = useQuery<any[]>({
|
|
126
126
|
queryKey: ['person-field-contact-types', currentLocaleCode],
|
|
@@ -134,7 +134,7 @@ function CreatePersonSheet({
|
|
|
134
134
|
placeholderData: (old) => old ?? [],
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
const { data: documentTypes = [] } = useQuery<any[]>({
|
|
137
|
+
const { data: documentTypes = [] } = useQuery<any[]>({
|
|
138
138
|
queryKey: ['person-field-document-types', currentLocaleCode],
|
|
139
139
|
queryFn: async () => {
|
|
140
140
|
const response = await request<any>({
|
|
@@ -162,21 +162,21 @@ function CreatePersonSheet({
|
|
|
162
162
|
return found?.document_type_id || documentTypes[0]?.document_type_id;
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
-
const resolveAddressType = () => 'residential';
|
|
166
|
-
|
|
167
|
-
const handleSubmit = async (values: CreatePersonValues) => {
|
|
168
|
-
try {
|
|
169
|
-
const normalizedType = allowCompanyRegistration ? values.type : 'individual';
|
|
170
|
-
|
|
171
|
-
const createResponse = await request<any>({
|
|
172
|
-
url: '/person',
|
|
173
|
-
method: 'POST',
|
|
174
|
-
data: {
|
|
175
|
-
name: values.name,
|
|
176
|
-
type: normalizedType,
|
|
177
|
-
status: 'active',
|
|
178
|
-
},
|
|
179
|
-
});
|
|
165
|
+
const resolveAddressType = () => 'residential';
|
|
166
|
+
|
|
167
|
+
const handleSubmit = async (values: CreatePersonValues) => {
|
|
168
|
+
try {
|
|
169
|
+
const normalizedType = allowCompanyRegistration ? values.type : 'individual';
|
|
170
|
+
|
|
171
|
+
const createResponse = await request<any>({
|
|
172
|
+
url: '/person',
|
|
173
|
+
method: 'POST',
|
|
174
|
+
data: {
|
|
175
|
+
name: values.name,
|
|
176
|
+
type: normalizedType,
|
|
177
|
+
status: 'active',
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
180
|
|
|
181
181
|
const personId = Number(
|
|
182
182
|
createResponse?.data?.id ?? createResponse?.data?.data?.id
|
|
@@ -187,12 +187,12 @@ function CreatePersonSheet({
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
const emailTypeId = resolveContactTypeId('EMAIL', 0);
|
|
190
|
-
const phoneTypeId =
|
|
191
|
-
resolveContactTypeId('PHONE', 1) || resolveContactTypeId('MOBILE', 1);
|
|
192
|
-
const documentTypeId = resolveDocumentTypeId(
|
|
193
|
-
normalizedType === 'individual' ? 'CPF' : 'CNPJ'
|
|
194
|
-
);
|
|
195
|
-
const addressType = resolveAddressType();
|
|
190
|
+
const phoneTypeId =
|
|
191
|
+
resolveContactTypeId('PHONE', 1) || resolveContactTypeId('MOBILE', 1);
|
|
192
|
+
const documentTypeId = resolveDocumentTypeId(
|
|
193
|
+
normalizedType === 'individual' ? 'CPF' : 'CNPJ'
|
|
194
|
+
);
|
|
195
|
+
const addressType = resolveAddressType();
|
|
196
196
|
|
|
197
197
|
const contacts = [
|
|
198
198
|
values.email && emailTypeId
|
|
@@ -220,28 +220,28 @@ function CreatePersonSheet({
|
|
|
220
220
|
]
|
|
221
221
|
: [];
|
|
222
222
|
|
|
223
|
-
const addresses =
|
|
224
|
-
values.line1 && values.city && values.state
|
|
225
|
-
? [
|
|
226
|
-
{
|
|
227
|
-
line1: values.line1.trim(),
|
|
228
|
-
city: values.city.trim(),
|
|
229
|
-
state: values.state.trim(),
|
|
230
|
-
is_primary: true,
|
|
231
|
-
address_type: addressType,
|
|
232
|
-
},
|
|
233
|
-
]
|
|
234
|
-
: [];
|
|
223
|
+
const addresses =
|
|
224
|
+
values.line1 && values.city && values.state
|
|
225
|
+
? [
|
|
226
|
+
{
|
|
227
|
+
line1: values.line1.trim(),
|
|
228
|
+
city: values.city.trim(),
|
|
229
|
+
state: values.state.trim(),
|
|
230
|
+
is_primary: true,
|
|
231
|
+
address_type: addressType,
|
|
232
|
+
},
|
|
233
|
+
]
|
|
234
|
+
: [];
|
|
235
235
|
|
|
236
236
|
await request({
|
|
237
237
|
url: `/person/${personId}`,
|
|
238
238
|
method: 'PATCH',
|
|
239
|
-
data: {
|
|
240
|
-
name: values.name,
|
|
241
|
-
type: normalizedType,
|
|
242
|
-
status: 'active',
|
|
243
|
-
contacts,
|
|
244
|
-
documents,
|
|
239
|
+
data: {
|
|
240
|
+
name: values.name,
|
|
241
|
+
type: normalizedType,
|
|
242
|
+
status: 'active',
|
|
243
|
+
contacts,
|
|
244
|
+
documents,
|
|
245
245
|
addresses,
|
|
246
246
|
},
|
|
247
247
|
});
|
|
@@ -272,14 +272,14 @@ function CreatePersonSheet({
|
|
|
272
272
|
className="w-full overflow-y-auto sm:max-w-xl"
|
|
273
273
|
onCloseAutoFocus={(event) => event.preventDefault()}
|
|
274
274
|
>
|
|
275
|
-
<SheetHeader>
|
|
276
|
-
<SheetTitle>{t('sheet.title', { entityLabel })}</SheetTitle>
|
|
277
|
-
<SheetDescription>
|
|
278
|
-
{allowCompanyRegistration
|
|
279
|
-
? t('sheet.description')
|
|
280
|
-
: t('sheet.descriptionIndividualOnly')}
|
|
281
|
-
</SheetDescription>
|
|
282
|
-
</SheetHeader>
|
|
275
|
+
<SheetHeader>
|
|
276
|
+
<SheetTitle>{t('sheet.title', { entityLabel })}</SheetTitle>
|
|
277
|
+
<SheetDescription>
|
|
278
|
+
{allowCompanyRegistration
|
|
279
|
+
? t('sheet.description')
|
|
280
|
+
: t('sheet.descriptionIndividualOnly')}
|
|
281
|
+
</SheetDescription>
|
|
282
|
+
</SheetHeader>
|
|
283
283
|
|
|
284
284
|
<Form {...form}>
|
|
285
285
|
<div className="space-y-4 p-4">
|
|
@@ -300,33 +300,33 @@ function CreatePersonSheet({
|
|
|
300
300
|
)}
|
|
301
301
|
/>
|
|
302
302
|
|
|
303
|
-
{allowCompanyRegistration ? (
|
|
304
|
-
<FormField
|
|
305
|
-
control={form.control}
|
|
306
|
-
name="type"
|
|
307
|
-
render={({ field }) => (
|
|
308
|
-
<FormItem>
|
|
309
|
-
<FormLabel>{t('fields.type')}</FormLabel>
|
|
310
|
-
<Select value={field.value} onValueChange={field.onChange}>
|
|
311
|
-
<FormControl>
|
|
312
|
-
<SelectTrigger>
|
|
313
|
-
<SelectValue placeholder={t('common.select')} />
|
|
314
|
-
</SelectTrigger>
|
|
315
|
-
</FormControl>
|
|
316
|
-
<SelectContent>
|
|
317
|
-
<SelectItem value="individual">
|
|
318
|
-
{t('types.individual')}
|
|
319
|
-
</SelectItem>
|
|
320
|
-
<SelectItem value="company">
|
|
321
|
-
{t('types.company')}
|
|
322
|
-
</SelectItem>
|
|
323
|
-
</SelectContent>
|
|
324
|
-
</Select>
|
|
325
|
-
<FormMessage />
|
|
326
|
-
</FormItem>
|
|
327
|
-
)}
|
|
328
|
-
/>
|
|
329
|
-
) : null}
|
|
303
|
+
{allowCompanyRegistration ? (
|
|
304
|
+
<FormField
|
|
305
|
+
control={form.control}
|
|
306
|
+
name="type"
|
|
307
|
+
render={({ field }) => (
|
|
308
|
+
<FormItem>
|
|
309
|
+
<FormLabel>{t('fields.type')}</FormLabel>
|
|
310
|
+
<Select value={field.value} onValueChange={field.onChange}>
|
|
311
|
+
<FormControl>
|
|
312
|
+
<SelectTrigger>
|
|
313
|
+
<SelectValue placeholder={t('common.select')} />
|
|
314
|
+
</SelectTrigger>
|
|
315
|
+
</FormControl>
|
|
316
|
+
<SelectContent>
|
|
317
|
+
<SelectItem value="individual">
|
|
318
|
+
{t('types.individual')}
|
|
319
|
+
</SelectItem>
|
|
320
|
+
<SelectItem value="company">
|
|
321
|
+
{t('types.company')}
|
|
322
|
+
</SelectItem>
|
|
323
|
+
</SelectContent>
|
|
324
|
+
</Select>
|
|
325
|
+
<FormMessage />
|
|
326
|
+
</FormItem>
|
|
327
|
+
)}
|
|
328
|
+
/>
|
|
329
|
+
) : null}
|
|
330
330
|
|
|
331
331
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
332
332
|
<FormField
|