@hed-hog/finance 0.0.223 → 0.0.225
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 +19 -0
- package/dist/dto/create-financial-title.dto.d.ts.map +1 -0
- package/dist/dto/create-financial-title.dto.js +128 -0
- package/dist/dto/create-financial-title.dto.js.map +1 -0
- package/dist/finance.controller.d.ts +276 -0
- package/dist/finance.controller.d.ts.map +1 -0
- package/dist/finance.controller.js +110 -0
- package/dist/finance.controller.js.map +1 -0
- package/dist/finance.module.d.ts.map +1 -1
- package/dist/finance.module.js +8 -3
- package/dist/finance.module.js.map +1 -1
- package/dist/finance.service.d.ts +295 -0
- package/dist/finance.service.d.ts.map +1 -0
- package/dist/finance.service.js +416 -0
- package/dist/finance.service.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/hedhog/data/menu.yaml +72 -25
- package/hedhog/data/route.yaml +55 -1
- package/hedhog/frontend/app/_lib/formatters.ts.ejs +20 -0
- package/hedhog/frontend/app/_lib/use-finance-data.ts.ejs +87 -0
- package/hedhog/frontend/app/accounts-payable/approvals/page.tsx.ejs +290 -0
- package/hedhog/frontend/app/accounts-payable/installments/[id]/page.tsx.ejs +410 -0
- package/hedhog/frontend/app/accounts-payable/installments/page.tsx.ejs +388 -0
- package/hedhog/frontend/app/accounts-receivable/collections-default/page.tsx.ejs +423 -0
- package/hedhog/frontend/app/accounts-receivable/installments/[id]/page.tsx.ejs +411 -0
- package/hedhog/frontend/app/accounts-receivable/installments/page.tsx.ejs +385 -0
- package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +296 -0
- package/hedhog/frontend/app/cash-and-banks/bank-reconciliation/page.tsx.ejs +427 -0
- package/hedhog/frontend/app/cash-and-banks/statements/page.tsx.ejs +273 -0
- package/hedhog/frontend/app/cash-and-banks/transfers/page.tsx.ejs +253 -0
- package/hedhog/frontend/app/page.tsx.ejs +338 -17
- package/hedhog/frontend/app/planning/cash-flow-forecast/page.tsx.ejs +298 -0
- package/hedhog/frontend/app/planning/receivables-calendar/page.tsx.ejs +225 -0
- package/hedhog/frontend/app/planning/scenarios/page.tsx.ejs +338 -0
- package/hedhog/frontend/messages/en.json +776 -0
- package/hedhog/frontend/messages/pt.json +776 -0
- package/hedhog/query/constraints.sql +169 -0
- package/package.json +3 -3
- package/src/dto/create-financial-title.dto.ts +142 -0
- package/src/finance.controller.ts +89 -0
- package/src/finance.module.ts +8 -3
- package/src/finance.service.ts +529 -0
- package/src/index.ts +4 -0
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
import { getLocaleText } from '@hed-hog/api-locale';
|
|
2
|
+
import { PaginationDTO, PaginationService } from '@hed-hog/api-pagination';
|
|
3
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
4
|
+
import {
|
|
5
|
+
BadRequestException,
|
|
6
|
+
Injectable,
|
|
7
|
+
NotFoundException,
|
|
8
|
+
} from '@nestjs/common';
|
|
9
|
+
import { CreateFinancialTitleDto } from './dto/create-financial-title.dto';
|
|
10
|
+
|
|
11
|
+
type TitleType = 'payable' | 'receivable';
|
|
12
|
+
|
|
13
|
+
@Injectable()
|
|
14
|
+
export class FinanceService {
|
|
15
|
+
constructor(
|
|
16
|
+
private readonly prisma: PrismaService,
|
|
17
|
+
private readonly paginationService: PaginationService,
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
async getData() {
|
|
21
|
+
const [
|
|
22
|
+
payables,
|
|
23
|
+
receivables,
|
|
24
|
+
people,
|
|
25
|
+
categories,
|
|
26
|
+
costCenters,
|
|
27
|
+
bankAccounts,
|
|
28
|
+
tags,
|
|
29
|
+
auditLogs,
|
|
30
|
+
] = await Promise.all([
|
|
31
|
+
this.loadTitles('payable'),
|
|
32
|
+
this.loadTitles('receivable'),
|
|
33
|
+
this.loadPeople(),
|
|
34
|
+
this.loadCategories(),
|
|
35
|
+
this.loadCostCenters(),
|
|
36
|
+
this.loadBankAccounts(),
|
|
37
|
+
this.loadTags(),
|
|
38
|
+
this.loadAuditLogs(),
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
kpis: {
|
|
43
|
+
saldoCaixa: 0,
|
|
44
|
+
aPagar30dias: 0,
|
|
45
|
+
aPagar7dias: 0,
|
|
46
|
+
aReceber30dias: 0,
|
|
47
|
+
aReceber7dias: 0,
|
|
48
|
+
inadimplencia: 0,
|
|
49
|
+
},
|
|
50
|
+
fluxoCaixaPrevisto: [],
|
|
51
|
+
titulosPagar: payables,
|
|
52
|
+
titulosReceber: receivables,
|
|
53
|
+
extratos: [],
|
|
54
|
+
contasBancarias: bankAccounts,
|
|
55
|
+
pessoas: people,
|
|
56
|
+
categorias: categories,
|
|
57
|
+
centrosCusto: costCenters,
|
|
58
|
+
aprovacoesPendentes: [],
|
|
59
|
+
agingInadimplencia: [],
|
|
60
|
+
cenarios: [],
|
|
61
|
+
transferencias: [],
|
|
62
|
+
tags,
|
|
63
|
+
logsAuditoria: auditLogs,
|
|
64
|
+
recebiveis: [],
|
|
65
|
+
adquirentes: [],
|
|
66
|
+
historicoContatos: [],
|
|
67
|
+
entradasPrevistas: [],
|
|
68
|
+
saidasPrevistas: [],
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async listAccountsPayableInstallments(
|
|
73
|
+
paginationParams: PaginationDTO,
|
|
74
|
+
status?: string,
|
|
75
|
+
) {
|
|
76
|
+
return this.listTitles('payable', paginationParams, status);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async listAccountsReceivableInstallments(
|
|
80
|
+
paginationParams: PaginationDTO,
|
|
81
|
+
status?: string,
|
|
82
|
+
) {
|
|
83
|
+
return this.listTitles('receivable', paginationParams, status);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async getAccountsPayableInstallment(id: number, locale: string) {
|
|
87
|
+
const title = await this.getTitleById(id, 'payable', locale);
|
|
88
|
+
return this.mapTitleToFront(title);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async getAccountsReceivableInstallment(id: number, locale: string) {
|
|
92
|
+
const title = await this.getTitleById(id, 'receivable', locale);
|
|
93
|
+
return this.mapTitleToFront(title);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async createAccountsPayableTitle(
|
|
97
|
+
data: CreateFinancialTitleDto,
|
|
98
|
+
locale: string,
|
|
99
|
+
userId?: number,
|
|
100
|
+
) {
|
|
101
|
+
return this.createTitle(data, 'payable', locale, userId);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async createAccountsReceivableTitle(
|
|
105
|
+
data: CreateFinancialTitleDto,
|
|
106
|
+
locale: string,
|
|
107
|
+
userId?: number,
|
|
108
|
+
) {
|
|
109
|
+
return this.createTitle(data, 'receivable', locale, userId);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private async listTitles(
|
|
113
|
+
titleType: TitleType,
|
|
114
|
+
paginationParams: PaginationDTO,
|
|
115
|
+
status?: string,
|
|
116
|
+
) {
|
|
117
|
+
const prismaStatus = this.mapStatusFromPt(status);
|
|
118
|
+
const where: any = {
|
|
119
|
+
title_type: titleType,
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
if (prismaStatus) {
|
|
123
|
+
where.status = prismaStatus;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return this.paginationService.paginate(
|
|
127
|
+
this.prisma.financial_title,
|
|
128
|
+
paginationParams,
|
|
129
|
+
{
|
|
130
|
+
where,
|
|
131
|
+
include: this.defaultTitleInclude(),
|
|
132
|
+
orderBy: { created_at: 'desc' },
|
|
133
|
+
},
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private async getTitleById(id: number, titleType: TitleType, locale: string) {
|
|
138
|
+
const title = await this.prisma.financial_title.findFirst({
|
|
139
|
+
where: {
|
|
140
|
+
id,
|
|
141
|
+
title_type: titleType,
|
|
142
|
+
},
|
|
143
|
+
include: this.defaultTitleInclude(),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
if (!title) {
|
|
147
|
+
throw new NotFoundException(
|
|
148
|
+
getLocaleText(
|
|
149
|
+
'itemNotFound',
|
|
150
|
+
locale,
|
|
151
|
+
`Financial title with ID ${id} not found`,
|
|
152
|
+
).replace('{{item}}', 'Financial title'),
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return title;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
private async createTitle(
|
|
160
|
+
data: CreateFinancialTitleDto,
|
|
161
|
+
titleType: TitleType,
|
|
162
|
+
locale: string,
|
|
163
|
+
userId?: number,
|
|
164
|
+
) {
|
|
165
|
+
const person = await this.prisma.person.findUnique({
|
|
166
|
+
where: { id: data.person_id },
|
|
167
|
+
select: { id: true },
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (!person) {
|
|
171
|
+
throw new BadRequestException(
|
|
172
|
+
getLocaleText('personNotFound', locale, 'Person not found'),
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (data.finance_category_id) {
|
|
177
|
+
const category = await this.prisma.finance_category.findUnique({
|
|
178
|
+
where: { id: data.finance_category_id },
|
|
179
|
+
select: { id: true },
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (!category) {
|
|
183
|
+
throw new BadRequestException(
|
|
184
|
+
getLocaleText('categoryNotFound', locale, 'Category not found'),
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (data.cost_center_id) {
|
|
190
|
+
const costCenter = await this.prisma.cost_center.findUnique({
|
|
191
|
+
where: { id: data.cost_center_id },
|
|
192
|
+
select: { id: true },
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
if (!costCenter) {
|
|
196
|
+
throw new BadRequestException(
|
|
197
|
+
getLocaleText('costCenterNotFound', locale, 'Cost center not found'),
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const installments =
|
|
203
|
+
data.installments && data.installments.length > 0
|
|
204
|
+
? data.installments
|
|
205
|
+
: [
|
|
206
|
+
{
|
|
207
|
+
installment_number: 1,
|
|
208
|
+
due_date: data.due_date,
|
|
209
|
+
amount: data.total_amount,
|
|
210
|
+
},
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
const title = await this.prisma.financial_title.create({
|
|
214
|
+
data: {
|
|
215
|
+
person_id: data.person_id,
|
|
216
|
+
title_type: titleType,
|
|
217
|
+
status: 'open',
|
|
218
|
+
document_number: data.document_number,
|
|
219
|
+
description: data.description,
|
|
220
|
+
competence_date: data.competence_date
|
|
221
|
+
? new Date(data.competence_date)
|
|
222
|
+
: null,
|
|
223
|
+
issue_date: data.issue_date ? new Date(data.issue_date) : null,
|
|
224
|
+
total_amount_cents: this.toCents(data.total_amount),
|
|
225
|
+
finance_category_id: data.finance_category_id,
|
|
226
|
+
created_by_user_id: userId,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
for (let index = 0; index < installments.length; index++) {
|
|
231
|
+
const installment = installments[index];
|
|
232
|
+
const amountCents = this.toCents(installment.amount);
|
|
233
|
+
|
|
234
|
+
const createdInstallment = await this.prisma.financial_installment.create({
|
|
235
|
+
data: {
|
|
236
|
+
title_id: title.id,
|
|
237
|
+
installment_number: installment.installment_number || index + 1,
|
|
238
|
+
competence_date: data.competence_date
|
|
239
|
+
? new Date(data.competence_date)
|
|
240
|
+
: new Date(installment.due_date),
|
|
241
|
+
due_date: new Date(installment.due_date),
|
|
242
|
+
amount_cents: amountCents,
|
|
243
|
+
open_amount_cents: amountCents,
|
|
244
|
+
status: 'open',
|
|
245
|
+
notes: data.description,
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
if (data.cost_center_id) {
|
|
250
|
+
await this.prisma.installment_allocation.create({
|
|
251
|
+
data: {
|
|
252
|
+
installment_id: createdInstallment.id,
|
|
253
|
+
cost_center_id: data.cost_center_id,
|
|
254
|
+
allocated_amount_cents: amountCents,
|
|
255
|
+
},
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const createdTitle = await this.getTitleById(title.id, titleType, locale);
|
|
261
|
+
return this.mapTitleToFront(createdTitle, data.payment_channel);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private async loadTitles(type: TitleType) {
|
|
265
|
+
const titles = await this.prisma.financial_title.findMany({
|
|
266
|
+
where: { title_type: type },
|
|
267
|
+
include: this.defaultTitleInclude(),
|
|
268
|
+
orderBy: { created_at: 'desc' },
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return titles.map((title) => this.mapTitleToFront(title));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
private async loadPeople() {
|
|
275
|
+
const people = await this.prisma.person.findMany({
|
|
276
|
+
include: {
|
|
277
|
+
document: {
|
|
278
|
+
select: {
|
|
279
|
+
value: true,
|
|
280
|
+
},
|
|
281
|
+
take: 1,
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
orderBy: { name: 'asc' },
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
return people.map((person) => ({
|
|
288
|
+
id: String(person.id),
|
|
289
|
+
nome: person.name,
|
|
290
|
+
tipo: 'ambos',
|
|
291
|
+
documento: person.document[0]?.value || '',
|
|
292
|
+
}));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private async loadCategories() {
|
|
296
|
+
const categories = await this.prisma.finance_category.findMany({
|
|
297
|
+
orderBy: [{ code: 'asc' }, { name: 'asc' }],
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
return categories.map((category) => ({
|
|
301
|
+
id: String(category.id),
|
|
302
|
+
codigo: category.code,
|
|
303
|
+
nome: category.name,
|
|
304
|
+
natureza:
|
|
305
|
+
category.kind === 'revenue'
|
|
306
|
+
? 'receita'
|
|
307
|
+
: category.kind === 'expense'
|
|
308
|
+
? 'despesa'
|
|
309
|
+
: category.kind,
|
|
310
|
+
status: category.status,
|
|
311
|
+
}));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
private async loadCostCenters() {
|
|
315
|
+
const costCenters = await this.prisma.cost_center.findMany({
|
|
316
|
+
orderBy: [{ code: 'asc' }, { name: 'asc' }],
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
return costCenters.map((costCenter) => ({
|
|
320
|
+
id: String(costCenter.id),
|
|
321
|
+
codigo: costCenter.code,
|
|
322
|
+
nome: costCenter.name,
|
|
323
|
+
status: costCenter.status,
|
|
324
|
+
}));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
private async loadBankAccounts() {
|
|
328
|
+
const bankAccounts = await this.prisma.bank_account.findMany({
|
|
329
|
+
orderBy: [{ code: 'asc' }, { name: 'asc' }],
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
return bankAccounts.map((bankAccount) => ({
|
|
333
|
+
id: String(bankAccount.id),
|
|
334
|
+
codigo: bankAccount.code,
|
|
335
|
+
descricao: bankAccount.name,
|
|
336
|
+
banco: bankAccount.bank_name,
|
|
337
|
+
agencia: bankAccount.agency,
|
|
338
|
+
conta: bankAccount.account_number,
|
|
339
|
+
ativo: bankAccount.status === 'active',
|
|
340
|
+
}));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
private async loadTags() {
|
|
344
|
+
const tags = await this.prisma.tag.findMany({
|
|
345
|
+
orderBy: { slug: 'asc' },
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return tags.map((tag) => ({
|
|
349
|
+
id: String(tag.id),
|
|
350
|
+
nome: tag.slug,
|
|
351
|
+
cor: tag.color,
|
|
352
|
+
}));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
private async loadAuditLogs() {
|
|
356
|
+
const logs = await this.prisma.audit_log.findMany({
|
|
357
|
+
orderBy: { created_at: 'desc' },
|
|
358
|
+
take: 500,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
return logs.map((log) => ({
|
|
362
|
+
id: String(log.id),
|
|
363
|
+
entidade: log.entity_table === 'financial_title' ? 'TituloPagar' : log.entity_table,
|
|
364
|
+
entidadeId: log.entity_id,
|
|
365
|
+
usuarioId: log.actor_user_id ? String(log.actor_user_id) : null,
|
|
366
|
+
acao: log.action,
|
|
367
|
+
detalhes: log.summary,
|
|
368
|
+
antes: log.before_data,
|
|
369
|
+
depois: log.after_data,
|
|
370
|
+
data: log.created_at.toISOString(),
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
private mapTitleToFront(title: any, paymentChannelOverride?: string) {
|
|
375
|
+
const allocations = title.financial_installment.flatMap(
|
|
376
|
+
(installment) => installment.installment_allocation,
|
|
377
|
+
);
|
|
378
|
+
const firstCostCenter = allocations[0]?.cost_center_id;
|
|
379
|
+
|
|
380
|
+
const tags = [
|
|
381
|
+
...new Set(
|
|
382
|
+
title.financial_installment
|
|
383
|
+
.flatMap((installment) => installment.financial_installment_tag)
|
|
384
|
+
.map((tagRelation) => String(tagRelation.tag_id)),
|
|
385
|
+
),
|
|
386
|
+
];
|
|
387
|
+
|
|
388
|
+
const channelFromSettlement = title.financial_installment
|
|
389
|
+
.flatMap((installment) => installment.settlement_allocation)
|
|
390
|
+
.map((allocation) => allocation.settlement?.payment_method?.type)
|
|
391
|
+
.find(Boolean);
|
|
392
|
+
|
|
393
|
+
const mappedInstallments = title.financial_installment.map((installment) => ({
|
|
394
|
+
id: String(installment.id),
|
|
395
|
+
numero: installment.installment_number,
|
|
396
|
+
vencimento: installment.due_date.toISOString(),
|
|
397
|
+
valor: this.fromCents(installment.amount_cents),
|
|
398
|
+
status: this.mapStatusToPt(installment.status),
|
|
399
|
+
metodoPagamento:
|
|
400
|
+
this.mapPaymentMethodToPt(
|
|
401
|
+
installment.settlement_allocation[0]?.settlement?.payment_method?.type,
|
|
402
|
+
) || paymentChannelOverride || 'transferencia',
|
|
403
|
+
liquidacoes: installment.settlement_allocation.map((allocation) => ({
|
|
404
|
+
id: String(allocation.id),
|
|
405
|
+
data: allocation.settlement?.settled_at?.toISOString(),
|
|
406
|
+
valor: this.fromCents(allocation.allocated_amount_cents),
|
|
407
|
+
juros: this.fromCents(allocation.interest_cents || 0),
|
|
408
|
+
desconto: this.fromCents(allocation.discount_cents || 0),
|
|
409
|
+
multa: this.fromCents(allocation.penalty_cents || 0),
|
|
410
|
+
contaBancariaId: allocation.settlement?.bank_account_id
|
|
411
|
+
? String(allocation.settlement.bank_account_id)
|
|
412
|
+
: null,
|
|
413
|
+
metodo:
|
|
414
|
+
this.mapPaymentMethodToPt(
|
|
415
|
+
allocation.settlement?.payment_method?.type,
|
|
416
|
+
) || 'transferencia',
|
|
417
|
+
})),
|
|
418
|
+
}));
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
id: String(title.id),
|
|
422
|
+
documento: title.document_number || `TIT-${title.id}`,
|
|
423
|
+
descricao: title.description || '',
|
|
424
|
+
competencia: title.competence_date
|
|
425
|
+
? title.competence_date.toISOString().slice(0, 7)
|
|
426
|
+
: '',
|
|
427
|
+
valorTotal: this.fromCents(title.total_amount_cents),
|
|
428
|
+
status: this.mapStatusToPt(title.status),
|
|
429
|
+
criadoEm: title.created_at.toISOString(),
|
|
430
|
+
categoriaId: title.finance_category_id ? String(title.finance_category_id) : null,
|
|
431
|
+
centroCustoId: firstCostCenter ? String(firstCostCenter) : null,
|
|
432
|
+
anexos: title.financial_title_attachment.map(
|
|
433
|
+
(attachment) => attachment.file?.filename || attachment.file?.path,
|
|
434
|
+
),
|
|
435
|
+
tags,
|
|
436
|
+
parcelas: mappedInstallments,
|
|
437
|
+
canal:
|
|
438
|
+
this.mapPaymentMethodToPt(channelFromSettlement) ||
|
|
439
|
+
paymentChannelOverride ||
|
|
440
|
+
'transferencia',
|
|
441
|
+
...(title.title_type === 'payable'
|
|
442
|
+
? { fornecedorId: String(title.person_id) }
|
|
443
|
+
: { clienteId: String(title.person_id) }),
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
private defaultTitleInclude() {
|
|
448
|
+
return {
|
|
449
|
+
person: true,
|
|
450
|
+
financial_title_attachment: {
|
|
451
|
+
include: {
|
|
452
|
+
file: true,
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
financial_installment: {
|
|
456
|
+
include: {
|
|
457
|
+
installment_allocation: true,
|
|
458
|
+
financial_installment_tag: true,
|
|
459
|
+
settlement_allocation: {
|
|
460
|
+
include: {
|
|
461
|
+
settlement: {
|
|
462
|
+
include: {
|
|
463
|
+
payment_method: true,
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
orderBy: {
|
|
470
|
+
installment_number: 'asc' as const,
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
private mapStatusToPt(status?: string | null) {
|
|
477
|
+
const statusMap = {
|
|
478
|
+
draft: 'rascunho',
|
|
479
|
+
approved: 'aprovado',
|
|
480
|
+
open: 'aberto',
|
|
481
|
+
partial: 'parcial',
|
|
482
|
+
settled: 'liquidado',
|
|
483
|
+
canceled: 'cancelado',
|
|
484
|
+
overdue: 'vencido',
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
return statusMap[status] || 'aberto';
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private mapStatusFromPt(status?: string) {
|
|
491
|
+
if (!status || status === 'all') {
|
|
492
|
+
return undefined;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const statusMap = {
|
|
496
|
+
rascunho: 'draft',
|
|
497
|
+
aprovado: 'approved',
|
|
498
|
+
aberto: 'open',
|
|
499
|
+
parcial: 'partial',
|
|
500
|
+
liquidado: 'settled',
|
|
501
|
+
cancelado: 'canceled',
|
|
502
|
+
vencido: 'overdue',
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
return statusMap[status];
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
private mapPaymentMethodToPt(paymentMethodType?: string | null) {
|
|
509
|
+
const paymentMethodMap = {
|
|
510
|
+
boleto: 'boleto',
|
|
511
|
+
pix: 'pix',
|
|
512
|
+
ted: 'transferencia',
|
|
513
|
+
doc: 'transferencia',
|
|
514
|
+
card: 'cartao',
|
|
515
|
+
cash: 'dinheiro',
|
|
516
|
+
other: 'transferencia',
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
return paymentMethodMap[paymentMethodType] || undefined;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
private toCents(value: number) {
|
|
523
|
+
return Math.round(value * 100);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
private fromCents(value: number) {
|
|
527
|
+
return Number((value / 100).toFixed(2));
|
|
528
|
+
}
|
|
529
|
+
}
|