@hed-hog/finance 0.0.237 → 0.0.238
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/dist/dto/create-finance-tag.dto.d.ts +5 -0
- package/dist/dto/create-finance-tag.dto.d.ts.map +1 -0
- package/dist/dto/create-finance-tag.dto.js +29 -0
- package/dist/dto/create-finance-tag.dto.js.map +1 -0
- package/dist/dto/update-installment-tags.dto.d.ts +4 -0
- package/dist/dto/update-installment-tags.dto.d.ts.map +1 -0
- package/dist/dto/update-installment-tags.dto.js +27 -0
- package/dist/dto/update-installment-tags.dto.js.map +1 -0
- package/dist/finance-data.controller.d.ts +4 -0
- package/dist/finance-data.controller.d.ts.map +1 -1
- package/dist/finance-installments.controller.d.ts +81 -0
- package/dist/finance-installments.controller.d.ts.map +1 -1
- package/dist/finance-installments.controller.js +36 -0
- package/dist/finance-installments.controller.js.map +1 -1
- package/dist/finance.service.d.ts +86 -0
- package/dist/finance.service.d.ts.map +1 -1
- package/dist/finance.service.js +185 -2
- package/dist/finance.service.js.map +1 -1
- package/hedhog/data/route.yaml +27 -0
- package/hedhog/frontend/app/_lib/use-finance-data.ts.ejs +2 -0
- package/hedhog/frontend/app/accounts-payable/installments/[id]/page.tsx.ejs +249 -78
- package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +41 -3
- package/hedhog/frontend/app/accounts-receivable/installments/[id]/page.tsx.ejs +202 -20
- package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +40 -1
- package/hedhog/frontend/messages/en.json +38 -0
- package/hedhog/frontend/messages/pt.json +38 -0
- package/package.json +5 -5
- package/src/dto/create-finance-tag.dto.ts +15 -0
- package/src/dto/update-installment-tags.dto.ts +12 -0
- package/src/finance-installments.controller.ts +43 -9
- package/src/finance.service.ts +255 -12
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
TableRow,
|
|
29
29
|
} from '@/components/ui/table';
|
|
30
30
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
|
31
|
+
import { TagSelectorSheet } from '@/components/ui/tag-selector-sheet';
|
|
32
|
+
import { useApp } from '@hed-hog/next-app-provider';
|
|
31
33
|
import {
|
|
32
34
|
ArrowLeft,
|
|
33
35
|
Download,
|
|
@@ -39,11 +41,13 @@ import {
|
|
|
39
41
|
import { useTranslations } from 'next-intl';
|
|
40
42
|
import Link from 'next/link';
|
|
41
43
|
import { useParams } from 'next/navigation';
|
|
44
|
+
import { useEffect, useState } from 'react';
|
|
42
45
|
import { formatarData } from '../../../_lib/formatters';
|
|
43
46
|
import { useFinanceData } from '../../../_lib/use-finance-data';
|
|
44
47
|
|
|
45
48
|
export default function TituloReceberDetalhePage() {
|
|
46
49
|
const t = useTranslations('finance.ReceivableInstallmentDetailPage');
|
|
50
|
+
const { request, showToastHandler } = useApp();
|
|
47
51
|
const params = useParams<{ id: string }>();
|
|
48
52
|
const id = params?.id;
|
|
49
53
|
const { data } = useFinanceData();
|
|
@@ -59,6 +63,22 @@ export default function TituloReceberDetalhePage() {
|
|
|
59
63
|
|
|
60
64
|
const titulo = titulosReceber.find((t) => t.id === id);
|
|
61
65
|
|
|
66
|
+
const [availableTags, setAvailableTags] = useState<any[]>([]);
|
|
67
|
+
const [selectedTagIds, setSelectedTagIds] = useState<string[]>([]);
|
|
68
|
+
const [isCreatingTag, setIsCreatingTag] = useState(false);
|
|
69
|
+
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
setAvailableTags(tags || []);
|
|
72
|
+
}, [tags]);
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (!titulo) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
setSelectedTagIds(Array.isArray(titulo.tags) ? titulo.tags : []);
|
|
80
|
+
}, [titulo]);
|
|
81
|
+
|
|
62
82
|
const canalBadge = {
|
|
63
83
|
boleto: {
|
|
64
84
|
label: t('channels.boleto'),
|
|
@@ -108,9 +128,21 @@ export default function TituloReceberDetalhePage() {
|
|
|
108
128
|
const cliente = getPessoaById(titulo.clienteId);
|
|
109
129
|
const categoria = getCategoriaById(titulo.categoriaId);
|
|
110
130
|
const centroCusto = getCentroCustoById(titulo.centroCustoId);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
.
|
|
131
|
+
|
|
132
|
+
const tagOptions = availableTags.map((tag) => ({
|
|
133
|
+
id: String(tag.id),
|
|
134
|
+
name: String(tag.nome || ''),
|
|
135
|
+
color: tag.cor,
|
|
136
|
+
usageCount:
|
|
137
|
+
typeof tag.usageCount === 'number'
|
|
138
|
+
? tag.usageCount
|
|
139
|
+
: typeof tag.usoCount === 'number'
|
|
140
|
+
? tag.usoCount
|
|
141
|
+
: typeof tag.count === 'number'
|
|
142
|
+
? tag.count
|
|
143
|
+
: undefined,
|
|
144
|
+
}));
|
|
145
|
+
|
|
114
146
|
const canal =
|
|
115
147
|
canalBadge[titulo.canal as keyof typeof canalBadge] ||
|
|
116
148
|
canalBadge.transferencia;
|
|
@@ -129,6 +161,131 @@ export default function TituloReceberDetalhePage() {
|
|
|
129
161
|
depois: log.depois,
|
|
130
162
|
}));
|
|
131
163
|
|
|
164
|
+
const attachmentDetails = Array.isArray(titulo.anexosDetalhes)
|
|
165
|
+
? titulo.anexosDetalhes
|
|
166
|
+
: (titulo.anexos || []).map((nome: string) => ({ nome }));
|
|
167
|
+
|
|
168
|
+
const handleOpenAttachment = async (fileId?: string) => {
|
|
169
|
+
if (!fileId) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const response = await request<{ url?: string }>({
|
|
174
|
+
url: `/file/open/${fileId}`,
|
|
175
|
+
method: 'PUT',
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
const url = response?.data?.url;
|
|
179
|
+
if (!url) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const tTagSelector = (key: string, fallback: string) => {
|
|
187
|
+
const fullKey = `tagSelector.${key}`;
|
|
188
|
+
return t.has(fullKey) ? t(fullKey) : fallback;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const toTagSlug = (value: string) => {
|
|
192
|
+
return value
|
|
193
|
+
.normalize('NFD')
|
|
194
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
195
|
+
.toLowerCase()
|
|
196
|
+
.trim()
|
|
197
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
198
|
+
.replace(/(^-|-$)+/g, '');
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const handleCreateTag = async (name: string) => {
|
|
202
|
+
const slug = toTagSlug(name);
|
|
203
|
+
|
|
204
|
+
if (!slug) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
setIsCreatingTag(true);
|
|
209
|
+
try {
|
|
210
|
+
const response = await request<{
|
|
211
|
+
id?: string | number;
|
|
212
|
+
nome?: string;
|
|
213
|
+
cor?: string;
|
|
214
|
+
}>({
|
|
215
|
+
url: '/finance/tags',
|
|
216
|
+
method: 'POST',
|
|
217
|
+
data: {
|
|
218
|
+
name: slug,
|
|
219
|
+
color: '#000000',
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const created = response?.data;
|
|
224
|
+
const newTag = {
|
|
225
|
+
id: String(created?.id || `temp-${Date.now()}`),
|
|
226
|
+
nome: created?.nome || slug,
|
|
227
|
+
cor: created?.cor || '#000000',
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
setAvailableTags((current) => {
|
|
231
|
+
if (current.some((tag) => String(tag.id) === newTag.id)) {
|
|
232
|
+
return current;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return [...current, newTag];
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
showToastHandler?.(
|
|
239
|
+
'success',
|
|
240
|
+
tTagSelector('messages.createSuccess', 'Tag criada com sucesso')
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
id: newTag.id,
|
|
245
|
+
name: newTag.nome,
|
|
246
|
+
color: newTag.cor,
|
|
247
|
+
};
|
|
248
|
+
} catch {
|
|
249
|
+
showToastHandler?.(
|
|
250
|
+
'error',
|
|
251
|
+
tTagSelector('messages.createError', 'Não foi possível criar a tag')
|
|
252
|
+
);
|
|
253
|
+
return null;
|
|
254
|
+
} finally {
|
|
255
|
+
setIsCreatingTag(false);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const handleChangeTags = async (nextTagIds: string[]) => {
|
|
260
|
+
if (!titulo?.id) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
const response = await request<{ tags?: string[] }>({
|
|
266
|
+
url: `/finance/accounts-receivable/installments/${titulo.id}/tags`,
|
|
267
|
+
method: 'PATCH',
|
|
268
|
+
data: {
|
|
269
|
+
tag_ids: nextTagIds.map((tagId) => Number(tagId)),
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
if (Array.isArray(response?.data?.tags)) {
|
|
274
|
+
setSelectedTagIds(response.data.tags);
|
|
275
|
+
} else {
|
|
276
|
+
setSelectedTagIds(nextTagIds);
|
|
277
|
+
}
|
|
278
|
+
} catch {
|
|
279
|
+
showToastHandler?.(
|
|
280
|
+
'error',
|
|
281
|
+
tTagSelector(
|
|
282
|
+
'messages.updateError',
|
|
283
|
+
'Não foi possível atualizar as tags'
|
|
284
|
+
)
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
|
|
132
289
|
return (
|
|
133
290
|
<Page>
|
|
134
291
|
<div className="flex items-center gap-4">
|
|
@@ -245,20 +402,44 @@ export default function TituloReceberDetalhePage() {
|
|
|
245
402
|
<dt className="text-sm font-medium text-muted-foreground">
|
|
246
403
|
{t('documentData.tags')}
|
|
247
404
|
</dt>
|
|
248
|
-
<dd className="mt-1
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
405
|
+
<dd className="mt-1">
|
|
406
|
+
<TagSelectorSheet
|
|
407
|
+
selectedTagIds={selectedTagIds}
|
|
408
|
+
tags={tagOptions}
|
|
409
|
+
onChange={handleChangeTags}
|
|
410
|
+
onCreateTag={handleCreateTag}
|
|
411
|
+
disabled={isCreatingTag}
|
|
412
|
+
emptyText={tTagSelector('noTags', 'Sem tags')}
|
|
413
|
+
labels={{
|
|
414
|
+
addTag: tTagSelector('addTag', 'Adicionar tag'),
|
|
415
|
+
sheetTitle: tTagSelector('sheetTitle', 'Gerenciar tags'),
|
|
416
|
+
sheetDescription: tTagSelector(
|
|
417
|
+
'sheetDescription',
|
|
418
|
+
'Selecione tags existentes ou crie uma nova.'
|
|
419
|
+
),
|
|
420
|
+
createLabel: tTagSelector('createLabel', 'Nova tag'),
|
|
421
|
+
createPlaceholder: tTagSelector(
|
|
422
|
+
'createPlaceholder',
|
|
423
|
+
'Digite o nome da tag'
|
|
424
|
+
),
|
|
425
|
+
createAction: tTagSelector('createAction', 'Criar tag'),
|
|
426
|
+
popularTitle: tTagSelector(
|
|
427
|
+
'popularTitle',
|
|
428
|
+
'Tags mais usadas'
|
|
429
|
+
),
|
|
430
|
+
selectedTitle: tTagSelector(
|
|
431
|
+
'selectedTitle',
|
|
432
|
+
'Tags selecionadas'
|
|
433
|
+
),
|
|
434
|
+
noTags: tTagSelector('noTags', 'Sem tags'),
|
|
435
|
+
cancel: tTagSelector('cancel', 'Cancelar'),
|
|
436
|
+
apply: tTagSelector('apply', 'Aplicar'),
|
|
437
|
+
removeTagAria: (tagName: string) =>
|
|
438
|
+
t.has('tagSelector.removeTagAria')
|
|
439
|
+
? t('tagSelector.removeTagAria', { tag: tagName })
|
|
440
|
+
: `Remover tag ${tagName}`,
|
|
441
|
+
}}
|
|
442
|
+
/>
|
|
262
443
|
</dd>
|
|
263
444
|
</div>
|
|
264
445
|
</dl>
|
|
@@ -271,16 +452,17 @@ export default function TituloReceberDetalhePage() {
|
|
|
271
452
|
<CardDescription>{t('attachments.description')}</CardDescription>
|
|
272
453
|
</CardHeader>
|
|
273
454
|
<CardContent>
|
|
274
|
-
{
|
|
455
|
+
{attachmentDetails.length > 0 ? (
|
|
275
456
|
<ul className="space-y-2">
|
|
276
|
-
{
|
|
457
|
+
{attachmentDetails.map((anexo: any, i: number) => (
|
|
277
458
|
<li key={i}>
|
|
278
459
|
<Button
|
|
279
460
|
variant="ghost"
|
|
280
461
|
className="h-auto w-full justify-start p-2"
|
|
462
|
+
onClick={() => void handleOpenAttachment(anexo?.id)}
|
|
281
463
|
>
|
|
282
464
|
<FileText className="mr-2 h-4 w-4" />
|
|
283
|
-
{anexo}
|
|
465
|
+
{anexo?.nome}
|
|
284
466
|
</Button>
|
|
285
467
|
</li>
|
|
286
468
|
))}
|
|
@@ -638,6 +638,7 @@ function NovoTituloSheet({
|
|
|
638
638
|
|
|
639
639
|
export default function TitulosReceberPage() {
|
|
640
640
|
const t = useTranslations('finance.ReceivableInstallmentsPage');
|
|
641
|
+
const { request, showToastHandler } = useApp();
|
|
641
642
|
const { data, refetch } = useFinanceData();
|
|
642
643
|
const { titulosReceber, pessoas, categorias, centrosCusto } = data;
|
|
643
644
|
|
|
@@ -674,6 +675,29 @@ export default function TitulosReceberPage() {
|
|
|
674
675
|
return matchesSearch && matchesStatus;
|
|
675
676
|
});
|
|
676
677
|
|
|
678
|
+
const handleOpenAttachment = async (fileId?: string) => {
|
|
679
|
+
if (!fileId) {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
try {
|
|
684
|
+
const response = await request<{ url?: string }>({
|
|
685
|
+
url: `/file/open/${fileId}`,
|
|
686
|
+
method: 'PUT',
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
const url = response?.data?.url;
|
|
690
|
+
if (!url) {
|
|
691
|
+
showToastHandler?.('error', 'Não foi possível abrir o anexo');
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
window.open(url, '_blank', 'noopener,noreferrer');
|
|
696
|
+
} catch {
|
|
697
|
+
showToastHandler?.('error', 'Não foi possível abrir o anexo');
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
|
|
677
701
|
return (
|
|
678
702
|
<Page>
|
|
679
703
|
<PageHeader
|
|
@@ -754,7 +778,22 @@ export default function TitulosReceberPage() {
|
|
|
754
778
|
{titulo.documento}
|
|
755
779
|
</Link>
|
|
756
780
|
{titulo.anexos.length > 0 && (
|
|
757
|
-
<
|
|
781
|
+
<Button
|
|
782
|
+
type="button"
|
|
783
|
+
variant="ghost"
|
|
784
|
+
size="icon"
|
|
785
|
+
className="ml-1 inline-flex h-5 w-5 align-middle text-muted-foreground"
|
|
786
|
+
onClick={(event) => {
|
|
787
|
+
event.preventDefault();
|
|
788
|
+
event.stopPropagation();
|
|
789
|
+
const firstAttachmentId =
|
|
790
|
+
titulo.anexosDetalhes?.[0]?.id;
|
|
791
|
+
void handleOpenAttachment(firstAttachmentId);
|
|
792
|
+
}}
|
|
793
|
+
aria-label="Abrir anexo"
|
|
794
|
+
>
|
|
795
|
+
<Paperclip className="h-3 w-3" />
|
|
796
|
+
</Button>
|
|
758
797
|
)}
|
|
759
798
|
</TableCell>
|
|
760
799
|
<TableCell>{cliente?.nome}</TableCell>
|
|
@@ -209,6 +209,25 @@
|
|
|
209
209
|
"createdAt": "Created At",
|
|
210
210
|
"tags": "Tags"
|
|
211
211
|
},
|
|
212
|
+
"tagSelector": {
|
|
213
|
+
"addTag": "Add tag",
|
|
214
|
+
"sheetTitle": "Manage tags",
|
|
215
|
+
"sheetDescription": "Select existing tags or create a new one.",
|
|
216
|
+
"createLabel": "New tag",
|
|
217
|
+
"createPlaceholder": "Type the tag name",
|
|
218
|
+
"createAction": "Create tag",
|
|
219
|
+
"popularTitle": "Most used tags",
|
|
220
|
+
"selectedTitle": "Selected tags",
|
|
221
|
+
"noTags": "No tags",
|
|
222
|
+
"cancel": "Cancel",
|
|
223
|
+
"apply": "Apply",
|
|
224
|
+
"removeTagAria": "Remove tag {tag}",
|
|
225
|
+
"messages": {
|
|
226
|
+
"createSuccess": "Tag created successfully",
|
|
227
|
+
"createError": "Could not create the tag",
|
|
228
|
+
"updateError": "Could not update tags"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
212
231
|
"attachments": {
|
|
213
232
|
"title": "Attachments",
|
|
214
233
|
"description": "Related documents",
|
|
@@ -415,6 +434,25 @@
|
|
|
415
434
|
"channel": "Channel",
|
|
416
435
|
"tags": "Tags"
|
|
417
436
|
},
|
|
437
|
+
"tagSelector": {
|
|
438
|
+
"addTag": "Add tag",
|
|
439
|
+
"sheetTitle": "Manage tags",
|
|
440
|
+
"sheetDescription": "Select existing tags or create a new one.",
|
|
441
|
+
"createLabel": "New tag",
|
|
442
|
+
"createPlaceholder": "Type the tag name",
|
|
443
|
+
"createAction": "Create tag",
|
|
444
|
+
"popularTitle": "Most used tags",
|
|
445
|
+
"selectedTitle": "Selected tags",
|
|
446
|
+
"noTags": "No tags",
|
|
447
|
+
"cancel": "Cancel",
|
|
448
|
+
"apply": "Apply",
|
|
449
|
+
"removeTagAria": "Remove tag {tag}",
|
|
450
|
+
"messages": {
|
|
451
|
+
"createSuccess": "Tag created successfully",
|
|
452
|
+
"createError": "Could not create the tag",
|
|
453
|
+
"updateError": "Could not update tags"
|
|
454
|
+
}
|
|
455
|
+
},
|
|
418
456
|
"attachments": {
|
|
419
457
|
"title": "Attachments",
|
|
420
458
|
"description": "Related documents",
|
|
@@ -209,6 +209,25 @@
|
|
|
209
209
|
"createdAt": "Data de Criação",
|
|
210
210
|
"tags": "Tags"
|
|
211
211
|
},
|
|
212
|
+
"tagSelector": {
|
|
213
|
+
"addTag": "Adicionar tag",
|
|
214
|
+
"sheetTitle": "Gerenciar tags",
|
|
215
|
+
"sheetDescription": "Selecione tags existentes ou crie uma nova.",
|
|
216
|
+
"createLabel": "Nova tag",
|
|
217
|
+
"createPlaceholder": "Digite o nome da tag",
|
|
218
|
+
"createAction": "Criar tag",
|
|
219
|
+
"popularTitle": "Tags mais usadas",
|
|
220
|
+
"selectedTitle": "Tags selecionadas",
|
|
221
|
+
"noTags": "Sem tags",
|
|
222
|
+
"cancel": "Cancelar",
|
|
223
|
+
"apply": "Aplicar",
|
|
224
|
+
"removeTagAria": "Remover tag {tag}",
|
|
225
|
+
"messages": {
|
|
226
|
+
"createSuccess": "Tag criada com sucesso",
|
|
227
|
+
"createError": "Não foi possível criar a tag",
|
|
228
|
+
"updateError": "Não foi possível atualizar as tags"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
212
231
|
"attachments": {
|
|
213
232
|
"title": "Anexos",
|
|
214
233
|
"description": "Documentos relacionados",
|
|
@@ -415,6 +434,25 @@
|
|
|
415
434
|
"channel": "Canal",
|
|
416
435
|
"tags": "Tags"
|
|
417
436
|
},
|
|
437
|
+
"tagSelector": {
|
|
438
|
+
"addTag": "Adicionar tag",
|
|
439
|
+
"sheetTitle": "Gerenciar tags",
|
|
440
|
+
"sheetDescription": "Selecione tags existentes ou crie uma nova.",
|
|
441
|
+
"createLabel": "Nova tag",
|
|
442
|
+
"createPlaceholder": "Digite o nome da tag",
|
|
443
|
+
"createAction": "Criar tag",
|
|
444
|
+
"popularTitle": "Tags mais usadas",
|
|
445
|
+
"selectedTitle": "Tags selecionadas",
|
|
446
|
+
"noTags": "Sem tags",
|
|
447
|
+
"cancel": "Cancelar",
|
|
448
|
+
"apply": "Aplicar",
|
|
449
|
+
"removeTagAria": "Remover tag {tag}",
|
|
450
|
+
"messages": {
|
|
451
|
+
"createSuccess": "Tag criada com sucesso",
|
|
452
|
+
"createError": "Não foi possível criar a tag",
|
|
453
|
+
"updateError": "Não foi possível atualizar as tags"
|
|
454
|
+
}
|
|
455
|
+
},
|
|
418
456
|
"attachments": {
|
|
419
457
|
"title": "Anexos",
|
|
420
458
|
"description": "Documentos relacionados",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/finance",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.238",
|
|
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-prisma": "0.0.4",
|
|
13
|
-
"@hed-hog/
|
|
13
|
+
"@hed-hog/api-locale": "0.0.11",
|
|
14
14
|
"@hed-hog/api-pagination": "0.0.5",
|
|
15
|
+
"@hed-hog/tag": "0.0.238",
|
|
15
16
|
"@hed-hog/api-types": "0.0.1",
|
|
16
17
|
"@hed-hog/api": "0.0.3",
|
|
17
|
-
"@hed-hog/contact": "0.0.
|
|
18
|
-
"@hed-hog/core": "0.0.
|
|
19
|
-
"@hed-hog/api-locale": "0.0.11"
|
|
18
|
+
"@hed-hog/contact": "0.0.238",
|
|
19
|
+
"@hed-hog/core": "0.0.238"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Transform } from 'class-transformer';
|
|
2
|
+
import { IsHexColor, IsOptional, IsString, MinLength } from 'class-validator';
|
|
3
|
+
|
|
4
|
+
export class CreateFinanceTagDto {
|
|
5
|
+
@Transform(({ value }) =>
|
|
6
|
+
typeof value === 'string' ? value.trim() : value,
|
|
7
|
+
)
|
|
8
|
+
@IsString()
|
|
9
|
+
@MinLength(1)
|
|
10
|
+
name: string;
|
|
11
|
+
|
|
12
|
+
@IsOptional()
|
|
13
|
+
@IsHexColor()
|
|
14
|
+
color?: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Type } from 'class-transformer';
|
|
2
|
+
import { ArrayUnique, IsArray, IsInt, IsOptional, Min } from 'class-validator';
|
|
3
|
+
|
|
4
|
+
export class UpdateInstallmentTagsDto {
|
|
5
|
+
@IsOptional()
|
|
6
|
+
@IsArray()
|
|
7
|
+
@ArrayUnique()
|
|
8
|
+
@Type(() => Number)
|
|
9
|
+
@IsInt({ each: true })
|
|
10
|
+
@Min(1, { each: true })
|
|
11
|
+
tag_ids?: number[];
|
|
12
|
+
}
|
|
@@ -2,21 +2,24 @@ import { Role, User } from '@hed-hog/api';
|
|
|
2
2
|
import { Locale } from '@hed-hog/api-locale';
|
|
3
3
|
import { Pagination } from '@hed-hog/api-pagination';
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
Body,
|
|
6
|
+
Controller,
|
|
7
|
+
Get,
|
|
8
|
+
Param,
|
|
9
|
+
ParseIntPipe,
|
|
10
|
+
Patch,
|
|
11
|
+
Post,
|
|
12
|
+
Query,
|
|
13
|
+
UploadedFile,
|
|
14
|
+
UseInterceptors,
|
|
14
15
|
} from '@nestjs/common';
|
|
15
16
|
import { FileInterceptor } from '@nestjs/platform-express';
|
|
17
|
+
import { CreateFinanceTagDto } from './dto/create-finance-tag.dto';
|
|
16
18
|
import { CreateFinancialTitleDto } from './dto/create-financial-title.dto';
|
|
17
19
|
import { ExtractFinancialTitleFromFileDto } from './dto/extract-financial-title-from-file.dto';
|
|
18
20
|
import { FinanceService } from './finance.service';
|
|
19
21
|
|
|
22
|
+
import { UpdateInstallmentTagsDto } from './dto/update-installment-tags.dto';
|
|
20
23
|
@Role()
|
|
21
24
|
@Controller('finance')
|
|
22
25
|
export class FinanceInstallmentsController {
|
|
@@ -54,6 +57,19 @@ export class FinanceInstallmentsController {
|
|
|
54
57
|
);
|
|
55
58
|
}
|
|
56
59
|
|
|
60
|
+
@Patch('accounts-payable/installments/:id/tags')
|
|
61
|
+
async updateAccountsPayableInstallmentTags(
|
|
62
|
+
@Param('id', ParseIntPipe) id: number,
|
|
63
|
+
@Body() data: UpdateInstallmentTagsDto,
|
|
64
|
+
@Locale() locale: string,
|
|
65
|
+
) {
|
|
66
|
+
return this.financeService.updateAccountsPayableInstallmentTags(
|
|
67
|
+
id,
|
|
68
|
+
data.tag_ids || [],
|
|
69
|
+
locale,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
57
73
|
@Post('accounts-payable/installments/extract-from-file')
|
|
58
74
|
@UseInterceptors(FileInterceptor('file'))
|
|
59
75
|
async extractAccountsPayableInfoFromFile(
|
|
@@ -95,6 +111,24 @@ export class FinanceInstallmentsController {
|
|
|
95
111
|
);
|
|
96
112
|
}
|
|
97
113
|
|
|
114
|
+
@Patch('accounts-receivable/installments/:id/tags')
|
|
115
|
+
async updateAccountsReceivableInstallmentTags(
|
|
116
|
+
@Param('id', ParseIntPipe) id: number,
|
|
117
|
+
@Body() data: UpdateInstallmentTagsDto,
|
|
118
|
+
@Locale() locale: string,
|
|
119
|
+
) {
|
|
120
|
+
return this.financeService.updateAccountsReceivableInstallmentTags(
|
|
121
|
+
id,
|
|
122
|
+
data.tag_ids || [],
|
|
123
|
+
locale,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@Post('tags')
|
|
128
|
+
async createTag(@Body() data: CreateFinanceTagDto) {
|
|
129
|
+
return this.financeService.createTag(data);
|
|
130
|
+
}
|
|
131
|
+
|
|
98
132
|
@Post('accounts-receivable/installments/extract-from-file')
|
|
99
133
|
@UseInterceptors(FileInterceptor('file'))
|
|
100
134
|
async extractAccountsReceivableInfoFromFile(
|