@hed-hog/finance 0.0.364 → 0.0.366
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-financial-title.dto.d.ts +8 -1
- package/dist/dto/create-financial-title.dto.d.ts.map +1 -1
- package/dist/dto/create-financial-title.dto.js +41 -3
- package/dist/dto/create-financial-title.dto.js.map +1 -1
- package/dist/finance.service.d.ts +1 -0
- package/dist/finance.service.d.ts.map +1 -1
- package/dist/finance.service.js +213 -120
- package/dist/finance.service.js.map +1 -1
- package/hedhog/data/route.yaml +6 -0
- package/hedhog/frontend/app/_components/finance-layout.tsx.ejs +15 -10
- package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +1135 -573
- package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +1132 -570
- package/hedhog/frontend/messages/en.json +92 -24
- package/hedhog/frontend/messages/pt.json +92 -24
- package/package.json +7 -7
- package/src/dto/create-financial-title.dto.ts +36 -5
- package/src/finance.service.ts +314 -144
|
@@ -18,6 +18,11 @@ import {
|
|
|
18
18
|
import { Badge } from '@/components/ui/badge';
|
|
19
19
|
import { Button } from '@/components/ui/button';
|
|
20
20
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
21
|
+
import {
|
|
22
|
+
Collapsible,
|
|
23
|
+
CollapsibleContent,
|
|
24
|
+
CollapsibleTrigger,
|
|
25
|
+
} from '@/components/ui/collapsible';
|
|
21
26
|
import { DateRangePicker } from '@/components/ui/date-range-picker';
|
|
22
27
|
import {
|
|
23
28
|
DropdownMenu,
|
|
@@ -56,6 +61,7 @@ import {
|
|
|
56
61
|
SheetTrigger,
|
|
57
62
|
} from '@/components/ui/sheet';
|
|
58
63
|
import { StatusBadge } from '@/components/ui/status-badge';
|
|
64
|
+
import { Switch } from '@/components/ui/switch';
|
|
59
65
|
import {
|
|
60
66
|
Table,
|
|
61
67
|
TableBody,
|
|
@@ -78,6 +84,8 @@ import { formatDistanceToNow } from 'date-fns';
|
|
|
78
84
|
import { enUS, ptBR } from 'date-fns/locale';
|
|
79
85
|
import {
|
|
80
86
|
AlertTriangle,
|
|
87
|
+
ChevronDown,
|
|
88
|
+
ChevronUp,
|
|
81
89
|
Download,
|
|
82
90
|
Edit,
|
|
83
91
|
Eye,
|
|
@@ -206,7 +214,7 @@ const getNewTitleFormSchema = (t: ReturnType<typeof useTranslations>) =>
|
|
|
206
214
|
z
|
|
207
215
|
.object({
|
|
208
216
|
tipoTitulo: z.enum(['parcelado', 'recorrente']).default('parcelado'),
|
|
209
|
-
documento: z.string().trim().
|
|
217
|
+
documento: z.string().trim().optional(),
|
|
210
218
|
clienteId: z.string().min(1, t('validation.clientRequired')),
|
|
211
219
|
competencia: z.string().optional(),
|
|
212
220
|
vencimento: z.string().min(1, t('validation.dueDateRequired')),
|
|
@@ -225,6 +233,8 @@ const getNewTitleFormSchema = (t: ReturnType<typeof useTranslations>) =>
|
|
|
225
233
|
amount: z
|
|
226
234
|
.number()
|
|
227
235
|
.min(0.01, t('validation.installmentAmountGreaterThanZero')),
|
|
236
|
+
paga: z.boolean().optional(),
|
|
237
|
+
dataPagamento: z.string().optional(),
|
|
228
238
|
})
|
|
229
239
|
)
|
|
230
240
|
.min(1, t('validation.installmentsRequired')),
|
|
@@ -241,12 +251,65 @@ const getNewTitleFormSchema = (t: ReturnType<typeof useTranslations>) =>
|
|
|
241
251
|
.or(z.literal('').transform(() => undefined)),
|
|
242
252
|
})
|
|
243
253
|
.optional(),
|
|
254
|
+
jaFoiPago: z.boolean().default(false),
|
|
255
|
+
pagamento: z
|
|
256
|
+
.object({
|
|
257
|
+
dataPagamento: z.string().optional(),
|
|
258
|
+
contaBancariaId: z.string().optional(),
|
|
259
|
+
valorPago: z.number().optional(),
|
|
260
|
+
juros: z.number().min(0).optional(),
|
|
261
|
+
multa: z.number().min(0).optional(),
|
|
262
|
+
desconto: z.number().min(0).optional(),
|
|
263
|
+
})
|
|
264
|
+
.optional(),
|
|
244
265
|
categoriaId: z.string().optional(),
|
|
245
266
|
centroCustoId: z.string().optional(),
|
|
246
267
|
canal: z.string().optional(),
|
|
247
268
|
descricao: z.string().optional(),
|
|
248
269
|
})
|
|
249
270
|
.superRefine((values, ctx) => {
|
|
271
|
+
if (values.jaFoiPago && values.tipoTitulo !== 'recorrente') {
|
|
272
|
+
if (!values.pagamento?.contaBancariaId) {
|
|
273
|
+
ctx.addIssue({
|
|
274
|
+
code: z.ZodIssueCode.custom,
|
|
275
|
+
path: ['pagamento', 'contaBancariaId'],
|
|
276
|
+
message: t('validation.bankAccountRequired'),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (values.installmentsCount === 1) {
|
|
281
|
+
if (!values.pagamento?.dataPagamento) {
|
|
282
|
+
ctx.addIssue({
|
|
283
|
+
code: z.ZodIssueCode.custom,
|
|
284
|
+
path: ['pagamento', 'dataPagamento'],
|
|
285
|
+
message: t('validation.paymentDateRequired'),
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const valorPago = values.pagamento?.valorPago ?? values.valor;
|
|
290
|
+
if (
|
|
291
|
+
!(valorPago > 0) ||
|
|
292
|
+
Math.round(valorPago * 100) > Math.round(values.valor * 100)
|
|
293
|
+
) {
|
|
294
|
+
ctx.addIssue({
|
|
295
|
+
code: z.ZodIssueCode.custom,
|
|
296
|
+
path: ['pagamento', 'valorPago'],
|
|
297
|
+
message: t('validation.paidAmountInvalid'),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
values.installments.forEach((installment, index) => {
|
|
302
|
+
if (installment.paga && !installment.dataPagamento) {
|
|
303
|
+
ctx.addIssue({
|
|
304
|
+
code: z.ZodIssueCode.custom,
|
|
305
|
+
path: ['installments', index, 'dataPagamento'],
|
|
306
|
+
message: t('validation.installmentPaymentDateRequired'),
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
250
313
|
if (values.tipoTitulo === 'recorrente') {
|
|
251
314
|
const r = values.recorrencia;
|
|
252
315
|
if (!r?.dataFim && !r?.numOcorrencias) {
|
|
@@ -284,6 +347,35 @@ const getNewTitleFormSchema = (t: ReturnType<typeof useTranslations>) =>
|
|
|
284
347
|
|
|
285
348
|
type NewTitleFormValues = z.infer<ReturnType<typeof getNewTitleFormSchema>>;
|
|
286
349
|
|
|
350
|
+
const getNewTitleDefaultValues = (): NewTitleFormValues => ({
|
|
351
|
+
tipoTitulo: 'parcelado',
|
|
352
|
+
documento: '',
|
|
353
|
+
clienteId: '',
|
|
354
|
+
competencia: '',
|
|
355
|
+
vencimento: '',
|
|
356
|
+
valor: 0,
|
|
357
|
+
installmentsCount: 1,
|
|
358
|
+
installments: [{ dueDate: '', amount: 0, paga: false, dataPagamento: '' }],
|
|
359
|
+
recorrencia: {
|
|
360
|
+
frequencia: 'monthly',
|
|
361
|
+
dataFim: '',
|
|
362
|
+
numOcorrencias: undefined,
|
|
363
|
+
},
|
|
364
|
+
jaFoiPago: false,
|
|
365
|
+
pagamento: {
|
|
366
|
+
dataPagamento: '',
|
|
367
|
+
contaBancariaId: '',
|
|
368
|
+
valorPago: undefined,
|
|
369
|
+
juros: undefined,
|
|
370
|
+
multa: undefined,
|
|
371
|
+
desconto: undefined,
|
|
372
|
+
},
|
|
373
|
+
categoriaId: '',
|
|
374
|
+
centroCustoId: '',
|
|
375
|
+
canal: '',
|
|
376
|
+
descricao: '',
|
|
377
|
+
});
|
|
378
|
+
|
|
287
379
|
type ReceivableInstallmentDraftPayload = {
|
|
288
380
|
mode: 'create' | 'edit';
|
|
289
381
|
titleId: string | null;
|
|
@@ -302,6 +394,7 @@ const RECEIVABLE_EDIT_TITLE_DRAFT_STORAGE_KEY =
|
|
|
302
394
|
function NovoTituloSheet({
|
|
303
395
|
categorias,
|
|
304
396
|
centrosCusto,
|
|
397
|
+
contasBancarias,
|
|
305
398
|
t,
|
|
306
399
|
onCreated,
|
|
307
400
|
onOptionsUpdated,
|
|
@@ -310,6 +403,7 @@ function NovoTituloSheet({
|
|
|
310
403
|
}: {
|
|
311
404
|
categorias: any[];
|
|
312
405
|
centrosCusto: any[];
|
|
406
|
+
contasBancarias: any[];
|
|
313
407
|
t: ReturnType<typeof useTranslations>;
|
|
314
408
|
onCreated: () => Promise<any> | void;
|
|
315
409
|
onOptionsUpdated?: () => Promise<any> | void;
|
|
@@ -328,6 +422,12 @@ function NovoTituloSheet({
|
|
|
328
422
|
const [isInstallmentsEdited, setIsInstallmentsEdited] = useState(false);
|
|
329
423
|
const [autoRedistributeInstallments, setAutoRedistributeInstallments] =
|
|
330
424
|
useState(true);
|
|
425
|
+
const [isConditionOpen, setIsConditionOpen] = useState(false);
|
|
426
|
+
const [isDetailsOpen, setIsDetailsOpen] = useState(false);
|
|
427
|
+
const paidAmountEditedRef = useRef(false);
|
|
428
|
+
const competenciaEditedRef = useRef(false);
|
|
429
|
+
const paymentDateEditedRef = useRef(false);
|
|
430
|
+
const submitAndNewRef = useRef(false);
|
|
331
431
|
const redistributionTimeoutRef = useRef<
|
|
332
432
|
Record<number, ReturnType<typeof setTimeout>>
|
|
333
433
|
>({});
|
|
@@ -360,25 +460,7 @@ function NovoTituloSheet({
|
|
|
360
460
|
|
|
361
461
|
const form = useForm<NewTitleFormValues>({
|
|
362
462
|
resolver: zodResolver(newTitleFormSchema),
|
|
363
|
-
defaultValues:
|
|
364
|
-
tipoTitulo: 'parcelado',
|
|
365
|
-
documento: '',
|
|
366
|
-
clienteId: '',
|
|
367
|
-
competencia: '',
|
|
368
|
-
vencimento: '',
|
|
369
|
-
valor: 0,
|
|
370
|
-
installmentsCount: 1,
|
|
371
|
-
installments: [{ dueDate: '', amount: 0 }],
|
|
372
|
-
recorrencia: {
|
|
373
|
-
frequencia: 'monthly',
|
|
374
|
-
dataFim: '',
|
|
375
|
-
numOcorrencias: undefined,
|
|
376
|
-
},
|
|
377
|
-
categoriaId: '',
|
|
378
|
-
centroCustoId: '',
|
|
379
|
-
canal: '',
|
|
380
|
-
descricao: '',
|
|
381
|
-
},
|
|
463
|
+
defaultValues: getNewTitleDefaultValues(),
|
|
382
464
|
});
|
|
383
465
|
|
|
384
466
|
const { fields: installmentFields, replace: replaceInstallments } =
|
|
@@ -393,6 +475,7 @@ function NovoTituloSheet({
|
|
|
393
475
|
|
|
394
476
|
const tipoTitulo = form.watch('tipoTitulo');
|
|
395
477
|
const isRecorrente = tipoTitulo === 'recorrente';
|
|
478
|
+
const jaFoiPago = form.watch('jaFoiPago');
|
|
396
479
|
|
|
397
480
|
const {
|
|
398
481
|
clearDraft,
|
|
@@ -415,12 +498,23 @@ function NovoTituloSheet({
|
|
|
415
498
|
installments: watchedFormValues.installments?.map((installment) => ({
|
|
416
499
|
dueDate: installment?.dueDate ?? '',
|
|
417
500
|
amount: Number(installment?.amount ?? 0),
|
|
418
|
-
|
|
501
|
+
paga: installment?.paga ?? false,
|
|
502
|
+
dataPagamento: installment?.dataPagamento ?? '',
|
|
503
|
+
})) ?? [{ dueDate: '', amount: 0, paga: false, dataPagamento: '' }],
|
|
419
504
|
recorrencia: {
|
|
420
505
|
frequencia: watchedFormValues.recorrencia?.frequencia ?? 'monthly',
|
|
421
506
|
dataFim: watchedFormValues.recorrencia?.dataFim ?? '',
|
|
422
507
|
numOcorrencias: watchedFormValues.recorrencia?.numOcorrencias,
|
|
423
508
|
},
|
|
509
|
+
jaFoiPago: watchedFormValues.jaFoiPago ?? false,
|
|
510
|
+
pagamento: {
|
|
511
|
+
dataPagamento: watchedFormValues.pagamento?.dataPagamento ?? '',
|
|
512
|
+
contaBancariaId: watchedFormValues.pagamento?.contaBancariaId ?? '',
|
|
513
|
+
valorPago: watchedFormValues.pagamento?.valorPago,
|
|
514
|
+
juros: watchedFormValues.pagamento?.juros,
|
|
515
|
+
multa: watchedFormValues.pagamento?.multa,
|
|
516
|
+
desconto: watchedFormValues.pagamento?.desconto,
|
|
517
|
+
},
|
|
424
518
|
categoriaId: watchedFormValues.categoriaId ?? '',
|
|
425
519
|
centroCustoId: watchedFormValues.centroCustoId ?? '',
|
|
426
520
|
canal: watchedFormValues.canal ?? '',
|
|
@@ -442,10 +536,13 @@ function NovoTituloSheet({
|
|
|
442
536
|
(watchedFormValues.descricao ?? '').trim() ||
|
|
443
537
|
(watchedFormValues.valor ?? 0) > 0 ||
|
|
444
538
|
(watchedFormValues.installmentsCount ?? 1) !== 1 ||
|
|
539
|
+
(watchedFormValues.jaFoiPago ?? false) ||
|
|
540
|
+
(watchedFormValues.pagamento?.contaBancariaId ?? '').trim() ||
|
|
445
541
|
(watchedFormValues.installments ?? []).some(
|
|
446
542
|
(installment) =>
|
|
447
543
|
(installment?.dueDate ?? '').trim() ||
|
|
448
|
-
Number(installment?.amount ?? 0) > 0
|
|
544
|
+
Number(installment?.amount ?? 0) > 0 ||
|
|
545
|
+
(installment?.paga ?? false)
|
|
449
546
|
) ||
|
|
450
547
|
uploadedFileId != null ||
|
|
451
548
|
uploadedFileName.trim()
|
|
@@ -484,6 +581,12 @@ function NovoTituloSheet({
|
|
|
484
581
|
const watchedDueDate = form.watch('vencimento');
|
|
485
582
|
const watchedInstallments = form.watch('installments');
|
|
486
583
|
|
|
584
|
+
const condicao = isRecorrente
|
|
585
|
+
? 'recorrente'
|
|
586
|
+
: (watchedInstallmentsCount ?? 1) > 1
|
|
587
|
+
? 'parcelado'
|
|
588
|
+
: 'avista';
|
|
589
|
+
|
|
487
590
|
useEffect(() => {
|
|
488
591
|
if (!open) {
|
|
489
592
|
return;
|
|
@@ -492,7 +595,8 @@ function NovoTituloSheet({
|
|
|
492
595
|
const storedDraft = loadDraft();
|
|
493
596
|
|
|
494
597
|
if (storedDraft?.payload.mode === 'create') {
|
|
495
|
-
|
|
598
|
+
const draftValues = storedDraft.payload.values;
|
|
599
|
+
form.reset({ ...getNewTitleDefaultValues(), ...draftValues });
|
|
496
600
|
setUploadedFileId(storedDraft.payload.uploadedFileId ?? null);
|
|
497
601
|
setUploadedFileName(storedDraft.payload.uploadedFileName ?? '');
|
|
498
602
|
setExtractionConfidence(null);
|
|
@@ -504,28 +608,25 @@ function NovoTituloSheet({
|
|
|
504
608
|
setAutoRedistributeInstallments(
|
|
505
609
|
storedDraft.payload.autoRedistributeInstallments ?? true
|
|
506
610
|
);
|
|
611
|
+
setIsConditionOpen(
|
|
612
|
+
(draftValues.installmentsCount ?? 1) > 1 ||
|
|
613
|
+
draftValues.tipoTitulo === 'recorrente'
|
|
614
|
+
);
|
|
615
|
+
setIsDetailsOpen(
|
|
616
|
+
Boolean(
|
|
617
|
+
(draftValues.categoriaId ?? '').trim() ||
|
|
618
|
+
(draftValues.centroCustoId ?? '').trim() ||
|
|
619
|
+
(draftValues.canal ?? '').trim() ||
|
|
620
|
+
(draftValues.descricao ?? '').trim()
|
|
621
|
+
)
|
|
622
|
+
);
|
|
623
|
+
paidAmountEditedRef.current = true;
|
|
624
|
+
competenciaEditedRef.current = true;
|
|
625
|
+
paymentDateEditedRef.current = true;
|
|
507
626
|
return;
|
|
508
627
|
}
|
|
509
628
|
|
|
510
|
-
form.reset(
|
|
511
|
-
tipoTitulo: 'parcelado',
|
|
512
|
-
documento: '',
|
|
513
|
-
clienteId: '',
|
|
514
|
-
competencia: '',
|
|
515
|
-
vencimento: '',
|
|
516
|
-
valor: 0,
|
|
517
|
-
installmentsCount: 1,
|
|
518
|
-
installments: [{ dueDate: '', amount: 0 }],
|
|
519
|
-
recorrencia: {
|
|
520
|
-
frequencia: 'monthly',
|
|
521
|
-
dataFim: '',
|
|
522
|
-
numOcorrencias: undefined,
|
|
523
|
-
},
|
|
524
|
-
categoriaId: '',
|
|
525
|
-
centroCustoId: '',
|
|
526
|
-
canal: '',
|
|
527
|
-
descricao: '',
|
|
528
|
-
});
|
|
629
|
+
form.reset(getNewTitleDefaultValues());
|
|
529
630
|
setUploadedFileId(null);
|
|
530
631
|
setUploadedFileName('');
|
|
531
632
|
setExtractionConfidence(null);
|
|
@@ -533,8 +634,48 @@ function NovoTituloSheet({
|
|
|
533
634
|
setUploadProgress(0);
|
|
534
635
|
setIsInstallmentsEdited(false);
|
|
535
636
|
setAutoRedistributeInstallments(true);
|
|
637
|
+
setIsConditionOpen(false);
|
|
638
|
+
setIsDetailsOpen(false);
|
|
639
|
+
paidAmountEditedRef.current = false;
|
|
640
|
+
competenciaEditedRef.current = false;
|
|
641
|
+
paymentDateEditedRef.current = false;
|
|
536
642
|
}, [form, loadDraft, open]);
|
|
537
643
|
|
|
644
|
+
useEffect(() => {
|
|
645
|
+
if (
|
|
646
|
+
!open ||
|
|
647
|
+
!jaFoiPago ||
|
|
648
|
+
condicao !== 'avista' ||
|
|
649
|
+
paidAmountEditedRef.current
|
|
650
|
+
) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
const currentPaidAmount = form.getValues('pagamento.valorPago');
|
|
655
|
+
if (currentPaidAmount !== watchedTotalValue) {
|
|
656
|
+
form.setValue('pagamento.valorPago', watchedTotalValue ?? 0);
|
|
657
|
+
}
|
|
658
|
+
}, [condicao, form, jaFoiPago, open, watchedTotalValue]);
|
|
659
|
+
|
|
660
|
+
useEffect(() => {
|
|
661
|
+
if (!open || !watchedDueDate) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (!competenciaEditedRef.current) {
|
|
666
|
+
const nextCompetencia = watchedDueDate.slice(0, 7);
|
|
667
|
+
if (form.getValues('competencia') !== nextCompetencia) {
|
|
668
|
+
form.setValue('competencia', nextCompetencia);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
if (!paymentDateEditedRef.current) {
|
|
673
|
+
if (form.getValues('pagamento.dataPagamento') !== watchedDueDate) {
|
|
674
|
+
form.setValue('pagamento.dataPagamento', watchedDueDate);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}, [form, open, watchedDueDate]);
|
|
678
|
+
|
|
538
679
|
useEffect(() => {
|
|
539
680
|
if (isInstallmentsEdited || !open) {
|
|
540
681
|
return;
|
|
@@ -621,13 +762,17 @@ function NovoTituloSheet({
|
|
|
621
762
|
}, []);
|
|
622
763
|
|
|
623
764
|
const handleSubmit = async (values: NewTitleFormValues) => {
|
|
765
|
+
const saveAndNew = submitAndNewRef.current;
|
|
766
|
+
submitAndNewRef.current = false;
|
|
767
|
+
|
|
624
768
|
try {
|
|
625
769
|
const recorrente = values.tipoTitulo === 'recorrente';
|
|
770
|
+
const pagoNoCadastro = values.jaFoiPago && !recorrente;
|
|
626
771
|
await request({
|
|
627
772
|
url: '/finance/accounts-receivable/installments',
|
|
628
773
|
method: 'POST',
|
|
629
774
|
data: {
|
|
630
|
-
document_number: values.documento,
|
|
775
|
+
document_number: values.documento?.trim() || undefined,
|
|
631
776
|
person_id: Number(values.clienteId),
|
|
632
777
|
competence_date: values.competencia
|
|
633
778
|
? `${values.competencia}-01`
|
|
@@ -641,6 +786,10 @@ function NovoTituloSheet({
|
|
|
641
786
|
? Number(values.centroCustoId)
|
|
642
787
|
: undefined,
|
|
643
788
|
payment_channel: values.canal || undefined,
|
|
789
|
+
bank_account_id:
|
|
790
|
+
pagoNoCadastro && values.pagamento?.contaBancariaId
|
|
791
|
+
? Number(values.pagamento.contaBancariaId)
|
|
792
|
+
: undefined,
|
|
644
793
|
description: values.descricao?.trim() || undefined,
|
|
645
794
|
...(recorrente
|
|
646
795
|
? {
|
|
@@ -656,6 +805,28 @@ function NovoTituloSheet({
|
|
|
656
805
|
installment_number: index + 1,
|
|
657
806
|
due_date: installment.dueDate || values.vencimento,
|
|
658
807
|
amount: installment.amount,
|
|
808
|
+
...(pagoNoCadastro
|
|
809
|
+
? values.installmentsCount === 1
|
|
810
|
+
? {
|
|
811
|
+
paid: true,
|
|
812
|
+
paid_at:
|
|
813
|
+
values.pagamento?.dataPagamento || undefined,
|
|
814
|
+
paid_amount:
|
|
815
|
+
values.pagamento?.valorPago || installment.amount,
|
|
816
|
+
interest: values.pagamento?.juros || undefined,
|
|
817
|
+
penalty: values.pagamento?.multa || undefined,
|
|
818
|
+
discount: values.pagamento?.desconto || undefined,
|
|
819
|
+
}
|
|
820
|
+
: installment.paga
|
|
821
|
+
? {
|
|
822
|
+
paid: true,
|
|
823
|
+
paid_at:
|
|
824
|
+
installment.dataPagamento ||
|
|
825
|
+
installment.dueDate ||
|
|
826
|
+
values.vencimento,
|
|
827
|
+
}
|
|
828
|
+
: {}
|
|
829
|
+
: {}),
|
|
659
830
|
})),
|
|
660
831
|
}),
|
|
661
832
|
attachment_file_ids: uploadedFileId ? [uploadedFileId] : undefined,
|
|
@@ -664,14 +835,35 @@ function NovoTituloSheet({
|
|
|
664
835
|
|
|
665
836
|
clearDraft();
|
|
666
837
|
await onCreated();
|
|
667
|
-
|
|
838
|
+
|
|
839
|
+
const defaults = getNewTitleDefaultValues();
|
|
840
|
+
const keptDueDate = saveAndNew ? values.vencimento : '';
|
|
841
|
+
form.reset({
|
|
842
|
+
...defaults,
|
|
843
|
+
vencimento: keptDueDate,
|
|
844
|
+
competencia: keptDueDate ? keptDueDate.slice(0, 7) : '',
|
|
845
|
+
pagamento: {
|
|
846
|
+
...defaults.pagamento,
|
|
847
|
+
dataPagamento: keptDueDate,
|
|
848
|
+
},
|
|
849
|
+
});
|
|
668
850
|
setUploadedFileId(null);
|
|
669
851
|
setUploadedFileName('');
|
|
670
852
|
setExtractionConfidence(null);
|
|
671
853
|
setExtractionWarnings([]);
|
|
854
|
+
setUploadProgress(0);
|
|
672
855
|
setIsInstallmentsEdited(false);
|
|
673
856
|
setAutoRedistributeInstallments(true);
|
|
674
|
-
|
|
857
|
+
setIsConditionOpen(false);
|
|
858
|
+
setIsDetailsOpen(false);
|
|
859
|
+
paidAmountEditedRef.current = false;
|
|
860
|
+
competenciaEditedRef.current = false;
|
|
861
|
+
paymentDateEditedRef.current = false;
|
|
862
|
+
|
|
863
|
+
if (!saveAndNew) {
|
|
864
|
+
setOpen(false);
|
|
865
|
+
}
|
|
866
|
+
|
|
675
867
|
showToastHandler?.('success', t('messages.createSuccess'));
|
|
676
868
|
} catch (error) {
|
|
677
869
|
showToastHandler?.(
|
|
@@ -855,6 +1047,61 @@ function NovoTituloSheet({
|
|
|
855
1047
|
}
|
|
856
1048
|
};
|
|
857
1049
|
|
|
1050
|
+
const formattedDueDateLabel = watchedDueDate
|
|
1051
|
+
? formatarData(`${watchedDueDate}T00:00:00`)
|
|
1052
|
+
: '-';
|
|
1053
|
+
|
|
1054
|
+
const conditionSummary = isRecorrente
|
|
1055
|
+
? t('sections.paymentCondition.summary.recurring', {
|
|
1056
|
+
frequency: t(
|
|
1057
|
+
`recurrenceEditor.frequencies.${
|
|
1058
|
+
form.watch('recorrencia.frequencia') || 'monthly'
|
|
1059
|
+
}` as Parameters<typeof t>[0]
|
|
1060
|
+
),
|
|
1061
|
+
})
|
|
1062
|
+
: condicao === 'parcelado'
|
|
1063
|
+
? t('sections.paymentCondition.summary.installments', {
|
|
1064
|
+
count: watchedInstallmentsCount ?? 1,
|
|
1065
|
+
date: formattedDueDateLabel,
|
|
1066
|
+
})
|
|
1067
|
+
: t('sections.paymentCondition.summary.cash', {
|
|
1068
|
+
date: formattedDueDateLabel,
|
|
1069
|
+
});
|
|
1070
|
+
|
|
1071
|
+
const renderCanalField = () => (
|
|
1072
|
+
<FormField
|
|
1073
|
+
control={form.control}
|
|
1074
|
+
name="canal"
|
|
1075
|
+
render={({ field }) => (
|
|
1076
|
+
<FormItem>
|
|
1077
|
+
<FormLabel>{t('fields.channel')}</FormLabel>
|
|
1078
|
+
<Select value={field.value} onValueChange={field.onChange}>
|
|
1079
|
+
<FormControl>
|
|
1080
|
+
<SelectTrigger className="w-full">
|
|
1081
|
+
<SelectValue placeholder={t('common.select')} />
|
|
1082
|
+
</SelectTrigger>
|
|
1083
|
+
</FormControl>
|
|
1084
|
+
<SelectContent>
|
|
1085
|
+
<SelectItem value="boleto">{t('channels.boleto')}</SelectItem>
|
|
1086
|
+
<SelectItem value="pix">PIX</SelectItem>
|
|
1087
|
+
<SelectItem value="cartao">{t('channels.card')}</SelectItem>
|
|
1088
|
+
<SelectItem value="transferencia">
|
|
1089
|
+
{t('channels.transfer')}
|
|
1090
|
+
</SelectItem>
|
|
1091
|
+
<SelectItem value="debito_automatico">
|
|
1092
|
+
{t('channels.debitAutomatico')}
|
|
1093
|
+
</SelectItem>
|
|
1094
|
+
<SelectItem value="debito_em_conta">
|
|
1095
|
+
{t('channels.debitEmConta')}
|
|
1096
|
+
</SelectItem>
|
|
1097
|
+
</SelectContent>
|
|
1098
|
+
</Select>
|
|
1099
|
+
<FormMessage />
|
|
1100
|
+
</FormItem>
|
|
1101
|
+
)}
|
|
1102
|
+
/>
|
|
1103
|
+
);
|
|
1104
|
+
|
|
858
1105
|
return (
|
|
859
1106
|
<Sheet open={open} onOpenChange={setOpen}>
|
|
860
1107
|
<SheetTrigger asChild>
|
|
@@ -865,7 +1112,7 @@ function NovoTituloSheet({
|
|
|
865
1112
|
</SheetTrigger>
|
|
866
1113
|
<ResizableSheetContent
|
|
867
1114
|
sheetId="finance-receivable-create-title"
|
|
868
|
-
defaultWidth={
|
|
1115
|
+
defaultWidth={1024}
|
|
869
1116
|
className="flex h-full w-full flex-col overflow-hidden p-0 gap-0"
|
|
870
1117
|
>
|
|
871
1118
|
<SheetHeader className="border-b border-border/50 px-4 py-4 sm:px-6">
|
|
@@ -878,10 +1125,12 @@ function NovoTituloSheet({
|
|
|
878
1125
|
onSubmit={form.handleSubmit(handleSubmit, handleInvalidSubmit)}
|
|
879
1126
|
>
|
|
880
1127
|
<FinanceSheetBody className="pt-0">
|
|
881
|
-
<FinanceSheetSection
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
1128
|
+
<FinanceSheetSection
|
|
1129
|
+
className="pt-0 mt-0"
|
|
1130
|
+
title={t('sections.main.title')}
|
|
1131
|
+
description={t('sections.main.description')}
|
|
1132
|
+
actions={
|
|
1133
|
+
<div className="flex items-center gap-1">
|
|
885
1134
|
<Input
|
|
886
1135
|
ref={fileInputRef}
|
|
887
1136
|
className="hidden"
|
|
@@ -903,113 +1152,95 @@ function NovoTituloSheet({
|
|
|
903
1152
|
}
|
|
904
1153
|
/>
|
|
905
1154
|
|
|
906
|
-
<
|
|
1155
|
+
<Tooltip>
|
|
1156
|
+
<TooltipTrigger asChild>
|
|
1157
|
+
<Button
|
|
1158
|
+
type="button"
|
|
1159
|
+
variant="outline"
|
|
1160
|
+
size="icon"
|
|
1161
|
+
onClick={handleSelectFile}
|
|
1162
|
+
aria-label={
|
|
1163
|
+
uploadedFileId
|
|
1164
|
+
? t('common.upload.change')
|
|
1165
|
+
: t('common.upload.label')
|
|
1166
|
+
}
|
|
1167
|
+
disabled={
|
|
1168
|
+
isUploadingFile ||
|
|
1169
|
+
isExtractingFileData ||
|
|
1170
|
+
form.formState.isSubmitting
|
|
1171
|
+
}
|
|
1172
|
+
>
|
|
1173
|
+
{isUploadingFile || isExtractingFileData ? (
|
|
1174
|
+
<Loader2 className="h-4 w-4 animate-spin" />
|
|
1175
|
+
) : (
|
|
1176
|
+
<Upload className="h-4 w-4" />
|
|
1177
|
+
)}
|
|
1178
|
+
</Button>
|
|
1179
|
+
</TooltipTrigger>
|
|
1180
|
+
<TooltipContent>
|
|
1181
|
+
{isUploadingFile && !isExtractingFileData
|
|
1182
|
+
? t('common.upload.uploadingProgress', {
|
|
1183
|
+
progress: uploadProgress,
|
|
1184
|
+
})
|
|
1185
|
+
: isExtractingFileData
|
|
1186
|
+
? t('common.upload.processingAi')
|
|
1187
|
+
: uploadedFileId
|
|
1188
|
+
? `${t('common.upload.selectedPrefix')} ${uploadedFileName} — ${t('common.upload.change')}`
|
|
1189
|
+
: t('common.upload.label')}
|
|
1190
|
+
</TooltipContent>
|
|
1191
|
+
</Tooltip>
|
|
1192
|
+
|
|
1193
|
+
{uploadedFileId && (
|
|
907
1194
|
<Tooltip>
|
|
908
1195
|
<TooltipTrigger asChild>
|
|
909
1196
|
<Button
|
|
910
1197
|
type="button"
|
|
911
1198
|
variant="outline"
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
}
|
|
915
|
-
onClick={handleSelectFile}
|
|
916
|
-
aria-label={
|
|
917
|
-
uploadedFileId
|
|
918
|
-
? t('common.upload.change')
|
|
919
|
-
: t('common.upload.upload')
|
|
920
|
-
}
|
|
1199
|
+
size="icon"
|
|
1200
|
+
onClick={clearUploadedFile}
|
|
1201
|
+
aria-label={t('common.upload.remove')}
|
|
921
1202
|
disabled={
|
|
922
1203
|
isUploadingFile ||
|
|
923
1204
|
isExtractingFileData ||
|
|
924
1205
|
form.formState.isSubmitting
|
|
925
1206
|
}
|
|
926
1207
|
>
|
|
927
|
-
|
|
928
|
-
<Upload className="h-4 w-4" />
|
|
929
|
-
) : (
|
|
930
|
-
<>
|
|
931
|
-
<Upload className="mr-2 h-4 w-4" />
|
|
932
|
-
{t('common.upload.upload')}
|
|
933
|
-
</>
|
|
934
|
-
)}
|
|
1208
|
+
<Trash2 className="h-4 w-4" />
|
|
935
1209
|
</Button>
|
|
936
1210
|
</TooltipTrigger>
|
|
937
1211
|
<TooltipContent>
|
|
938
|
-
{
|
|
939
|
-
? t('common.upload.change')
|
|
940
|
-
: t('common.upload.upload')}
|
|
1212
|
+
{t('common.upload.remove')}
|
|
941
1213
|
</TooltipContent>
|
|
942
1214
|
</Tooltip>
|
|
1215
|
+
)}
|
|
1216
|
+
</div>
|
|
1217
|
+
}
|
|
1218
|
+
>
|
|
1219
|
+
{!isExtractingFileData &&
|
|
1220
|
+
extractionConfidence !== null &&
|
|
1221
|
+
extractionConfidence < 70 && (
|
|
1222
|
+
<p className="text-xs text-destructive">
|
|
1223
|
+
{t('common.upload.lowConfidence', {
|
|
1224
|
+
confidence: Math.round(extractionConfidence),
|
|
1225
|
+
})}
|
|
1226
|
+
</p>
|
|
1227
|
+
)}
|
|
943
1228
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
variant="outline"
|
|
950
|
-
className="w-full"
|
|
951
|
-
onClick={clearUploadedFile}
|
|
952
|
-
aria-label={t('common.upload.remove')}
|
|
953
|
-
disabled={
|
|
954
|
-
isUploadingFile ||
|
|
955
|
-
isExtractingFileData ||
|
|
956
|
-
form.formState.isSubmitting
|
|
957
|
-
}
|
|
958
|
-
>
|
|
959
|
-
<Trash2 className="h-4 w-4" />
|
|
960
|
-
</Button>
|
|
961
|
-
</TooltipTrigger>
|
|
962
|
-
<TooltipContent>
|
|
963
|
-
{t('common.upload.remove')}
|
|
964
|
-
</TooltipContent>
|
|
965
|
-
</Tooltip>
|
|
966
|
-
)}
|
|
967
|
-
</div>
|
|
968
|
-
|
|
969
|
-
<div className="space-y-1 rounded-lg border border-dashed border-border/70 bg-muted/20 p-3">
|
|
970
|
-
{uploadedFileId && (
|
|
971
|
-
<p className="truncate text-xs text-muted-foreground">
|
|
972
|
-
{t('common.upload.selectedPrefix')} {uploadedFileName}
|
|
973
|
-
</p>
|
|
974
|
-
)}
|
|
975
|
-
|
|
976
|
-
{isUploadingFile && !isExtractingFileData && (
|
|
977
|
-
<div className="space-y-1">
|
|
978
|
-
<Progress value={uploadProgress} className="h-2" />
|
|
979
|
-
<p className="text-xs text-muted-foreground">
|
|
980
|
-
{t('common.upload.uploadingProgress', {
|
|
981
|
-
progress: uploadProgress,
|
|
982
|
-
})}
|
|
983
|
-
</p>
|
|
984
|
-
</div>
|
|
985
|
-
)}
|
|
986
|
-
|
|
987
|
-
{isExtractingFileData && (
|
|
988
|
-
<p className="flex items-center gap-2 text-xs text-primary">
|
|
989
|
-
<Loader2 className="h-4 w-4 animate-spin" />
|
|
990
|
-
{t('common.upload.processingAi')}
|
|
991
|
-
</p>
|
|
992
|
-
)}
|
|
993
|
-
|
|
994
|
-
{!isExtractingFileData &&
|
|
995
|
-
extractionConfidence !== null &&
|
|
996
|
-
extractionConfidence < 70 && (
|
|
997
|
-
<p className="text-xs text-destructive">
|
|
998
|
-
{t('common.upload.lowConfidence', {
|
|
999
|
-
confidence: Math.round(extractionConfidence),
|
|
1000
|
-
})}
|
|
1001
|
-
</p>
|
|
1002
|
-
)}
|
|
1229
|
+
{!isExtractingFileData && extractionWarnings.length > 0 && (
|
|
1230
|
+
<p className="truncate text-xs text-muted-foreground">
|
|
1231
|
+
{extractionWarnings[0]}
|
|
1232
|
+
</p>
|
|
1233
|
+
)}
|
|
1003
1234
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
</div>
|
|
1235
|
+
<PersonPickerField
|
|
1236
|
+
form={form}
|
|
1237
|
+
name="clienteId"
|
|
1238
|
+
label={t('fields.client')}
|
|
1239
|
+
entityLabel="cliente"
|
|
1240
|
+
selectPlaceholder={t('common.select')}
|
|
1241
|
+
/>
|
|
1012
1242
|
|
|
1243
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
1013
1244
|
<FormField
|
|
1014
1245
|
control={form.control}
|
|
1015
1246
|
name="documento"
|
|
@@ -1017,230 +1248,124 @@ function NovoTituloSheet({
|
|
|
1017
1248
|
<FormItem>
|
|
1018
1249
|
<FormLabel>{t('fields.document')}</FormLabel>
|
|
1019
1250
|
<FormControl>
|
|
1020
|
-
<Input
|
|
1251
|
+
<Input
|
|
1252
|
+
placeholder="FAT-00000"
|
|
1253
|
+
{...field}
|
|
1254
|
+
value={field.value || ''}
|
|
1255
|
+
/>
|
|
1256
|
+
</FormControl>
|
|
1257
|
+
<FormMessage />
|
|
1258
|
+
</FormItem>
|
|
1259
|
+
)}
|
|
1260
|
+
/>
|
|
1261
|
+
|
|
1262
|
+
<FormField
|
|
1263
|
+
control={form.control}
|
|
1264
|
+
name="vencimento"
|
|
1265
|
+
render={({ field }) => (
|
|
1266
|
+
<FormItem>
|
|
1267
|
+
<FormLabel>{t('fields.dueDate')}</FormLabel>
|
|
1268
|
+
<FormControl>
|
|
1269
|
+
<Input
|
|
1270
|
+
type="date"
|
|
1271
|
+
{...field}
|
|
1272
|
+
value={field.value || ''}
|
|
1273
|
+
/>
|
|
1274
|
+
</FormControl>
|
|
1275
|
+
<FormMessage />
|
|
1276
|
+
</FormItem>
|
|
1277
|
+
)}
|
|
1278
|
+
/>
|
|
1279
|
+
|
|
1280
|
+
<FormField
|
|
1281
|
+
control={form.control}
|
|
1282
|
+
name="valor"
|
|
1283
|
+
render={({ field }) => (
|
|
1284
|
+
<FormItem>
|
|
1285
|
+
<FormLabel>
|
|
1286
|
+
{isRecorrente
|
|
1287
|
+
? t('fields.totalValueRecurring')
|
|
1288
|
+
: t('fields.totalValue')}
|
|
1289
|
+
</FormLabel>
|
|
1290
|
+
<FormControl>
|
|
1291
|
+
<InputMoney
|
|
1292
|
+
ref={field.ref}
|
|
1293
|
+
name={field.name}
|
|
1294
|
+
value={field.value}
|
|
1295
|
+
onBlur={field.onBlur}
|
|
1296
|
+
onValueChange={(value) => field.onChange(value ?? 0)}
|
|
1297
|
+
placeholder="0,00"
|
|
1298
|
+
/>
|
|
1021
1299
|
</FormControl>
|
|
1022
1300
|
<FormMessage />
|
|
1023
1301
|
</FormItem>
|
|
1024
1302
|
)}
|
|
1025
1303
|
/>
|
|
1026
1304
|
</div>
|
|
1305
|
+
</FinanceSheetSection>
|
|
1027
1306
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1307
|
+
{!isRecorrente && (
|
|
1308
|
+
<div className="space-y-4 rounded-lg border border-border/60 bg-muted/10 p-4">
|
|
1309
|
+
<FormField
|
|
1310
|
+
control={form.control}
|
|
1311
|
+
name="jaFoiPago"
|
|
1312
|
+
render={({ field }) => (
|
|
1313
|
+
<FormItem className="flex flex-row items-center justify-between gap-3 space-y-0">
|
|
1314
|
+
<div className="space-y-1">
|
|
1315
|
+
<FormLabel>{t('paidToggle.label')}</FormLabel>
|
|
1316
|
+
<p className="text-xs text-muted-foreground">
|
|
1317
|
+
{t('paidToggle.hint')}
|
|
1318
|
+
</p>
|
|
1319
|
+
</div>
|
|
1320
|
+
<FormControl>
|
|
1321
|
+
<Switch
|
|
1322
|
+
checked={field.value === true}
|
|
1323
|
+
onCheckedChange={(checked) => {
|
|
1324
|
+
const isPaid = checked === true;
|
|
1325
|
+
field.onChange(isPaid);
|
|
1326
|
+
|
|
1327
|
+
if (!isPaid) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1035
1330
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
<div className="flex gap-2">
|
|
1044
|
-
<Button
|
|
1045
|
-
type="button"
|
|
1046
|
-
variant={
|
|
1047
|
-
field.value === 'parcelado' ? 'default' : 'outline'
|
|
1048
|
-
}
|
|
1049
|
-
size="sm"
|
|
1050
|
-
onClick={() => field.onChange('parcelado')}
|
|
1051
|
-
>
|
|
1052
|
-
{t('titleType.installment')}
|
|
1053
|
-
</Button>
|
|
1054
|
-
<Button
|
|
1055
|
-
type="button"
|
|
1056
|
-
variant={
|
|
1057
|
-
field.value === 'recorrente' ? 'default' : 'outline'
|
|
1058
|
-
}
|
|
1059
|
-
size="sm"
|
|
1060
|
-
onClick={() => field.onChange('recorrente')}
|
|
1061
|
-
>
|
|
1062
|
-
{t('titleType.recurring')}
|
|
1063
|
-
</Button>
|
|
1064
|
-
</div>
|
|
1065
|
-
</FormItem>
|
|
1066
|
-
)}
|
|
1067
|
-
/>
|
|
1331
|
+
if (!form.getValues('pagamento.dataPagamento')) {
|
|
1332
|
+
form.setValue(
|
|
1333
|
+
'pagamento.dataPagamento',
|
|
1334
|
+
form.getValues('vencimento') ||
|
|
1335
|
+
new Date().toISOString().slice(0, 10)
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1068
1338
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
render={({ field }) => (
|
|
1075
|
-
<FormItem>
|
|
1076
|
-
<FormLabel>{t('fields.competency')}</FormLabel>
|
|
1077
|
-
<FormControl>
|
|
1078
|
-
<Input
|
|
1079
|
-
type="month"
|
|
1080
|
-
{...field}
|
|
1081
|
-
value={field.value || ''}
|
|
1082
|
-
/>
|
|
1083
|
-
</FormControl>
|
|
1084
|
-
<FormMessage />
|
|
1085
|
-
</FormItem>
|
|
1086
|
-
)}
|
|
1087
|
-
/>
|
|
1088
|
-
|
|
1089
|
-
<FormField
|
|
1090
|
-
control={form.control}
|
|
1091
|
-
name="vencimento"
|
|
1092
|
-
render={({ field }) => (
|
|
1093
|
-
<FormItem>
|
|
1094
|
-
<FormLabel>
|
|
1095
|
-
{isRecorrente
|
|
1096
|
-
? t('fields.dueDate')
|
|
1097
|
-
: t('fields.dueDate')}
|
|
1098
|
-
</FormLabel>
|
|
1099
|
-
<FormControl>
|
|
1100
|
-
<Input
|
|
1101
|
-
type="date"
|
|
1102
|
-
{...field}
|
|
1103
|
-
value={field.value || ''}
|
|
1104
|
-
/>
|
|
1105
|
-
</FormControl>
|
|
1106
|
-
<FormMessage />
|
|
1107
|
-
</FormItem>
|
|
1108
|
-
)}
|
|
1109
|
-
/>
|
|
1110
|
-
</div>
|
|
1111
|
-
|
|
1112
|
-
<div className="grid gap-4 md:grid-cols-2">
|
|
1113
|
-
<FormField
|
|
1114
|
-
control={form.control}
|
|
1115
|
-
name="valor"
|
|
1116
|
-
render={({ field }) => (
|
|
1117
|
-
<FormItem>
|
|
1118
|
-
<FormLabel>
|
|
1119
|
-
{isRecorrente
|
|
1120
|
-
? t('fields.totalValueRecurring')
|
|
1121
|
-
: t('fields.totalValue')}
|
|
1122
|
-
</FormLabel>
|
|
1123
|
-
<FormControl>
|
|
1124
|
-
<InputMoney
|
|
1125
|
-
ref={field.ref}
|
|
1126
|
-
name={field.name}
|
|
1127
|
-
value={field.value}
|
|
1128
|
-
onBlur={field.onBlur}
|
|
1129
|
-
onValueChange={(value) =>
|
|
1130
|
-
field.onChange(value ?? 0)
|
|
1339
|
+
if (!paidAmountEditedRef.current) {
|
|
1340
|
+
form.setValue(
|
|
1341
|
+
'pagamento.valorPago',
|
|
1342
|
+
form.getValues('valor') ?? 0
|
|
1343
|
+
);
|
|
1131
1344
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
</FormItem>
|
|
1137
|
-
)}
|
|
1138
|
-
/>
|
|
1139
|
-
|
|
1140
|
-
{!isRecorrente && (
|
|
1141
|
-
<FormField
|
|
1142
|
-
control={form.control}
|
|
1143
|
-
name="installmentsCount"
|
|
1144
|
-
render={({ field }) => (
|
|
1145
|
-
<FormItem>
|
|
1146
|
-
<FormLabel>
|
|
1147
|
-
{t('installmentsEditor.countLabel')}
|
|
1148
|
-
</FormLabel>
|
|
1149
|
-
<FormControl>
|
|
1150
|
-
<Input
|
|
1151
|
-
type="number"
|
|
1152
|
-
min={1}
|
|
1153
|
-
max={120}
|
|
1154
|
-
value={field.value}
|
|
1155
|
-
onChange={(event) => {
|
|
1156
|
-
const nextValue = Number(
|
|
1157
|
-
event.target.value || 1
|
|
1158
|
-
);
|
|
1159
|
-
field.onChange(
|
|
1160
|
-
Number.isNaN(nextValue) ? 1 : nextValue
|
|
1161
|
-
);
|
|
1162
|
-
}}
|
|
1163
|
-
/>
|
|
1164
|
-
</FormControl>
|
|
1165
|
-
<FormMessage />
|
|
1166
|
-
</FormItem>
|
|
1167
|
-
)}
|
|
1168
|
-
/>
|
|
1169
|
-
)}
|
|
1170
|
-
</div>
|
|
1171
|
-
</div>
|
|
1172
|
-
|
|
1173
|
-
{!isRecorrente && (
|
|
1174
|
-
<div className="space-y-3 rounded-md border p-3">
|
|
1175
|
-
<div className="flex items-center justify-between gap-2">
|
|
1176
|
-
<p className="text-sm font-medium">
|
|
1177
|
-
{t('installmentsEditor.title')}
|
|
1178
|
-
</p>
|
|
1179
|
-
<Button
|
|
1180
|
-
type="button"
|
|
1181
|
-
variant="outline"
|
|
1182
|
-
size="sm"
|
|
1183
|
-
onClick={() => {
|
|
1184
|
-
setIsInstallmentsEdited(false);
|
|
1185
|
-
replaceInstallments(
|
|
1186
|
-
buildEqualInstallments(
|
|
1187
|
-
form.getValues('installmentsCount'),
|
|
1188
|
-
form.getValues('valor'),
|
|
1189
|
-
form.getValues('vencimento')
|
|
1190
|
-
)
|
|
1191
|
-
);
|
|
1192
|
-
}}
|
|
1193
|
-
>
|
|
1194
|
-
{t('installmentsEditor.recalculate')}
|
|
1195
|
-
</Button>
|
|
1196
|
-
</div>
|
|
1197
|
-
|
|
1198
|
-
<div className="flex items-center gap-2">
|
|
1199
|
-
<Checkbox
|
|
1200
|
-
id="auto-redistribute-installments-receivable"
|
|
1201
|
-
checked={autoRedistributeInstallments}
|
|
1202
|
-
onCheckedChange={(checked) =>
|
|
1203
|
-
setAutoRedistributeInstallments(checked === true)
|
|
1204
|
-
}
|
|
1205
|
-
/>
|
|
1206
|
-
<Label
|
|
1207
|
-
htmlFor="auto-redistribute-installments-receivable"
|
|
1208
|
-
className="text-xs text-muted-foreground"
|
|
1209
|
-
>
|
|
1210
|
-
{t('installmentsEditor.autoRedistributeLabel')}
|
|
1211
|
-
</Label>
|
|
1212
|
-
</div>
|
|
1213
|
-
{autoRedistributeInstallments && (
|
|
1214
|
-
<p className="text-xs text-muted-foreground">
|
|
1215
|
-
{t('installmentsEditor.autoRedistributeHint')}
|
|
1216
|
-
</p>
|
|
1345
|
+
}}
|
|
1346
|
+
/>
|
|
1347
|
+
</FormControl>
|
|
1348
|
+
</FormItem>
|
|
1217
1349
|
)}
|
|
1350
|
+
/>
|
|
1218
1351
|
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
className="grid grid-cols-1 items-start gap-2 rounded-md border p-2 sm:grid-cols-[96px_1fr_160px]"
|
|
1224
|
-
>
|
|
1225
|
-
<div className="flex items-center text-sm text-muted-foreground">
|
|
1226
|
-
#{index + 1}
|
|
1227
|
-
</div>
|
|
1228
|
-
|
|
1352
|
+
{jaFoiPago && (
|
|
1353
|
+
<div className="space-y-4">
|
|
1354
|
+
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
1355
|
+
{condicao === 'avista' && (
|
|
1229
1356
|
<FormField
|
|
1230
1357
|
control={form.control}
|
|
1231
|
-
name=
|
|
1358
|
+
name="pagamento.dataPagamento"
|
|
1232
1359
|
render={({ field }) => (
|
|
1233
1360
|
<FormItem>
|
|
1234
|
-
<FormLabel
|
|
1235
|
-
{t('installmentsEditor.dueDateLabel')}
|
|
1236
|
-
</FormLabel>
|
|
1361
|
+
<FormLabel>{t('payment.dateLabel')}</FormLabel>
|
|
1237
1362
|
<FormControl>
|
|
1238
1363
|
<Input
|
|
1239
1364
|
type="date"
|
|
1240
1365
|
{...field}
|
|
1241
1366
|
value={field.value || ''}
|
|
1242
1367
|
onChange={(event) => {
|
|
1243
|
-
|
|
1368
|
+
paymentDateEditedRef.current = true;
|
|
1244
1369
|
field.onChange(event);
|
|
1245
1370
|
}}
|
|
1246
1371
|
/>
|
|
@@ -1249,39 +1374,73 @@ function NovoTituloSheet({
|
|
|
1249
1374
|
</FormItem>
|
|
1250
1375
|
)}
|
|
1251
1376
|
/>
|
|
1377
|
+
)}
|
|
1252
1378
|
|
|
1379
|
+
<FormField
|
|
1380
|
+
control={form.control}
|
|
1381
|
+
name="pagamento.contaBancariaId"
|
|
1382
|
+
render={({ field }) => (
|
|
1383
|
+
<FormItem>
|
|
1384
|
+
<FormLabel>
|
|
1385
|
+
{t('payment.bankAccountLabel')}
|
|
1386
|
+
</FormLabel>
|
|
1387
|
+
<Select
|
|
1388
|
+
value={field.value || ''}
|
|
1389
|
+
onValueChange={field.onChange}
|
|
1390
|
+
>
|
|
1391
|
+
<FormControl>
|
|
1392
|
+
<SelectTrigger className="w-full">
|
|
1393
|
+
<SelectValue
|
|
1394
|
+
placeholder={t(
|
|
1395
|
+
'payment.bankAccountPlaceholder'
|
|
1396
|
+
)}
|
|
1397
|
+
/>
|
|
1398
|
+
</SelectTrigger>
|
|
1399
|
+
</FormControl>
|
|
1400
|
+
<SelectContent>
|
|
1401
|
+
{contasBancarias.map((conta: any) => (
|
|
1402
|
+
<SelectItem
|
|
1403
|
+
key={conta.id}
|
|
1404
|
+
value={String(conta.id)}
|
|
1405
|
+
>
|
|
1406
|
+
{[
|
|
1407
|
+
conta.descricao,
|
|
1408
|
+
conta.banco &&
|
|
1409
|
+
conta.banco !== conta.descricao
|
|
1410
|
+
? conta.banco
|
|
1411
|
+
: null,
|
|
1412
|
+
]
|
|
1413
|
+
.filter(Boolean)
|
|
1414
|
+
.join(' — ')}
|
|
1415
|
+
</SelectItem>
|
|
1416
|
+
))}
|
|
1417
|
+
</SelectContent>
|
|
1418
|
+
</Select>
|
|
1419
|
+
<FormMessage />
|
|
1420
|
+
</FormItem>
|
|
1421
|
+
)}
|
|
1422
|
+
/>
|
|
1423
|
+
|
|
1424
|
+
{renderCanalField()}
|
|
1425
|
+
|
|
1426
|
+
{condicao === 'avista' && (
|
|
1253
1427
|
<FormField
|
|
1254
1428
|
control={form.control}
|
|
1255
|
-
name=
|
|
1429
|
+
name="pagamento.valorPago"
|
|
1256
1430
|
render={({ field }) => (
|
|
1257
1431
|
<FormItem>
|
|
1258
|
-
<FormLabel
|
|
1259
|
-
{t('
|
|
1432
|
+
<FormLabel>
|
|
1433
|
+
{t('payment.paidAmountLabel')}
|
|
1260
1434
|
</FormLabel>
|
|
1261
1435
|
<FormControl>
|
|
1262
1436
|
<InputMoney
|
|
1263
1437
|
ref={field.ref}
|
|
1264
1438
|
name={field.name}
|
|
1265
1439
|
value={field.value}
|
|
1266
|
-
onBlur={
|
|
1267
|
-
field.onBlur();
|
|
1268
|
-
|
|
1269
|
-
if (!autoRedistributeInstallments) {
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
clearScheduledRedistribution(index);
|
|
1274
|
-
runInstallmentRedistribution(index);
|
|
1275
|
-
}}
|
|
1440
|
+
onBlur={field.onBlur}
|
|
1276
1441
|
onValueChange={(value) => {
|
|
1277
|
-
|
|
1278
|
-
field.onChange(value
|
|
1279
|
-
|
|
1280
|
-
if (!autoRedistributeInstallments) {
|
|
1281
|
-
return;
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
scheduleInstallmentRedistribution(index);
|
|
1442
|
+
paidAmountEditedRef.current = true;
|
|
1443
|
+
field.onChange(value);
|
|
1285
1444
|
}}
|
|
1286
1445
|
placeholder="0,00"
|
|
1287
1446
|
/>
|
|
@@ -1290,125 +1449,186 @@ function NovoTituloSheet({
|
|
|
1290
1449
|
</FormItem>
|
|
1291
1450
|
)}
|
|
1292
1451
|
/>
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
</div>
|
|
1452
|
+
)}
|
|
1453
|
+
</div>
|
|
1296
1454
|
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1455
|
+
{condicao === 'avista' ? (
|
|
1456
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
1457
|
+
<FormField
|
|
1458
|
+
control={form.control}
|
|
1459
|
+
name="pagamento.juros"
|
|
1460
|
+
render={({ field }) => (
|
|
1461
|
+
<FormItem>
|
|
1462
|
+
<FormLabel>
|
|
1463
|
+
{t('payment.interestLabel')}
|
|
1464
|
+
</FormLabel>
|
|
1465
|
+
<FormControl>
|
|
1466
|
+
<InputMoney
|
|
1467
|
+
ref={field.ref}
|
|
1468
|
+
name={field.name}
|
|
1469
|
+
value={field.value}
|
|
1470
|
+
onBlur={field.onBlur}
|
|
1471
|
+
onValueChange={(value) =>
|
|
1472
|
+
field.onChange(value)
|
|
1473
|
+
}
|
|
1474
|
+
placeholder="0,00"
|
|
1475
|
+
/>
|
|
1476
|
+
</FormControl>
|
|
1477
|
+
<FormMessage />
|
|
1478
|
+
</FormItem>
|
|
1479
|
+
)}
|
|
1480
|
+
/>
|
|
1317
1481
|
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
<
|
|
1349
|
-
{t('
|
|
1350
|
-
</
|
|
1351
|
-
<
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
</
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1482
|
+
<FormField
|
|
1483
|
+
control={form.control}
|
|
1484
|
+
name="pagamento.multa"
|
|
1485
|
+
render={({ field }) => (
|
|
1486
|
+
<FormItem>
|
|
1487
|
+
<FormLabel>
|
|
1488
|
+
{t('payment.penaltyLabel')}
|
|
1489
|
+
</FormLabel>
|
|
1490
|
+
<FormControl>
|
|
1491
|
+
<InputMoney
|
|
1492
|
+
ref={field.ref}
|
|
1493
|
+
name={field.name}
|
|
1494
|
+
value={field.value}
|
|
1495
|
+
onBlur={field.onBlur}
|
|
1496
|
+
onValueChange={(value) =>
|
|
1497
|
+
field.onChange(value)
|
|
1498
|
+
}
|
|
1499
|
+
placeholder="0,00"
|
|
1500
|
+
/>
|
|
1501
|
+
</FormControl>
|
|
1502
|
+
<FormMessage />
|
|
1503
|
+
</FormItem>
|
|
1504
|
+
)}
|
|
1505
|
+
/>
|
|
1506
|
+
|
|
1507
|
+
<FormField
|
|
1508
|
+
control={form.control}
|
|
1509
|
+
name="pagamento.desconto"
|
|
1510
|
+
render={({ field }) => (
|
|
1511
|
+
<FormItem>
|
|
1512
|
+
<FormLabel>
|
|
1513
|
+
{t('payment.discountLabel')}
|
|
1514
|
+
</FormLabel>
|
|
1515
|
+
<FormControl>
|
|
1516
|
+
<InputMoney
|
|
1517
|
+
ref={field.ref}
|
|
1518
|
+
name={field.name}
|
|
1519
|
+
value={field.value}
|
|
1520
|
+
onBlur={field.onBlur}
|
|
1521
|
+
onValueChange={(value) =>
|
|
1522
|
+
field.onChange(value)
|
|
1523
|
+
}
|
|
1524
|
+
placeholder="0,00"
|
|
1525
|
+
/>
|
|
1526
|
+
</FormControl>
|
|
1527
|
+
<FormMessage />
|
|
1528
|
+
</FormItem>
|
|
1529
|
+
)}
|
|
1530
|
+
/>
|
|
1531
|
+
</div>
|
|
1532
|
+
) : (
|
|
1533
|
+
<p className="text-xs text-muted-foreground">
|
|
1534
|
+
{t('payment.installmentsHint')}
|
|
1535
|
+
</p>
|
|
1536
|
+
)}
|
|
1537
|
+
</div>
|
|
1538
|
+
)}
|
|
1539
|
+
</div>
|
|
1540
|
+
)}
|
|
1369
1541
|
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
/>
|
|
1542
|
+
<Collapsible
|
|
1543
|
+
open={isConditionOpen}
|
|
1544
|
+
onOpenChange={setIsConditionOpen}
|
|
1545
|
+
className="rounded-lg border border-border/60 bg-background"
|
|
1546
|
+
>
|
|
1547
|
+
<CollapsibleTrigger asChild>
|
|
1548
|
+
<div className="flex cursor-pointer items-center justify-between gap-3 px-4 py-3">
|
|
1549
|
+
<div className="min-w-0 space-y-0.5">
|
|
1550
|
+
<h3 className="text-sm font-semibold text-foreground">
|
|
1551
|
+
{t('sections.paymentCondition.title')}
|
|
1552
|
+
</h3>
|
|
1553
|
+
<p className="truncate text-xs text-muted-foreground">
|
|
1554
|
+
{conditionSummary}
|
|
1555
|
+
</p>
|
|
1556
|
+
</div>
|
|
1557
|
+
{isConditionOpen ? (
|
|
1558
|
+
<ChevronUp className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
1559
|
+
) : (
|
|
1560
|
+
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
1561
|
+
)}
|
|
1562
|
+
</div>
|
|
1563
|
+
</CollapsibleTrigger>
|
|
1564
|
+
|
|
1565
|
+
<CollapsibleContent className="space-y-4 border-t border-border/50 px-4 py-4">
|
|
1566
|
+
<div className="flex flex-wrap gap-2">
|
|
1567
|
+
<Button
|
|
1568
|
+
type="button"
|
|
1569
|
+
variant={condicao === 'avista' ? 'default' : 'outline'}
|
|
1570
|
+
size="sm"
|
|
1571
|
+
onClick={() => {
|
|
1572
|
+
form.setValue('tipoTitulo', 'parcelado');
|
|
1573
|
+
form.setValue('installmentsCount', 1);
|
|
1574
|
+
setIsInstallmentsEdited(false);
|
|
1575
|
+
}}
|
|
1576
|
+
>
|
|
1577
|
+
{t('titleType.cash')}
|
|
1578
|
+
</Button>
|
|
1579
|
+
<Button
|
|
1580
|
+
type="button"
|
|
1581
|
+
variant={condicao === 'parcelado' ? 'default' : 'outline'}
|
|
1582
|
+
size="sm"
|
|
1583
|
+
onClick={() => {
|
|
1584
|
+
form.setValue('tipoTitulo', 'parcelado');
|
|
1585
|
+
if ((form.getValues('installmentsCount') ?? 1) < 2) {
|
|
1586
|
+
form.setValue('installmentsCount', 2);
|
|
1587
|
+
}
|
|
1588
|
+
setIsInstallmentsEdited(false);
|
|
1589
|
+
}}
|
|
1590
|
+
>
|
|
1591
|
+
{t('titleType.installment')}
|
|
1592
|
+
</Button>
|
|
1593
|
+
<Button
|
|
1594
|
+
type="button"
|
|
1595
|
+
variant={
|
|
1596
|
+
condicao === 'recorrente' ? 'default' : 'outline'
|
|
1597
|
+
}
|
|
1598
|
+
size="sm"
|
|
1599
|
+
onClick={() => {
|
|
1600
|
+
form.setValue('tipoTitulo', 'recorrente');
|
|
1601
|
+
form.setValue('jaFoiPago', false);
|
|
1602
|
+
}}
|
|
1603
|
+
>
|
|
1604
|
+
{t('titleType.recurring')}
|
|
1605
|
+
</Button>
|
|
1606
|
+
</div>
|
|
1389
1607
|
|
|
1608
|
+
{condicao === 'parcelado' && (
|
|
1609
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
1390
1610
|
<FormField
|
|
1391
1611
|
control={form.control}
|
|
1392
|
-
name="
|
|
1612
|
+
name="installmentsCount"
|
|
1393
1613
|
render={({ field }) => (
|
|
1394
1614
|
<FormItem>
|
|
1395
1615
|
<FormLabel>
|
|
1396
|
-
{t('
|
|
1616
|
+
{t('installmentsEditor.countLabel')}
|
|
1397
1617
|
</FormLabel>
|
|
1398
1618
|
<FormControl>
|
|
1399
1619
|
<Input
|
|
1400
1620
|
type="number"
|
|
1401
1621
|
min={1}
|
|
1402
|
-
max={
|
|
1403
|
-
{
|
|
1404
|
-
|
|
1405
|
-
|
|
1622
|
+
max={120}
|
|
1623
|
+
value={field.value}
|
|
1624
|
+
onChange={(event) => {
|
|
1625
|
+
const nextValue = Number(
|
|
1626
|
+
event.target.value || 1
|
|
1627
|
+
);
|
|
1406
1628
|
field.onChange(
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
)
|
|
1411
|
-
}
|
|
1629
|
+
Number.isNaN(nextValue) ? 1 : nextValue
|
|
1630
|
+
);
|
|
1631
|
+
}}
|
|
1412
1632
|
/>
|
|
1413
1633
|
</FormControl>
|
|
1414
1634
|
<FormMessage />
|
|
@@ -1416,102 +1636,432 @@ function NovoTituloSheet({
|
|
|
1416
1636
|
)}
|
|
1417
1637
|
/>
|
|
1418
1638
|
</div>
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1639
|
+
)}
|
|
1640
|
+
|
|
1641
|
+
{condicao === 'parcelado' && (
|
|
1642
|
+
<div className="space-y-3 rounded-md border p-3">
|
|
1643
|
+
<div className="flex items-center justify-between gap-2">
|
|
1644
|
+
<p className="text-sm font-medium">
|
|
1645
|
+
{t('installmentsEditor.title')}
|
|
1646
|
+
</p>
|
|
1647
|
+
<Button
|
|
1648
|
+
type="button"
|
|
1649
|
+
variant="outline"
|
|
1650
|
+
size="sm"
|
|
1651
|
+
onClick={() => {
|
|
1652
|
+
setIsInstallmentsEdited(false);
|
|
1653
|
+
replaceInstallments(
|
|
1654
|
+
buildEqualInstallments(
|
|
1655
|
+
form.getValues('installmentsCount'),
|
|
1656
|
+
form.getValues('valor'),
|
|
1657
|
+
form.getValues('vencimento')
|
|
1658
|
+
)
|
|
1659
|
+
);
|
|
1660
|
+
}}
|
|
1661
|
+
>
|
|
1662
|
+
{t('installmentsEditor.recalculate')}
|
|
1663
|
+
</Button>
|
|
1664
|
+
</div>
|
|
1665
|
+
|
|
1666
|
+
<div className="flex items-center gap-2">
|
|
1667
|
+
<Checkbox
|
|
1668
|
+
id="auto-redistribute-installments-receivable"
|
|
1669
|
+
checked={autoRedistributeInstallments}
|
|
1670
|
+
onCheckedChange={(checked) =>
|
|
1671
|
+
setAutoRedistributeInstallments(checked === true)
|
|
1672
|
+
}
|
|
1673
|
+
/>
|
|
1674
|
+
<Label
|
|
1675
|
+
htmlFor="auto-redistribute-installments-receivable"
|
|
1676
|
+
className="text-xs text-muted-foreground"
|
|
1677
|
+
>
|
|
1678
|
+
{t('installmentsEditor.autoRedistributeLabel')}
|
|
1679
|
+
</Label>
|
|
1680
|
+
</div>
|
|
1681
|
+
{autoRedistributeInstallments && (
|
|
1682
|
+
<p className="text-xs text-muted-foreground">
|
|
1683
|
+
{t('installmentsEditor.autoRedistributeHint')}
|
|
1684
|
+
</p>
|
|
1685
|
+
)}
|
|
1686
|
+
|
|
1687
|
+
<div className="space-y-2">
|
|
1688
|
+
{installmentFields.map((installment, index) => (
|
|
1689
|
+
<div
|
|
1690
|
+
key={installment.id}
|
|
1691
|
+
className={`grid grid-cols-1 items-start gap-2 rounded-md border p-2 ${
|
|
1692
|
+
jaFoiPago
|
|
1693
|
+
? 'sm:grid-cols-[64px_1fr_140px_140px_72px]'
|
|
1694
|
+
: 'sm:grid-cols-[96px_1fr_160px]'
|
|
1695
|
+
}`}
|
|
1696
|
+
>
|
|
1697
|
+
<div className="flex items-center text-sm text-muted-foreground">
|
|
1698
|
+
#{index + 1}
|
|
1699
|
+
</div>
|
|
1700
|
+
|
|
1701
|
+
<FormField
|
|
1702
|
+
control={form.control}
|
|
1703
|
+
name={`installments.${index}.dueDate` as const}
|
|
1704
|
+
render={({ field }) => (
|
|
1705
|
+
<FormItem>
|
|
1706
|
+
<FormLabel className="text-xs">
|
|
1707
|
+
{t('installmentsEditor.dueDateLabel')}
|
|
1708
|
+
</FormLabel>
|
|
1709
|
+
<FormControl>
|
|
1710
|
+
<Input
|
|
1711
|
+
type="date"
|
|
1712
|
+
{...field}
|
|
1713
|
+
value={field.value || ''}
|
|
1714
|
+
onChange={(event) => {
|
|
1715
|
+
setIsInstallmentsEdited(true);
|
|
1716
|
+
field.onChange(event);
|
|
1717
|
+
}}
|
|
1718
|
+
/>
|
|
1719
|
+
</FormControl>
|
|
1720
|
+
<FormMessage />
|
|
1721
|
+
</FormItem>
|
|
1722
|
+
)}
|
|
1723
|
+
/>
|
|
1724
|
+
|
|
1725
|
+
<FormField
|
|
1726
|
+
control={form.control}
|
|
1727
|
+
name={`installments.${index}.amount` as const}
|
|
1728
|
+
render={({ field }) => (
|
|
1729
|
+
<FormItem>
|
|
1730
|
+
<FormLabel className="text-xs">
|
|
1731
|
+
{t('installmentsEditor.amountLabel')}
|
|
1732
|
+
</FormLabel>
|
|
1733
|
+
<FormControl>
|
|
1734
|
+
<InputMoney
|
|
1735
|
+
ref={field.ref}
|
|
1736
|
+
name={field.name}
|
|
1737
|
+
value={field.value}
|
|
1738
|
+
onBlur={() => {
|
|
1739
|
+
field.onBlur();
|
|
1740
|
+
|
|
1741
|
+
if (!autoRedistributeInstallments) {
|
|
1742
|
+
return;
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
clearScheduledRedistribution(index);
|
|
1746
|
+
runInstallmentRedistribution(index);
|
|
1747
|
+
}}
|
|
1748
|
+
onValueChange={(value) => {
|
|
1749
|
+
setIsInstallmentsEdited(true);
|
|
1750
|
+
field.onChange(value ?? 0);
|
|
1751
|
+
|
|
1752
|
+
if (!autoRedistributeInstallments) {
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
scheduleInstallmentRedistribution(
|
|
1757
|
+
index
|
|
1758
|
+
);
|
|
1759
|
+
}}
|
|
1760
|
+
placeholder="0,00"
|
|
1761
|
+
/>
|
|
1762
|
+
</FormControl>
|
|
1763
|
+
<FormMessage />
|
|
1764
|
+
</FormItem>
|
|
1765
|
+
)}
|
|
1766
|
+
/>
|
|
1767
|
+
|
|
1768
|
+
{jaFoiPago && (
|
|
1769
|
+
<FormField
|
|
1770
|
+
control={form.control}
|
|
1771
|
+
name={
|
|
1772
|
+
`installments.${index}.dataPagamento` as const
|
|
1773
|
+
}
|
|
1774
|
+
render={({ field }) => (
|
|
1775
|
+
<FormItem>
|
|
1776
|
+
<FormLabel className="text-xs">
|
|
1777
|
+
{t(
|
|
1778
|
+
'installmentsEditor.paymentDateLabel'
|
|
1779
|
+
)}
|
|
1780
|
+
</FormLabel>
|
|
1781
|
+
<FormControl>
|
|
1782
|
+
<Input
|
|
1783
|
+
type="date"
|
|
1784
|
+
{...field}
|
|
1785
|
+
value={field.value || ''}
|
|
1786
|
+
disabled={
|
|
1787
|
+
!watchedInstallments?.[index]?.paga
|
|
1788
|
+
}
|
|
1789
|
+
/>
|
|
1790
|
+
</FormControl>
|
|
1791
|
+
<FormMessage />
|
|
1792
|
+
</FormItem>
|
|
1793
|
+
)}
|
|
1794
|
+
/>
|
|
1795
|
+
)}
|
|
1796
|
+
|
|
1797
|
+
{jaFoiPago && (
|
|
1798
|
+
<FormField
|
|
1799
|
+
control={form.control}
|
|
1800
|
+
name={`installments.${index}.paga` as const}
|
|
1801
|
+
render={({ field }) => (
|
|
1802
|
+
<FormItem>
|
|
1803
|
+
<FormLabel className="text-xs">
|
|
1804
|
+
{t('installmentsEditor.paidLabel')}
|
|
1805
|
+
</FormLabel>
|
|
1806
|
+
<FormControl>
|
|
1807
|
+
<div className="flex h-9 items-center">
|
|
1808
|
+
<Checkbox
|
|
1809
|
+
checked={field.value === true}
|
|
1810
|
+
onCheckedChange={(checked) => {
|
|
1811
|
+
const isPaid = checked === true;
|
|
1812
|
+
field.onChange(isPaid);
|
|
1813
|
+
|
|
1814
|
+
if (
|
|
1815
|
+
isPaid &&
|
|
1816
|
+
!form.getValues(
|
|
1817
|
+
`installments.${index}.dataPagamento`
|
|
1818
|
+
)
|
|
1819
|
+
) {
|
|
1820
|
+
form.setValue(
|
|
1821
|
+
`installments.${index}.dataPagamento`,
|
|
1822
|
+
form.getValues(
|
|
1823
|
+
`installments.${index}.dueDate`
|
|
1824
|
+
) || ''
|
|
1825
|
+
);
|
|
1826
|
+
}
|
|
1827
|
+
}}
|
|
1828
|
+
/>
|
|
1829
|
+
</div>
|
|
1830
|
+
</FormControl>
|
|
1831
|
+
</FormItem>
|
|
1832
|
+
)}
|
|
1833
|
+
/>
|
|
1834
|
+
)}
|
|
1835
|
+
</div>
|
|
1836
|
+
))}
|
|
1837
|
+
</div>
|
|
1838
|
+
|
|
1839
|
+
<p
|
|
1840
|
+
className={`text-xs ${
|
|
1841
|
+
installmentsDiffCents === 0
|
|
1842
|
+
? 'text-muted-foreground'
|
|
1843
|
+
: 'text-destructive'
|
|
1844
|
+
}`}
|
|
1845
|
+
>
|
|
1846
|
+
{t('installmentsEditor.totalPrefix', {
|
|
1847
|
+
total: installmentsTotal.toFixed(2),
|
|
1848
|
+
})}
|
|
1849
|
+
{installmentsDiffCents > 0 &&
|
|
1850
|
+
` ${t('installmentsEditor.adjustmentNeeded')}`}
|
|
1851
|
+
</p>
|
|
1852
|
+
{form.formState.errors.installments?.message && (
|
|
1853
|
+
<p className="text-xs text-destructive">
|
|
1854
|
+
{form.formState.errors.installments.message}
|
|
1855
|
+
</p>
|
|
1856
|
+
)}
|
|
1857
|
+
</div>
|
|
1858
|
+
)}
|
|
1859
|
+
|
|
1860
|
+
{isRecorrente && (
|
|
1861
|
+
<div className="space-y-3 rounded-md border p-3">
|
|
1862
|
+
<p className="text-sm font-medium">
|
|
1863
|
+
{t('recurrenceEditor.title')}
|
|
1864
|
+
</p>
|
|
1865
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
1866
|
+
<FormField
|
|
1867
|
+
control={form.control}
|
|
1868
|
+
name="recorrencia.frequencia"
|
|
1869
|
+
render={({ field }) => (
|
|
1870
|
+
<FormItem>
|
|
1871
|
+
<FormLabel>
|
|
1872
|
+
{t('recurrenceEditor.frequencyLabel')}
|
|
1873
|
+
</FormLabel>
|
|
1874
|
+
<Select
|
|
1875
|
+
value={field.value}
|
|
1876
|
+
onValueChange={field.onChange}
|
|
1877
|
+
>
|
|
1878
|
+
<FormControl>
|
|
1879
|
+
<SelectTrigger className="w-full">
|
|
1880
|
+
<SelectValue />
|
|
1881
|
+
</SelectTrigger>
|
|
1882
|
+
</FormControl>
|
|
1883
|
+
<SelectContent>
|
|
1884
|
+
<SelectItem value="weekly">
|
|
1885
|
+
{t('recurrenceEditor.frequencies.weekly')}
|
|
1886
|
+
</SelectItem>
|
|
1887
|
+
<SelectItem value="biweekly">
|
|
1888
|
+
{t('recurrenceEditor.frequencies.biweekly')}
|
|
1889
|
+
</SelectItem>
|
|
1890
|
+
<SelectItem value="monthly">
|
|
1891
|
+
{t('recurrenceEditor.frequencies.monthly')}
|
|
1892
|
+
</SelectItem>
|
|
1893
|
+
<SelectItem value="bimonthly">
|
|
1894
|
+
{t(
|
|
1895
|
+
'recurrenceEditor.frequencies.bimonthly'
|
|
1896
|
+
)}
|
|
1897
|
+
</SelectItem>
|
|
1898
|
+
<SelectItem value="quarterly">
|
|
1899
|
+
{t(
|
|
1900
|
+
'recurrenceEditor.frequencies.quarterly'
|
|
1901
|
+
)}
|
|
1902
|
+
</SelectItem>
|
|
1903
|
+
<SelectItem value="semiannual">
|
|
1904
|
+
{t(
|
|
1905
|
+
'recurrenceEditor.frequencies.semiannual'
|
|
1906
|
+
)}
|
|
1907
|
+
</SelectItem>
|
|
1908
|
+
<SelectItem value="annual">
|
|
1909
|
+
{t('recurrenceEditor.frequencies.annual')}
|
|
1910
|
+
</SelectItem>
|
|
1911
|
+
</SelectContent>
|
|
1912
|
+
</Select>
|
|
1913
|
+
<FormMessage />
|
|
1914
|
+
</FormItem>
|
|
1915
|
+
)}
|
|
1916
|
+
/>
|
|
1917
|
+
|
|
1918
|
+
<FormField
|
|
1919
|
+
control={form.control}
|
|
1920
|
+
name="recorrencia.dataFim"
|
|
1921
|
+
render={({ field }) => (
|
|
1922
|
+
<FormItem>
|
|
1923
|
+
<FormLabel>
|
|
1924
|
+
{t('recurrenceEditor.endDateLabel')}
|
|
1925
|
+
</FormLabel>
|
|
1926
|
+
<FormControl>
|
|
1927
|
+
<Input
|
|
1928
|
+
type="date"
|
|
1929
|
+
{...field}
|
|
1930
|
+
value={field.value || ''}
|
|
1931
|
+
/>
|
|
1932
|
+
</FormControl>
|
|
1933
|
+
<FormMessage />
|
|
1934
|
+
</FormItem>
|
|
1935
|
+
)}
|
|
1936
|
+
/>
|
|
1937
|
+
|
|
1938
|
+
<FormField
|
|
1939
|
+
control={form.control}
|
|
1940
|
+
name="recorrencia.numOcorrencias"
|
|
1941
|
+
render={({ field }) => (
|
|
1942
|
+
<FormItem>
|
|
1943
|
+
<FormLabel>
|
|
1944
|
+
{t('recurrenceEditor.maxOccurrencesLabel')}
|
|
1945
|
+
</FormLabel>
|
|
1946
|
+
<FormControl>
|
|
1947
|
+
<Input
|
|
1948
|
+
type="number"
|
|
1949
|
+
min={1}
|
|
1950
|
+
max={600}
|
|
1951
|
+
{...field}
|
|
1952
|
+
value={field.value ?? ''}
|
|
1953
|
+
onChange={(e) =>
|
|
1954
|
+
field.onChange(
|
|
1955
|
+
e.target.value === ''
|
|
1956
|
+
? undefined
|
|
1957
|
+
: Number(e.target.value)
|
|
1958
|
+
)
|
|
1959
|
+
}
|
|
1960
|
+
/>
|
|
1961
|
+
</FormControl>
|
|
1962
|
+
<FormMessage />
|
|
1963
|
+
</FormItem>
|
|
1964
|
+
)}
|
|
1965
|
+
/>
|
|
1966
|
+
</div>
|
|
1967
|
+
{form.formState.errors.recorrencia?.message && (
|
|
1968
|
+
<p className="text-xs text-destructive">
|
|
1969
|
+
{form.formState.errors.recorrencia.message}
|
|
1970
|
+
</p>
|
|
1971
|
+
)}
|
|
1972
|
+
</div>
|
|
1973
|
+
)}
|
|
1974
|
+
</CollapsibleContent>
|
|
1975
|
+
</Collapsible>
|
|
1976
|
+
|
|
1977
|
+
<Collapsible
|
|
1978
|
+
open={isDetailsOpen}
|
|
1979
|
+
onOpenChange={setIsDetailsOpen}
|
|
1980
|
+
className="rounded-lg border border-border/60 bg-background"
|
|
1981
|
+
>
|
|
1982
|
+
<CollapsibleTrigger asChild>
|
|
1983
|
+
<div className="flex cursor-pointer items-center justify-between gap-3 px-4 py-3">
|
|
1984
|
+
<div className="min-w-0 space-y-0.5">
|
|
1985
|
+
<h3 className="text-sm font-semibold text-foreground">
|
|
1986
|
+
{t('sections.details.title')}
|
|
1987
|
+
</h3>
|
|
1988
|
+
<p className="truncate text-xs text-muted-foreground">
|
|
1989
|
+
{t('sections.details.description')}
|
|
1422
1990
|
</p>
|
|
1991
|
+
</div>
|
|
1992
|
+
{isDetailsOpen ? (
|
|
1993
|
+
<ChevronUp className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
1994
|
+
) : (
|
|
1995
|
+
<ChevronDown className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
1423
1996
|
)}
|
|
1424
1997
|
</div>
|
|
1425
|
-
|
|
1426
|
-
</FinanceSheetSection>
|
|
1998
|
+
</CollapsibleTrigger>
|
|
1427
1999
|
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
2000
|
+
<CollapsibleContent className="space-y-4 border-t border-border/50 px-4 py-4">
|
|
2001
|
+
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
|
2002
|
+
<FormField
|
|
2003
|
+
control={form.control}
|
|
2004
|
+
name="competencia"
|
|
2005
|
+
render={({ field }) => (
|
|
2006
|
+
<FormItem>
|
|
2007
|
+
<FormLabel>{t('fields.competency')}</FormLabel>
|
|
2008
|
+
<FormControl>
|
|
2009
|
+
<Input
|
|
2010
|
+
type="month"
|
|
2011
|
+
{...field}
|
|
2012
|
+
value={field.value || ''}
|
|
2013
|
+
onChange={(event) => {
|
|
2014
|
+
competenciaEditedRef.current = true;
|
|
2015
|
+
field.onChange(event);
|
|
2016
|
+
}}
|
|
2017
|
+
/>
|
|
2018
|
+
</FormControl>
|
|
2019
|
+
<FormMessage />
|
|
2020
|
+
</FormItem>
|
|
2021
|
+
)}
|
|
2022
|
+
/>
|
|
1442
2023
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
2024
|
+
<CategoryPickerField
|
|
2025
|
+
form={form}
|
|
2026
|
+
name="categoriaId"
|
|
2027
|
+
label={t('fields.category')}
|
|
2028
|
+
selectPlaceholder={t('common.select')}
|
|
2029
|
+
categories={categorias}
|
|
2030
|
+
categoryKind="receita"
|
|
2031
|
+
onCreated={onOptionsUpdated}
|
|
2032
|
+
/>
|
|
2033
|
+
|
|
2034
|
+
<CostCenterPickerField
|
|
2035
|
+
form={form}
|
|
2036
|
+
name="centroCustoId"
|
|
2037
|
+
label={t('fields.costCenter')}
|
|
2038
|
+
selectPlaceholder={t('common.select')}
|
|
2039
|
+
costCenters={centrosCusto}
|
|
2040
|
+
onCreated={onOptionsUpdated}
|
|
2041
|
+
/>
|
|
2042
|
+
|
|
2043
|
+
{!jaFoiPago && renderCanalField()}
|
|
2044
|
+
</div>
|
|
1451
2045
|
|
|
1452
2046
|
<FormField
|
|
1453
2047
|
control={form.control}
|
|
1454
|
-
name="
|
|
2048
|
+
name="descricao"
|
|
1455
2049
|
render={({ field }) => (
|
|
1456
2050
|
<FormItem>
|
|
1457
|
-
<FormLabel>{t('fields.
|
|
1458
|
-
<
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
</SelectTrigger>
|
|
1466
|
-
</FormControl>
|
|
1467
|
-
<SelectContent>
|
|
1468
|
-
<SelectItem value="boleto">
|
|
1469
|
-
{t('channels.boleto')}
|
|
1470
|
-
</SelectItem>
|
|
1471
|
-
<SelectItem value="pix">PIX</SelectItem>
|
|
1472
|
-
<SelectItem value="cartao">
|
|
1473
|
-
{t('channels.card')}
|
|
1474
|
-
</SelectItem>
|
|
1475
|
-
<SelectItem value="transferencia">
|
|
1476
|
-
{t('channels.transfer')}
|
|
1477
|
-
</SelectItem>
|
|
1478
|
-
<SelectItem value="debito_automatico">
|
|
1479
|
-
{t('channels.debitAutomatico')}
|
|
1480
|
-
</SelectItem>
|
|
1481
|
-
<SelectItem value="debito_em_conta">
|
|
1482
|
-
{t('channels.debitEmConta')}
|
|
1483
|
-
</SelectItem>
|
|
1484
|
-
</SelectContent>
|
|
1485
|
-
</Select>
|
|
2051
|
+
<FormLabel>{t('fields.description')}</FormLabel>
|
|
2052
|
+
<FormControl>
|
|
2053
|
+
<Textarea
|
|
2054
|
+
placeholder={t('newTitle.descriptionPlaceholder')}
|
|
2055
|
+
{...field}
|
|
2056
|
+
value={field.value || ''}
|
|
2057
|
+
/>
|
|
2058
|
+
</FormControl>
|
|
1486
2059
|
<FormMessage />
|
|
1487
2060
|
</FormItem>
|
|
1488
2061
|
)}
|
|
1489
2062
|
/>
|
|
1490
|
-
</
|
|
1491
|
-
</
|
|
1492
|
-
|
|
1493
|
-
<FinanceSheetSection
|
|
1494
|
-
title={t('sections.notes.title')}
|
|
1495
|
-
description={t('sections.notes.description')}
|
|
1496
|
-
>
|
|
1497
|
-
<FormField
|
|
1498
|
-
control={form.control}
|
|
1499
|
-
name="descricao"
|
|
1500
|
-
render={({ field }) => (
|
|
1501
|
-
<FormItem>
|
|
1502
|
-
<FormLabel>{t('fields.description')}</FormLabel>
|
|
1503
|
-
<FormControl>
|
|
1504
|
-
<Textarea
|
|
1505
|
-
placeholder={t('newTitle.descriptionPlaceholder')}
|
|
1506
|
-
{...field}
|
|
1507
|
-
value={field.value || ''}
|
|
1508
|
-
/>
|
|
1509
|
-
</FormControl>
|
|
1510
|
-
<FormMessage />
|
|
1511
|
-
</FormItem>
|
|
1512
|
-
)}
|
|
1513
|
-
/>
|
|
1514
|
-
</FinanceSheetSection>
|
|
2063
|
+
</CollapsibleContent>
|
|
2064
|
+
</Collapsible>
|
|
1515
2065
|
</FinanceSheetBody>
|
|
1516
2066
|
|
|
1517
2067
|
<div className="border-t border-border/50 px-4 py-4 sm:px-6">
|
|
@@ -1526,6 +2076,23 @@ function NovoTituloSheet({
|
|
|
1526
2076
|
</Button>
|
|
1527
2077
|
<Button
|
|
1528
2078
|
type="submit"
|
|
2079
|
+
variant="outline"
|
|
2080
|
+
onClick={() => {
|
|
2081
|
+
submitAndNewRef.current = true;
|
|
2082
|
+
}}
|
|
2083
|
+
disabled={
|
|
2084
|
+
form.formState.isSubmitting ||
|
|
2085
|
+
isUploadingFile ||
|
|
2086
|
+
isExtractingFileData
|
|
2087
|
+
}
|
|
2088
|
+
>
|
|
2089
|
+
{t('common.saveAndNew')}
|
|
2090
|
+
</Button>
|
|
2091
|
+
<Button
|
|
2092
|
+
type="submit"
|
|
2093
|
+
onClick={() => {
|
|
2094
|
+
submitAndNewRef.current = false;
|
|
2095
|
+
}}
|
|
1529
2096
|
disabled={
|
|
1530
2097
|
form.formState.isSubmitting ||
|
|
1531
2098
|
isUploadingFile ||
|
|
@@ -1610,25 +2177,7 @@ function EditarTituloSheet({
|
|
|
1610
2177
|
|
|
1611
2178
|
const form = useForm<NewTitleFormValues>({
|
|
1612
2179
|
resolver: zodResolver(newTitleFormSchema),
|
|
1613
|
-
defaultValues:
|
|
1614
|
-
tipoTitulo: 'parcelado',
|
|
1615
|
-
documento: '',
|
|
1616
|
-
clienteId: '',
|
|
1617
|
-
competencia: '',
|
|
1618
|
-
vencimento: '',
|
|
1619
|
-
valor: 0,
|
|
1620
|
-
installmentsCount: 1,
|
|
1621
|
-
installments: [{ dueDate: '', amount: 0 }],
|
|
1622
|
-
recorrencia: {
|
|
1623
|
-
frequencia: 'monthly',
|
|
1624
|
-
dataFim: '',
|
|
1625
|
-
numOcorrencias: undefined,
|
|
1626
|
-
},
|
|
1627
|
-
categoriaId: '',
|
|
1628
|
-
centroCustoId: '',
|
|
1629
|
-
canal: '',
|
|
1630
|
-
descricao: '',
|
|
1631
|
-
},
|
|
2180
|
+
defaultValues: getNewTitleDefaultValues(),
|
|
1632
2181
|
});
|
|
1633
2182
|
|
|
1634
2183
|
const { fields: installmentFields, replace: replaceInstallments } =
|
|
@@ -1665,12 +2214,16 @@ function EditarTituloSheet({
|
|
|
1665
2214
|
installments: watchedFormValues.installments?.map((installment) => ({
|
|
1666
2215
|
dueDate: installment?.dueDate ?? '',
|
|
1667
2216
|
amount: Number(installment?.amount ?? 0),
|
|
1668
|
-
|
|
2217
|
+
paga: installment?.paga ?? false,
|
|
2218
|
+
dataPagamento: installment?.dataPagamento ?? '',
|
|
2219
|
+
})) ?? [{ dueDate: '', amount: 0, paga: false, dataPagamento: '' }],
|
|
1669
2220
|
recorrencia: {
|
|
1670
2221
|
frequencia: watchedFormValues.recorrencia?.frequencia ?? 'monthly',
|
|
1671
2222
|
dataFim: watchedFormValues.recorrencia?.dataFim ?? '',
|
|
1672
2223
|
numOcorrencias: watchedFormValues.recorrencia?.numOcorrencias,
|
|
1673
2224
|
},
|
|
2225
|
+
jaFoiPago: false,
|
|
2226
|
+
pagamento: undefined,
|
|
1674
2227
|
categoriaId: watchedFormValues.categoriaId ?? '',
|
|
1675
2228
|
centroCustoId: watchedFormValues.centroCustoId ?? '',
|
|
1676
2229
|
canal: watchedFormValues.canal ?? '',
|
|
@@ -1762,7 +2315,11 @@ function EditarTituloSheet({
|
|
|
1762
2315
|
String(storedDraft.payload.titleId ?? '') === String(titulo.id ?? '');
|
|
1763
2316
|
|
|
1764
2317
|
if (shouldRestoreDraft) {
|
|
1765
|
-
form.reset(
|
|
2318
|
+
form.reset({
|
|
2319
|
+
...getNewTitleDefaultValues(),
|
|
2320
|
+
...storedDraft.payload.values,
|
|
2321
|
+
jaFoiPago: false,
|
|
2322
|
+
});
|
|
1766
2323
|
setUploadedFileId(storedDraft.payload.uploadedFileId ?? null);
|
|
1767
2324
|
setUploadedFileName(storedDraft.payload.uploadedFileName ?? '');
|
|
1768
2325
|
setExtractionConfidence(null);
|
|
@@ -1791,8 +2348,12 @@ function EditarTituloSheet({
|
|
|
1791
2348
|
|
|
1792
2349
|
const isRecurringTitle = Boolean(titulo.isRecurring);
|
|
1793
2350
|
form.reset({
|
|
2351
|
+
...getNewTitleDefaultValues(),
|
|
1794
2352
|
tipoTitulo: isRecurringTitle ? 'recorrente' : 'parcelado',
|
|
1795
|
-
documento:
|
|
2353
|
+
documento:
|
|
2354
|
+
titulo.documento && titulo.documento !== `TIT-${titulo.id}`
|
|
2355
|
+
? titulo.documento
|
|
2356
|
+
: '',
|
|
1796
2357
|
clienteId: titulo.clienteId || '',
|
|
1797
2358
|
competencia: titulo.competencia || '',
|
|
1798
2359
|
vencimento:
|
|
@@ -2110,7 +2671,7 @@ function EditarTituloSheet({
|
|
|
2110
2671
|
url: `/finance/accounts-receivable/installments/${titulo.id}`,
|
|
2111
2672
|
method: 'PATCH',
|
|
2112
2673
|
data: {
|
|
2113
|
-
document_number: values.documento,
|
|
2674
|
+
document_number: values.documento?.trim() || null,
|
|
2114
2675
|
person_id: Number(values.clienteId),
|
|
2115
2676
|
competence_date: values.competencia
|
|
2116
2677
|
? `${values.competencia}-01`
|
|
@@ -3117,6 +3678,7 @@ export default function TitulosReceberPage() {
|
|
|
3117
3678
|
<NovoTituloSheet
|
|
3118
3679
|
categorias={categorias}
|
|
3119
3680
|
centrosCusto={centrosCusto}
|
|
3681
|
+
contasBancarias={data.contasBancarias || []}
|
|
3120
3682
|
t={t}
|
|
3121
3683
|
open={isCreateSheetOpen}
|
|
3122
3684
|
onOpenChange={setIsCreateSheetOpen}
|