@hed-hog/finance 0.0.322 → 0.0.326
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-bank-account.dto.d.ts +1 -0
- package/dist/dto/create-bank-account.dto.d.ts.map +1 -1
- package/dist/dto/create-bank-account.dto.js +7 -0
- package/dist/dto/create-bank-account.dto.js.map +1 -1
- package/dist/dto/update-bank-account.dto.d.ts +1 -0
- package/dist/dto/update-bank-account.dto.d.ts.map +1 -1
- package/dist/dto/update-bank-account.dto.js +7 -0
- package/dist/dto/update-bank-account.dto.js.map +1 -1
- package/dist/finance-bank-accounts.controller.d.ts +21 -0
- package/dist/finance-bank-accounts.controller.d.ts.map +1 -1
- package/dist/finance-data.controller.d.ts +13 -0
- package/dist/finance-data.controller.d.ts.map +1 -1
- package/dist/finance.service.d.ts +37 -2
- package/dist/finance.service.d.ts.map +1 -1
- package/dist/finance.service.js +125 -19
- package/dist/finance.service.js.map +1 -1
- package/hedhog/data/integration_event_catalog.yaml +274 -0
- package/hedhog/frontend/app/administration/categories/page.tsx.ejs +1 -1
- package/hedhog/frontend/app/administration/cost-centers/page.tsx.ejs +1 -1
- package/hedhog/frontend/app/administration/currencies/page.tsx.ejs +1 -1
- package/hedhog/frontend/app/administration/period-close/page.tsx.ejs +1 -1
- package/hedhog/frontend/app/cash-and-banks/bank-accounts/page.tsx.ejs +83 -37
- package/hedhog/frontend/widgets/bank-reconciliation-status.tsx.ejs +33 -9
- package/hedhog/frontend/widgets/cash-balance-kpi.tsx.ejs +30 -9
- package/package.json +7 -7
- package/src/dto/create-bank-account.dto.ts +12 -6
- package/src/dto/update-bank-account.dto.ts +6 -0
- package/src/finance.service.ts +156 -26
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { getLocaleText } from '@hed-hog/api-locale';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
IsDateString,
|
|
4
|
+
IsInt,
|
|
5
|
+
IsNumber,
|
|
6
|
+
IsOptional,
|
|
7
|
+
IsString,
|
|
8
|
+
Min,
|
|
9
9
|
} from 'class-validator';
|
|
10
10
|
|
|
11
11
|
export class CreateBankAccountDto {
|
|
@@ -47,6 +47,12 @@ export class CreateBankAccountDto {
|
|
|
47
47
|
})
|
|
48
48
|
logo_file_id?: number | null;
|
|
49
49
|
|
|
50
|
+
@IsOptional()
|
|
51
|
+
@IsInt({
|
|
52
|
+
message: (args) => getLocaleText('validation.idMustBeInteger', args.value),
|
|
53
|
+
})
|
|
54
|
+
currency_id?: number | null;
|
|
55
|
+
|
|
50
56
|
@IsOptional()
|
|
51
57
|
@IsNumber(
|
|
52
58
|
{},
|
|
@@ -42,6 +42,12 @@ export class UpdateBankAccountDto {
|
|
|
42
42
|
})
|
|
43
43
|
logo_file_id?: number | null;
|
|
44
44
|
|
|
45
|
+
@IsOptional()
|
|
46
|
+
@IsInt({
|
|
47
|
+
message: (args) => getLocaleText('validation.idMustBeInteger', args.value),
|
|
48
|
+
})
|
|
49
|
+
currency_id?: number | null;
|
|
50
|
+
|
|
45
51
|
@IsOptional()
|
|
46
52
|
@IsString({
|
|
47
53
|
message: (args) =>
|
package/src/finance.service.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { getLocaleText } from '@hed-hog/api-locale';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
PageOrderDirection,
|
|
4
|
+
PaginationDTO,
|
|
5
|
+
PaginationService,
|
|
6
6
|
} from '@hed-hog/api-pagination';
|
|
7
7
|
import { PrismaService } from '@hed-hog/api-prisma';
|
|
8
|
-
import { AiService, FileService, SettingService } from '@hed-hog/core';
|
|
8
|
+
import { AiService, FileService, IntegrationDeveloperApiService, SettingService } from '@hed-hog/core';
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
BadRequestException,
|
|
11
|
+
ConflictException,
|
|
12
|
+
forwardRef,
|
|
13
|
+
Inject,
|
|
14
|
+
Injectable,
|
|
15
|
+
Logger,
|
|
16
|
+
NotFoundException,
|
|
17
17
|
} from '@nestjs/common';
|
|
18
18
|
import { createHash } from 'node:crypto';
|
|
19
19
|
import { readFile } from 'node:fs/promises';
|
|
@@ -87,6 +87,8 @@ export class FinanceService {
|
|
|
87
87
|
private readonly settingService: SettingService,
|
|
88
88
|
@Inject(forwardRef(() => FileService))
|
|
89
89
|
private readonly fileService: FileService,
|
|
90
|
+
@Inject(forwardRef(() => IntegrationDeveloperApiService))
|
|
91
|
+
private readonly integrationApi: IntegrationDeveloperApiService,
|
|
90
92
|
) {}
|
|
91
93
|
|
|
92
94
|
async getAgentExtractInfoFromFile(
|
|
@@ -2286,9 +2288,36 @@ export class FinanceService {
|
|
|
2286
2288
|
);
|
|
2287
2289
|
const receivableInstallments = this.extractOpenInstallments(receivables);
|
|
2288
2290
|
|
|
2289
|
-
const
|
|
2290
|
-
|
|
2291
|
-
|
|
2291
|
+
const activeAccounts = (bankAccounts || []).filter(
|
|
2292
|
+
(account) => account?.ativo !== false,
|
|
2293
|
+
);
|
|
2294
|
+
|
|
2295
|
+
const saldoCaixa = activeAccounts.reduce(
|
|
2296
|
+
(acc, account) => acc + Number(account?.saldoAtual || 0),
|
|
2297
|
+
0,
|
|
2298
|
+
);
|
|
2299
|
+
|
|
2300
|
+
const saldoCaixaPorMoeda: Record<
|
|
2301
|
+
string,
|
|
2302
|
+
{ total: number; reconciled: number; symbol: string; name: string }
|
|
2303
|
+
> = {};
|
|
2304
|
+
for (const account of activeAccounts) {
|
|
2305
|
+
const code = account?.currency?.code || 'BRL';
|
|
2306
|
+
const symbol = account?.currency?.symbol || 'R$';
|
|
2307
|
+
const name = account?.currency?.name || 'Real Brasileiro';
|
|
2308
|
+
if (!saldoCaixaPorMoeda[code]) {
|
|
2309
|
+
saldoCaixaPorMoeda[code] = { total: 0, reconciled: 0, symbol, name };
|
|
2310
|
+
}
|
|
2311
|
+
saldoCaixaPorMoeda[code].total = Number(
|
|
2312
|
+
(saldoCaixaPorMoeda[code].total + Number(account?.saldoAtual || 0)).toFixed(2),
|
|
2313
|
+
);
|
|
2314
|
+
saldoCaixaPorMoeda[code].reconciled = Number(
|
|
2315
|
+
(
|
|
2316
|
+
saldoCaixaPorMoeda[code].reconciled +
|
|
2317
|
+
Number(account?.saldoConciliado || 0)
|
|
2318
|
+
).toFixed(2),
|
|
2319
|
+
);
|
|
2320
|
+
}
|
|
2292
2321
|
|
|
2293
2322
|
const aPagar7dias = this.sumInstallmentsDueBetween(
|
|
2294
2323
|
payableInstallments,
|
|
@@ -2318,6 +2347,7 @@ export class FinanceService {
|
|
|
2318
2347
|
|
|
2319
2348
|
return {
|
|
2320
2349
|
saldoCaixa: Number(saldoCaixa.toFixed(2)),
|
|
2350
|
+
saldoCaixaPorMoeda,
|
|
2321
2351
|
aPagar30dias: Number(aPagar30dias.toFixed(2)),
|
|
2322
2352
|
aPagar7dias: Number(aPagar7dias.toFixed(2)),
|
|
2323
2353
|
aReceber30dias: Number(aReceber30dias.toFixed(2)),
|
|
@@ -2794,6 +2824,14 @@ export class FinanceService {
|
|
|
2794
2824
|
description: true,
|
|
2795
2825
|
},
|
|
2796
2826
|
},
|
|
2827
|
+
currency: {
|
|
2828
|
+
select: {
|
|
2829
|
+
id: true,
|
|
2830
|
+
code: true,
|
|
2831
|
+
symbol: true,
|
|
2832
|
+
name: true,
|
|
2833
|
+
},
|
|
2834
|
+
},
|
|
2797
2835
|
},
|
|
2798
2836
|
orderBy: [{ code: 'asc' }, { name: 'asc' }],
|
|
2799
2837
|
},
|
|
@@ -3057,7 +3095,7 @@ export class FinanceService {
|
|
|
3057
3095
|
});
|
|
3058
3096
|
});
|
|
3059
3097
|
|
|
3060
|
-
|
|
3098
|
+
const transferResult = {
|
|
3061
3099
|
id: transferReference.replace('transfer:', ''),
|
|
3062
3100
|
contaOrigemId: String(sourceAccountId),
|
|
3063
3101
|
contaDestinoId: String(destinationAccountId),
|
|
@@ -3065,6 +3103,16 @@ export class FinanceService {
|
|
|
3065
3103
|
valor: amount,
|
|
3066
3104
|
descricao: description,
|
|
3067
3105
|
};
|
|
3106
|
+
|
|
3107
|
+
await this.integrationApi.publishEvent({
|
|
3108
|
+
eventName: 'finance.transfer.created',
|
|
3109
|
+
sourceModule: 'finance',
|
|
3110
|
+
aggregateType: 'transfer',
|
|
3111
|
+
aggregateId: transferResult.id,
|
|
3112
|
+
payload: { id: transferResult.id, sourceAccountId, destinationAccountId, amount, date: postedDate.toISOString() },
|
|
3113
|
+
}).catch(() => null);
|
|
3114
|
+
|
|
3115
|
+
return transferResult;
|
|
3068
3116
|
}
|
|
3069
3117
|
|
|
3070
3118
|
async listCostCenters() {
|
|
@@ -4430,6 +4478,7 @@ export class FinanceService {
|
|
|
4430
4478
|
account_number: data.account || null,
|
|
4431
4479
|
account_type: accountType,
|
|
4432
4480
|
logo_file_id: data.logo_file_id ?? null,
|
|
4481
|
+
currency_id: data.currency_id ?? null,
|
|
4433
4482
|
status: 'active',
|
|
4434
4483
|
},
|
|
4435
4484
|
});
|
|
@@ -4478,10 +4527,28 @@ export class FinanceService {
|
|
|
4478
4527
|
description: true,
|
|
4479
4528
|
},
|
|
4480
4529
|
},
|
|
4530
|
+
currency: {
|
|
4531
|
+
select: {
|
|
4532
|
+
id: true,
|
|
4533
|
+
code: true,
|
|
4534
|
+
symbol: true,
|
|
4535
|
+
name: true,
|
|
4536
|
+
},
|
|
4537
|
+
},
|
|
4481
4538
|
},
|
|
4482
4539
|
});
|
|
4483
4540
|
|
|
4484
|
-
|
|
4541
|
+
const mapped = this.mapBankAccountToFront(account);
|
|
4542
|
+
|
|
4543
|
+
await this.integrationApi.publishEvent({
|
|
4544
|
+
eventName: 'finance.bank_account.created',
|
|
4545
|
+
sourceModule: 'finance',
|
|
4546
|
+
aggregateType: 'bank_account',
|
|
4547
|
+
aggregateId: String(createdAccount.id),
|
|
4548
|
+
payload: { id: createdAccount.id, name, bank: data.bank, accountType: this.mapAccountTypeFromPt(data.type) },
|
|
4549
|
+
}).catch(() => null);
|
|
4550
|
+
|
|
4551
|
+
return mapped;
|
|
4485
4552
|
}
|
|
4486
4553
|
|
|
4487
4554
|
async createCostCenter(data: CreateCostCenterDto) {
|
|
@@ -4495,6 +4562,14 @@ export class FinanceService {
|
|
|
4495
4562
|
},
|
|
4496
4563
|
});
|
|
4497
4564
|
|
|
4565
|
+
await this.integrationApi.publishEvent({
|
|
4566
|
+
eventName: 'finance.cost_center.created',
|
|
4567
|
+
sourceModule: 'finance',
|
|
4568
|
+
aggregateType: 'cost_center',
|
|
4569
|
+
aggregateId: String(created.id),
|
|
4570
|
+
payload: { id: created.id, code, name: data.name.trim() },
|
|
4571
|
+
}).catch(() => null);
|
|
4572
|
+
|
|
4498
4573
|
return this.mapCostCenterToFront(created);
|
|
4499
4574
|
}
|
|
4500
4575
|
|
|
@@ -4577,7 +4652,7 @@ export class FinanceService {
|
|
|
4577
4652
|
throw new NotFoundException('Bank account not found');
|
|
4578
4653
|
}
|
|
4579
4654
|
|
|
4580
|
-
const
|
|
4655
|
+
const updatedBankAccount = await this.prisma.bank_account.update({
|
|
4581
4656
|
where: { id },
|
|
4582
4657
|
data: {
|
|
4583
4658
|
bank_name: data.bank,
|
|
@@ -4587,6 +4662,8 @@ export class FinanceService {
|
|
|
4587
4662
|
account_type: data.type ? this.mapAccountTypeFromPt(data.type) : undefined,
|
|
4588
4663
|
logo_file_id:
|
|
4589
4664
|
data.logo_file_id === undefined ? undefined : data.logo_file_id,
|
|
4665
|
+
currency_id:
|
|
4666
|
+
data.currency_id === undefined ? undefined : data.currency_id,
|
|
4590
4667
|
status: data.status,
|
|
4591
4668
|
},
|
|
4592
4669
|
include: {
|
|
@@ -4598,10 +4675,26 @@ export class FinanceService {
|
|
|
4598
4675
|
description: true,
|
|
4599
4676
|
},
|
|
4600
4677
|
},
|
|
4678
|
+
currency: {
|
|
4679
|
+
select: {
|
|
4680
|
+
id: true,
|
|
4681
|
+
code: true,
|
|
4682
|
+
symbol: true,
|
|
4683
|
+
name: true,
|
|
4684
|
+
},
|
|
4685
|
+
},
|
|
4601
4686
|
},
|
|
4602
4687
|
});
|
|
4603
4688
|
|
|
4604
|
-
|
|
4689
|
+
await this.integrationApi.publishEvent({
|
|
4690
|
+
eventName: 'finance.bank_account.updated',
|
|
4691
|
+
sourceModule: 'finance',
|
|
4692
|
+
aggregateType: 'bank_account',
|
|
4693
|
+
aggregateId: String(id),
|
|
4694
|
+
payload: { id, name: data.description, status: data.status },
|
|
4695
|
+
}).catch(() => null);
|
|
4696
|
+
|
|
4697
|
+
return this.mapBankAccountToFront(updatedBankAccount);
|
|
4605
4698
|
}
|
|
4606
4699
|
|
|
4607
4700
|
async updateCostCenter(id: number, data: UpdateCostCenterDto) {
|
|
@@ -4614,7 +4707,7 @@ export class FinanceService {
|
|
|
4614
4707
|
throw new NotFoundException('Cost center not found');
|
|
4615
4708
|
}
|
|
4616
4709
|
|
|
4617
|
-
const
|
|
4710
|
+
const updatedCostCenter = await this.prisma.cost_center.update({
|
|
4618
4711
|
where: { id },
|
|
4619
4712
|
data: {
|
|
4620
4713
|
name: data.name?.trim(),
|
|
@@ -4622,7 +4715,15 @@ export class FinanceService {
|
|
|
4622
4715
|
},
|
|
4623
4716
|
});
|
|
4624
4717
|
|
|
4625
|
-
|
|
4718
|
+
await this.integrationApi.publishEvent({
|
|
4719
|
+
eventName: 'finance.cost_center.updated',
|
|
4720
|
+
sourceModule: 'finance',
|
|
4721
|
+
aggregateType: 'cost_center',
|
|
4722
|
+
aggregateId: String(id),
|
|
4723
|
+
payload: { id, name: data.name, status: data.status },
|
|
4724
|
+
}).catch(() => null);
|
|
4725
|
+
|
|
4726
|
+
return this.mapCostCenterToFront(updatedCostCenter);
|
|
4626
4727
|
}
|
|
4627
4728
|
|
|
4628
4729
|
async updateFinanceCategory(id: number, data: UpdateFinanceCategoryDto) {
|
|
@@ -4714,11 +4815,17 @@ export class FinanceService {
|
|
|
4714
4815
|
|
|
4715
4816
|
await this.prisma.bank_account.update({
|
|
4716
4817
|
where: { id },
|
|
4717
|
-
data: {
|
|
4718
|
-
status: 'inactive',
|
|
4719
|
-
},
|
|
4818
|
+
data: { status: 'inactive' },
|
|
4720
4819
|
});
|
|
4721
4820
|
|
|
4821
|
+
await this.integrationApi.publishEvent({
|
|
4822
|
+
eventName: 'finance.bank_account.deleted',
|
|
4823
|
+
sourceModule: 'finance',
|
|
4824
|
+
aggregateType: 'bank_account',
|
|
4825
|
+
aggregateId: String(id),
|
|
4826
|
+
payload: { id },
|
|
4827
|
+
}).catch(() => null);
|
|
4828
|
+
|
|
4722
4829
|
return { success: true };
|
|
4723
4830
|
}
|
|
4724
4831
|
|
|
@@ -4734,11 +4841,17 @@ export class FinanceService {
|
|
|
4734
4841
|
|
|
4735
4842
|
await this.prisma.cost_center.update({
|
|
4736
4843
|
where: { id },
|
|
4737
|
-
data: {
|
|
4738
|
-
status: 'inactive',
|
|
4739
|
-
},
|
|
4844
|
+
data: { status: 'inactive' },
|
|
4740
4845
|
});
|
|
4741
4846
|
|
|
4847
|
+
await this.integrationApi.publishEvent({
|
|
4848
|
+
eventName: 'finance.cost_center.deleted',
|
|
4849
|
+
sourceModule: 'finance',
|
|
4850
|
+
aggregateType: 'cost_center',
|
|
4851
|
+
aggregateId: String(id),
|
|
4852
|
+
payload: { id },
|
|
4853
|
+
}).catch(() => null);
|
|
4854
|
+
|
|
4742
4855
|
return { success: true };
|
|
4743
4856
|
}
|
|
4744
4857
|
|
|
@@ -6465,6 +6578,14 @@ export class FinanceService {
|
|
|
6465
6578
|
description: true,
|
|
6466
6579
|
},
|
|
6467
6580
|
},
|
|
6581
|
+
currency: {
|
|
6582
|
+
select: {
|
|
6583
|
+
id: true,
|
|
6584
|
+
code: true,
|
|
6585
|
+
symbol: true,
|
|
6586
|
+
name: true,
|
|
6587
|
+
},
|
|
6588
|
+
},
|
|
6468
6589
|
},
|
|
6469
6590
|
orderBy: [{ code: 'asc' }, { name: 'asc' }],
|
|
6470
6591
|
});
|
|
@@ -7016,6 +7137,15 @@ export class FinanceService {
|
|
|
7016
7137
|
conta: bankAccount.account_number || '-',
|
|
7017
7138
|
tipo: this.mapAccountTypeToPt(bankAccount.account_type),
|
|
7018
7139
|
logoFileId: bankAccount.logo_file_id ?? null,
|
|
7140
|
+
currencyId: bankAccount.currency_id ?? null,
|
|
7141
|
+
currency: bankAccount.currency
|
|
7142
|
+
? {
|
|
7143
|
+
id: String(bankAccount.currency.id),
|
|
7144
|
+
code: bankAccount.currency.code,
|
|
7145
|
+
symbol: bankAccount.currency.symbol,
|
|
7146
|
+
name: bankAccount.currency.name,
|
|
7147
|
+
}
|
|
7148
|
+
: null,
|
|
7019
7149
|
saldoAtual: this.fromCents(currentCents),
|
|
7020
7150
|
saldoConciliado: this.fromCents(reconciledCents),
|
|
7021
7151
|
ativo: bankAccount.status === 'active',
|