@hed-hog/finance 0.0.328 → 0.0.329
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/hedhog/frontend/app/_components/category-picker-field.tsx.ejs +3 -0
- package/hedhog/frontend/app/_components/cost-center-picker-field.tsx.ejs +3 -0
- package/hedhog/frontend/app/_components/finance-entity-field-with-create.tsx.ejs +9 -4
- package/hedhog/frontend/app/_components/finance-picker.tsx.ejs +242 -0
- package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +12 -10
- package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +12 -10
- package/package.json +6 -6
|
@@ -6,14 +6,14 @@ import { useTranslations } from 'next-intl';
|
|
|
6
6
|
import { useMemo, useState } from 'react';
|
|
7
7
|
import { FieldValues, Path, UseFormReturn } from 'react-hook-form';
|
|
8
8
|
|
|
9
|
-
type FinanceCategory = {
|
|
9
|
+
export type FinanceCategory = {
|
|
10
10
|
id: number | string;
|
|
11
11
|
codigo?: string;
|
|
12
12
|
nome: string;
|
|
13
13
|
natureza?: string;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
type CostCenter = {
|
|
16
|
+
export type CostCenter = {
|
|
17
17
|
id: number | string;
|
|
18
18
|
codigo?: string;
|
|
19
19
|
nome: string;
|
|
@@ -44,7 +44,7 @@ const extractCreatedId = (
|
|
|
44
44
|
return String(id);
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
export function
|
|
47
|
+
export function CategoryPickerField<TFieldValues extends FieldValues>({
|
|
48
48
|
form,
|
|
49
49
|
name,
|
|
50
50
|
label,
|
|
@@ -144,7 +144,7 @@ export function CategoryFieldWithCreate<TFieldValues extends FieldValues>({
|
|
|
144
144
|
);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
export function
|
|
147
|
+
export function CostCenterPickerField<TFieldValues extends FieldValues>({
|
|
148
148
|
form,
|
|
149
149
|
name,
|
|
150
150
|
label,
|
|
@@ -235,3 +235,8 @@ export function CostCenterFieldWithCreate<TFieldValues extends FieldValues>({
|
|
|
235
235
|
/>
|
|
236
236
|
);
|
|
237
237
|
}
|
|
238
|
+
|
|
239
|
+
export {
|
|
240
|
+
CategoryPickerField as CategoryFieldWithCreate,
|
|
241
|
+
CostCenterPickerField as CostCenterFieldWithCreate,
|
|
242
|
+
};
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { EntityPicker } from '@/components/ui/entity-picker';
|
|
4
|
+
import { useApp } from '@hed-hog/next-app-provider';
|
|
5
|
+
import { useTranslations } from 'next-intl';
|
|
6
|
+
import { useMemo, useState } from 'react';
|
|
7
|
+
import { FieldValues, Path, UseFormReturn } from 'react-hook-form';
|
|
8
|
+
|
|
9
|
+
export type FinanceCategory = {
|
|
10
|
+
id: number | string;
|
|
11
|
+
codigo?: string;
|
|
12
|
+
nome: string;
|
|
13
|
+
natureza?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type CostCenter = {
|
|
17
|
+
id: number | string;
|
|
18
|
+
codigo?: string;
|
|
19
|
+
nome: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type CreatedEntityResponse = {
|
|
23
|
+
id?: number | string | null;
|
|
24
|
+
data?: {
|
|
25
|
+
id?: number | string | null;
|
|
26
|
+
} | null;
|
|
27
|
+
category_id?: number | string | null;
|
|
28
|
+
cost_center_id?: number | string | null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const extractCreatedId = (
|
|
32
|
+
payload: CreatedEntityResponse | null | undefined
|
|
33
|
+
): string | null => {
|
|
34
|
+
const id =
|
|
35
|
+
payload?.id ??
|
|
36
|
+
payload?.data?.id ??
|
|
37
|
+
payload?.category_id ??
|
|
38
|
+
payload?.cost_center_id;
|
|
39
|
+
|
|
40
|
+
if (id === undefined || id === null || id === '') {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return String(id);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export function CategoryPickerField<TFieldValues extends FieldValues>({
|
|
48
|
+
form,
|
|
49
|
+
name,
|
|
50
|
+
label,
|
|
51
|
+
selectPlaceholder,
|
|
52
|
+
categories,
|
|
53
|
+
categoryKind,
|
|
54
|
+
onCreated,
|
|
55
|
+
}: {
|
|
56
|
+
form: UseFormReturn<TFieldValues>;
|
|
57
|
+
name: Path<TFieldValues>;
|
|
58
|
+
label: string;
|
|
59
|
+
selectPlaceholder: string;
|
|
60
|
+
categories: FinanceCategory[];
|
|
61
|
+
categoryKind: 'receita' | 'despesa';
|
|
62
|
+
onCreated?: () => Promise<unknown> | void;
|
|
63
|
+
}) {
|
|
64
|
+
const { request, showToastHandler } = useApp();
|
|
65
|
+
const t = useTranslations('finance.FinanceEntityFieldWithCreate');
|
|
66
|
+
const [localCategories, setLocalCategories] = useState<FinanceCategory[]>([]);
|
|
67
|
+
|
|
68
|
+
const filteredCategories = useMemo(() => {
|
|
69
|
+
const merged = [...(categories || []), ...localCategories];
|
|
70
|
+
const uniqueById = merged.filter(
|
|
71
|
+
(item, index, arr) =>
|
|
72
|
+
arr.findIndex(
|
|
73
|
+
(candidate) => String(candidate.id) === String(item.id)
|
|
74
|
+
) === index
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return uniqueById.filter((item) => item.natureza === categoryKind);
|
|
78
|
+
}, [categories, categoryKind, localCategories]);
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<EntityPicker<FinanceCategory, TFieldValues>
|
|
82
|
+
form={form}
|
|
83
|
+
name={name}
|
|
84
|
+
label={label}
|
|
85
|
+
placeholder={selectPlaceholder}
|
|
86
|
+
searchPlaceholder={selectPlaceholder}
|
|
87
|
+
emptySelectionLabel={selectPlaceholder}
|
|
88
|
+
clearable
|
|
89
|
+
allowEmptySelection
|
|
90
|
+
options={filteredCategories}
|
|
91
|
+
createActionLabel={t('actions.createCategoryAria')}
|
|
92
|
+
createTitle={t('categorySheet.title')}
|
|
93
|
+
createDescription={t('categorySheet.description')}
|
|
94
|
+
createFields={[
|
|
95
|
+
{
|
|
96
|
+
name: 'nome',
|
|
97
|
+
label: t('fields.name'),
|
|
98
|
+
placeholder: t('categorySheet.namePlaceholder'),
|
|
99
|
+
required: true,
|
|
100
|
+
},
|
|
101
|
+
]}
|
|
102
|
+
getOptionValue={(category) => String(category.id)}
|
|
103
|
+
getOptionLabel={(category) =>
|
|
104
|
+
category.codigo
|
|
105
|
+
? `${category.codigo} - ${category.nome}`
|
|
106
|
+
: category.nome
|
|
107
|
+
}
|
|
108
|
+
onCreate={async (values) => {
|
|
109
|
+
try {
|
|
110
|
+
const createdName = values.nome?.trim() ?? '';
|
|
111
|
+
const response = await request<CreatedEntityResponse>({
|
|
112
|
+
url: '/finance/categories',
|
|
113
|
+
method: 'POST',
|
|
114
|
+
data: {
|
|
115
|
+
name: createdName,
|
|
116
|
+
kind: categoryKind,
|
|
117
|
+
parent_id: null,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const createdId = extractCreatedId(response?.data);
|
|
122
|
+
const createdCategory = createdId
|
|
123
|
+
? {
|
|
124
|
+
id: String(createdId),
|
|
125
|
+
nome: createdName,
|
|
126
|
+
natureza: categoryKind,
|
|
127
|
+
}
|
|
128
|
+
: null;
|
|
129
|
+
|
|
130
|
+
if (createdCategory) {
|
|
131
|
+
setLocalCategories((prev) => [...prev, createdCategory]);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
await onCreated?.();
|
|
135
|
+
showToastHandler?.('success', t('messages.categoryCreateSuccess'));
|
|
136
|
+
|
|
137
|
+
return createdCategory;
|
|
138
|
+
} catch {
|
|
139
|
+
showToastHandler?.('error', t('messages.categoryCreateError'));
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function CostCenterPickerField<TFieldValues extends FieldValues>({
|
|
148
|
+
form,
|
|
149
|
+
name,
|
|
150
|
+
label,
|
|
151
|
+
selectPlaceholder,
|
|
152
|
+
costCenters,
|
|
153
|
+
onCreated,
|
|
154
|
+
}: {
|
|
155
|
+
form: UseFormReturn<TFieldValues>;
|
|
156
|
+
name: Path<TFieldValues>;
|
|
157
|
+
label: string;
|
|
158
|
+
selectPlaceholder: string;
|
|
159
|
+
costCenters: CostCenter[];
|
|
160
|
+
onCreated?: () => Promise<unknown> | void;
|
|
161
|
+
}) {
|
|
162
|
+
const { request, showToastHandler } = useApp();
|
|
163
|
+
const t = useTranslations('finance.FinanceEntityFieldWithCreate');
|
|
164
|
+
const [localCostCenters, setLocalCostCenters] = useState<CostCenter[]>([]);
|
|
165
|
+
|
|
166
|
+
const mergedCostCenters = useMemo(() => {
|
|
167
|
+
const merged = [...(costCenters || []), ...localCostCenters];
|
|
168
|
+
|
|
169
|
+
return merged.filter(
|
|
170
|
+
(item, index, arr) =>
|
|
171
|
+
arr.findIndex(
|
|
172
|
+
(candidate) => String(candidate.id) === String(item.id)
|
|
173
|
+
) === index
|
|
174
|
+
);
|
|
175
|
+
}, [costCenters, localCostCenters]);
|
|
176
|
+
|
|
177
|
+
return (
|
|
178
|
+
<EntityPicker<CostCenter, TFieldValues>
|
|
179
|
+
form={form}
|
|
180
|
+
name={name}
|
|
181
|
+
label={label}
|
|
182
|
+
placeholder={selectPlaceholder}
|
|
183
|
+
searchPlaceholder={selectPlaceholder}
|
|
184
|
+
emptySelectionLabel={selectPlaceholder}
|
|
185
|
+
clearable
|
|
186
|
+
allowEmptySelection
|
|
187
|
+
options={mergedCostCenters}
|
|
188
|
+
createActionLabel={t('actions.createCostCenterAria')}
|
|
189
|
+
createTitle={t('costCenterSheet.title')}
|
|
190
|
+
createDescription={t('costCenterSheet.description')}
|
|
191
|
+
createFields={[
|
|
192
|
+
{
|
|
193
|
+
name: 'nome',
|
|
194
|
+
label: t('fields.name'),
|
|
195
|
+
placeholder: t('costCenterSheet.namePlaceholder'),
|
|
196
|
+
required: true,
|
|
197
|
+
},
|
|
198
|
+
]}
|
|
199
|
+
getOptionValue={(center) => String(center.id)}
|
|
200
|
+
getOptionLabel={(center) =>
|
|
201
|
+
center.codigo ? `${center.codigo} - ${center.nome}` : center.nome
|
|
202
|
+
}
|
|
203
|
+
onCreate={async (values) => {
|
|
204
|
+
try {
|
|
205
|
+
const createdName = values.nome?.trim() ?? '';
|
|
206
|
+
const response = await request<CreatedEntityResponse>({
|
|
207
|
+
url: '/finance/cost-centers',
|
|
208
|
+
method: 'POST',
|
|
209
|
+
data: {
|
|
210
|
+
name: createdName,
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const createdId = extractCreatedId(response?.data);
|
|
215
|
+
const createdCostCenter = createdId
|
|
216
|
+
? {
|
|
217
|
+
id: String(createdId),
|
|
218
|
+
nome: createdName,
|
|
219
|
+
}
|
|
220
|
+
: null;
|
|
221
|
+
|
|
222
|
+
if (createdCostCenter) {
|
|
223
|
+
setLocalCostCenters((prev) => [...prev, createdCostCenter]);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
await onCreated?.();
|
|
227
|
+
showToastHandler?.('success', t('messages.costCenterCreateSuccess'));
|
|
228
|
+
|
|
229
|
+
return createdCostCenter;
|
|
230
|
+
} catch {
|
|
231
|
+
showToastHandler?.('error', t('messages.costCenterCreateError'));
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}}
|
|
235
|
+
/>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export {
|
|
240
|
+
CategoryPickerField as CategoryFieldWithCreate,
|
|
241
|
+
CostCenterPickerField as CostCenterFieldWithCreate,
|
|
242
|
+
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { PersonPickerField } from '@/app/(app)/(libraries)/contact/_components/person-picker';
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
CategoryPickerField,
|
|
6
|
+
} from '@/app/(app)/(libraries)/finance/_components/category-picker-field';
|
|
7
|
+
import {
|
|
8
|
+
CostCenterPickerField,
|
|
9
|
+
} from '@/app/(app)/(libraries)/finance/_components/cost-center-picker-field';
|
|
8
10
|
import {
|
|
9
11
|
FinancePageSection,
|
|
10
12
|
FinanceSheetBody,
|
|
@@ -963,7 +965,7 @@ function NovoTituloSheet({
|
|
|
963
965
|
/>
|
|
964
966
|
</div>
|
|
965
967
|
|
|
966
|
-
<
|
|
968
|
+
<PersonPickerField
|
|
967
969
|
form={form}
|
|
968
970
|
name="fornecedorId"
|
|
969
971
|
label={t('fields.supplier')}
|
|
@@ -1216,7 +1218,7 @@ function NovoTituloSheet({
|
|
|
1216
1218
|
description={t('sections.classification.description')}
|
|
1217
1219
|
>
|
|
1218
1220
|
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
1219
|
-
<
|
|
1221
|
+
<CategoryPickerField
|
|
1220
1222
|
form={form}
|
|
1221
1223
|
name="categoriaId"
|
|
1222
1224
|
label={t('fields.category')}
|
|
@@ -1226,7 +1228,7 @@ function NovoTituloSheet({
|
|
|
1226
1228
|
onCreated={onCategoriesUpdated}
|
|
1227
1229
|
/>
|
|
1228
1230
|
|
|
1229
|
-
<
|
|
1231
|
+
<CostCenterPickerField
|
|
1230
1232
|
form={form}
|
|
1231
1233
|
name="centroCustoId"
|
|
1232
1234
|
label={t('fields.costCenter')}
|
|
@@ -2079,7 +2081,7 @@ function EditarTituloSheet({
|
|
|
2079
2081
|
/>
|
|
2080
2082
|
</div>
|
|
2081
2083
|
|
|
2082
|
-
<
|
|
2084
|
+
<PersonPickerField
|
|
2083
2085
|
form={form}
|
|
2084
2086
|
name="fornecedorId"
|
|
2085
2087
|
label={t('fields.supplier')}
|
|
@@ -2333,7 +2335,7 @@ function EditarTituloSheet({
|
|
|
2333
2335
|
description={t('sections.classification.description')}
|
|
2334
2336
|
>
|
|
2335
2337
|
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
2336
|
-
<
|
|
2338
|
+
<CategoryPickerField
|
|
2337
2339
|
form={form}
|
|
2338
2340
|
name="categoriaId"
|
|
2339
2341
|
label={t('fields.category')}
|
|
@@ -2343,7 +2345,7 @@ function EditarTituloSheet({
|
|
|
2343
2345
|
onCreated={onCategoriesUpdated}
|
|
2344
2346
|
/>
|
|
2345
2347
|
|
|
2346
|
-
<
|
|
2348
|
+
<CostCenterPickerField
|
|
2347
2349
|
form={form}
|
|
2348
2350
|
name="centroCustoId"
|
|
2349
2351
|
label={t('fields.costCenter')}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { PersonPickerField } from '@/app/(app)/(libraries)/contact/_components/person-picker';
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
CategoryPickerField,
|
|
6
|
+
} from '@/app/(app)/(libraries)/finance/_components/category-picker-field';
|
|
7
|
+
import {
|
|
8
|
+
CostCenterPickerField,
|
|
9
|
+
} from '@/app/(app)/(libraries)/finance/_components/cost-center-picker-field';
|
|
8
10
|
import {
|
|
9
11
|
FinancePageSection,
|
|
10
12
|
FinanceSheetBody,
|
|
@@ -943,7 +945,7 @@ function NovoTituloSheet({
|
|
|
943
945
|
/>
|
|
944
946
|
</div>
|
|
945
947
|
|
|
946
|
-
<
|
|
948
|
+
<PersonPickerField
|
|
947
949
|
form={form}
|
|
948
950
|
name="clienteId"
|
|
949
951
|
label={t('fields.client')}
|
|
@@ -1194,7 +1196,7 @@ function NovoTituloSheet({
|
|
|
1194
1196
|
description={t('sections.classification.description')}
|
|
1195
1197
|
>
|
|
1196
1198
|
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
1197
|
-
<
|
|
1199
|
+
<CategoryPickerField
|
|
1198
1200
|
form={form}
|
|
1199
1201
|
name="categoriaId"
|
|
1200
1202
|
label={t('fields.category')}
|
|
@@ -1204,7 +1206,7 @@ function NovoTituloSheet({
|
|
|
1204
1206
|
onCreated={onOptionsUpdated}
|
|
1205
1207
|
/>
|
|
1206
1208
|
|
|
1207
|
-
<
|
|
1209
|
+
<CostCenterPickerField
|
|
1208
1210
|
form={form}
|
|
1209
1211
|
name="centroCustoId"
|
|
1210
1212
|
label={t('fields.costCenter')}
|
|
@@ -2049,7 +2051,7 @@ function EditarTituloSheet({
|
|
|
2049
2051
|
/>
|
|
2050
2052
|
</div>
|
|
2051
2053
|
|
|
2052
|
-
<
|
|
2054
|
+
<PersonPickerField
|
|
2053
2055
|
form={form}
|
|
2054
2056
|
name="clienteId"
|
|
2055
2057
|
label={t('fields.client')}
|
|
@@ -2302,7 +2304,7 @@ function EditarTituloSheet({
|
|
|
2302
2304
|
description={t('sections.classification.description')}
|
|
2303
2305
|
>
|
|
2304
2306
|
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
2305
|
-
<
|
|
2307
|
+
<CategoryPickerField
|
|
2306
2308
|
form={form}
|
|
2307
2309
|
name="categoriaId"
|
|
2308
2310
|
label={t('fields.category')}
|
|
@@ -2312,7 +2314,7 @@ function EditarTituloSheet({
|
|
|
2312
2314
|
onCreated={onOptionsUpdated}
|
|
2313
2315
|
/>
|
|
2314
2316
|
|
|
2315
|
-
<
|
|
2317
|
+
<CostCenterPickerField
|
|
2316
2318
|
form={form}
|
|
2317
2319
|
name="centroCustoId"
|
|
2318
2320
|
label={t('fields.costCenter')}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/finance",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.329",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
"@nestjs/jwt": "^11",
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
12
|
"@hed-hog/api": "0.0.8",
|
|
13
|
-
"@hed-hog/api-prisma": "0.0.6",
|
|
14
13
|
"@hed-hog/api-locale": "0.0.14",
|
|
15
|
-
"@hed-hog/contact": "0.0.
|
|
16
|
-
"@hed-hog/
|
|
14
|
+
"@hed-hog/contact": "0.0.329",
|
|
15
|
+
"@hed-hog/tag": "0.0.329",
|
|
16
|
+
"@hed-hog/core": "0.0.329",
|
|
17
|
+
"@hed-hog/api-prisma": "0.0.6",
|
|
17
18
|
"@hed-hog/api-types": "0.0.1",
|
|
18
|
-
"@hed-hog/
|
|
19
|
-
"@hed-hog/core": "0.0.328"
|
|
19
|
+
"@hed-hog/api-pagination": "0.0.7"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|