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